You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
241 lines
8.3 KiB
241 lines
8.3 KiB
import type * as Address from './Address.js'
|
|
import type * as Errors from './Errors.js'
|
|
import * as Hex from './Hex.js'
|
|
import type { Compute } from './internal/types.js'
|
|
|
|
/** A Log as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/main/src/schemas/receipt.yaml). */
|
|
export type Log<
|
|
pending extends boolean = false,
|
|
bigintType = bigint,
|
|
numberType = number,
|
|
> = Compute<{
|
|
/** The address from which this log originated */
|
|
address: Address.Address
|
|
/** Hash of block containing this log or `null` if pending */
|
|
blockHash: pending extends true ? null : Hex.Hex
|
|
/** Number of block containing this log or `null` if pending */
|
|
blockNumber: pending extends true ? null : bigintType
|
|
/** Contains the non-integered arguments of the log */
|
|
data: Hex.Hex
|
|
/** Index of this log within its block or `null` if pending */
|
|
logIndex: pending extends true ? null : numberType
|
|
/** List of topics associated with this log */
|
|
topics: [Hex.Hex, ...(readonly Hex.Hex[])]
|
|
/** Hash of the transaction that created this log or `null` if pending */
|
|
transactionHash: pending extends true ? null : Hex.Hex
|
|
/** Index of the transaction that created this log or `null` if pending */
|
|
transactionIndex: pending extends true ? null : numberType
|
|
/** `true` if this filter has been destroyed and is invalid */
|
|
removed: boolean
|
|
}>
|
|
|
|
/** An RPC Log as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/main/src/schemas/receipt.yaml). */
|
|
export type Rpc<pending extends boolean = false> = Log<
|
|
pending,
|
|
Hex.Hex,
|
|
Hex.Hex
|
|
>
|
|
|
|
/**
|
|
* Converts a {@link ox#Log.Rpc} to an {@link ox#Log.Log}.
|
|
*
|
|
* @example
|
|
* ```ts twoslash
|
|
* import { Log } from 'ox'
|
|
*
|
|
* const log = Log.fromRpc({
|
|
* address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
|
|
* topics: [
|
|
* '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
|
|
* '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
* '0x0000000000000000000000000c04d9e9278ec5e4d424476d3ebec70cb5d648d1',
|
|
* '0x000000000000000000000000000000000000000000000000000000000000025b',
|
|
* ],
|
|
* data: '0x',
|
|
* blockHash:
|
|
* '0xabe69134e80a12f6a93d0aa18215b5b86c2fb338bae911790ca374a8716e01a4',
|
|
* blockNumber: '0x12d846c',
|
|
* transactionHash:
|
|
* '0xcfa52db0bc2cb5bdcb2c5bd8816df7a2f018a0e3964ab1ef4d794cf327966e93',
|
|
* transactionIndex: '0x91',
|
|
* logIndex: '0x10f',
|
|
* removed: false,
|
|
* })
|
|
* // @log: {
|
|
* // @log: address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
|
|
* // @log: blockHash: '0xabe69134e80a12f6a93d0aa18215b5b86c2fb338bae911790ca374a8716e01a4',
|
|
* // @log: blockNumber: 19760236n,
|
|
* // @log: data: '0x',
|
|
* // @log: logIndex: 271,
|
|
* // @log: removed: false,
|
|
* // @log: topics: [
|
|
* // @log: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
|
|
* // @log: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
* // @log: "0x0000000000000000000000000c04d9e9278ec5e4d424476d3ebec70cb5d648d1",
|
|
* // @log: "0x000000000000000000000000000000000000000000000000000000000000025b",
|
|
* // @log: transactionHash:
|
|
* // @log: '0xcfa52db0bc2cb5bdcb2c5bd8816df7a2f018a0e3964ab1ef4d794cf327966e93',
|
|
* // @log: transactionIndex: 145,
|
|
* // @log: }
|
|
* ```
|
|
*
|
|
* @example
|
|
* ### End-to-end
|
|
*
|
|
* Below is an example of how to use `Log.fromRpc` to instantiate a {@link ox#Log.Log} from an RPC log.
|
|
*
|
|
* ```ts twoslash
|
|
* import 'ox/window'
|
|
* import { AbiEvent, Hex, Log } from 'ox'
|
|
*
|
|
* const transfer = AbiEvent.from(
|
|
* 'event Transfer(address indexed from, address indexed to, uint256 indexed value)',
|
|
* )
|
|
*
|
|
* const { topics } = AbiEvent.encode(transfer)
|
|
*
|
|
* const logs = await window.ethereum!.request({
|
|
* method: 'eth_getLogs',
|
|
* params: [
|
|
* {
|
|
* address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
|
|
* fromBlock: Hex.fromNumber(19760235n),
|
|
* toBlock: Hex.fromNumber(19760240n),
|
|
* topics,
|
|
* },
|
|
* ],
|
|
* })
|
|
*
|
|
* const log = Log.fromRpc(logs[0]) // [!code focus]
|
|
* // @log: {
|
|
* // @log: address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
|
|
* // @log: blockHash: '0xabe69134e80a12f6a93d0aa18215b5b86c2fb338bae911790ca374a8716e01a4',
|
|
* // @log: blockNumber: 19760236n,
|
|
* // @log: data: '0x',
|
|
* // @log: logIndex: 271,
|
|
* // @log: removed: false,
|
|
* // @log: topics: [
|
|
* // @log: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
|
|
* // @log: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
* // @log: "0x0000000000000000000000000c04d9e9278ec5e4d424476d3ebec70cb5d648d1",
|
|
* // @log: "0x000000000000000000000000000000000000000000000000000000000000025b",
|
|
* // @log: transactionHash:
|
|
* // @log: '0xcfa52db0bc2cb5bdcb2c5bd8816df7a2f018a0e3964ab1ef4d794cf327966e93',
|
|
* // @log: transactionIndex: 145,
|
|
* // @log: }
|
|
* ```
|
|
*
|
|
* :::note
|
|
*
|
|
* For simplicity, the above example uses `window.ethereum.request`, but you can use any
|
|
* type of JSON-RPC interface.
|
|
*
|
|
* :::
|
|
*
|
|
* @param log - The RPC log to convert.
|
|
* @returns An instantiated {@link ox#Log.Log}.
|
|
*/
|
|
export function fromRpc<
|
|
const log extends Rpc<boolean>,
|
|
pending extends boolean = false,
|
|
>(
|
|
log: log | Rpc<boolean>,
|
|
_options: fromRpc.Options<pending> = {},
|
|
): Log<pending> {
|
|
return {
|
|
...log,
|
|
blockNumber: log.blockNumber ? BigInt(log.blockNumber) : null,
|
|
logIndex: log.logIndex ? Number(log.logIndex) : null,
|
|
transactionIndex: log.transactionIndex
|
|
? Number(log.transactionIndex)
|
|
: null,
|
|
} as Log<pending>
|
|
}
|
|
|
|
export declare namespace fromRpc {
|
|
type Options<pending extends boolean = false> = {
|
|
pending?: pending | boolean | undefined
|
|
}
|
|
|
|
type ErrorType = Errors.GlobalErrorType
|
|
}
|
|
|
|
/**
|
|
* Converts a {@link ox#Log.Log} to a {@link ox#Log.Rpc}.
|
|
*
|
|
* @example
|
|
* ```ts twoslash
|
|
* import { Log } from 'ox'
|
|
*
|
|
* const log = Log.toRpc({
|
|
* address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
|
|
* blockHash:
|
|
* '0xabe69134e80a12f6a93d0aa18215b5b86c2fb338bae911790ca374a8716e01a4',
|
|
* blockNumber: 19760236n,
|
|
* data: '0x',
|
|
* logIndex: 271,
|
|
* removed: false,
|
|
* topics: [
|
|
* '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
|
|
* '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
* '0x0000000000000000000000000c04d9e9278ec5e4d424476d3ebec70cb5d648d1',
|
|
* '0x000000000000000000000000000000000000000000000000000000000000025b',
|
|
* ],
|
|
* transactionHash:
|
|
* '0xcfa52db0bc2cb5bdcb2c5bd8816df7a2f018a0e3964ab1ef4d794cf327966e93',
|
|
* transactionIndex: 145,
|
|
* })
|
|
* // @log: {
|
|
* // @log: address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
|
|
* // @log: blockHash: '0xabe69134e80a12f6a93d0aa18215b5b86c2fb338bae911790ca374a8716e01a4',
|
|
* // @log: blockNumber: '0x012d846c',
|
|
* // @log: data: '0x',
|
|
* // @log: logIndex: '0x010f',
|
|
* // @log: removed: false,
|
|
* // @log: topics: [
|
|
* // @log: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
|
|
* // @log: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
* // @log: '0x0000000000000000000000000c04d9e9278ec5e4d424476d3ebec70cb5d648d1',
|
|
* // @log: '0x000000000000000000000000000000000000000000000000000000000000025b',
|
|
* // @log: ],
|
|
* // @log: transactionHash:
|
|
* // @log: '0xcfa52db0bc2cb5bdcb2c5bd8816df7a2f018a0e3964ab1ef4d794cf327966e93',
|
|
* // @log: transactionIndex: '0x91',
|
|
* // @log: }
|
|
* ```
|
|
*
|
|
* @param log - The log to convert.
|
|
* @returns An RPC log.
|
|
*/
|
|
export function toRpc<
|
|
const log extends Log<boolean>,
|
|
pending extends boolean = false,
|
|
>(log: log, _options: toRpc.Options<pending> = {}): Rpc<pending> {
|
|
return {
|
|
address: log.address,
|
|
blockHash: log.blockHash,
|
|
blockNumber:
|
|
typeof log.blockNumber === 'bigint'
|
|
? Hex.fromNumber(log.blockNumber)
|
|
: null,
|
|
data: log.data,
|
|
logIndex:
|
|
typeof log.logIndex === 'number' ? Hex.fromNumber(log.logIndex) : null,
|
|
topics: log.topics,
|
|
transactionHash: log.transactionHash,
|
|
transactionIndex:
|
|
typeof log.transactionIndex === 'number'
|
|
? Hex.fromNumber(log.transactionIndex)
|
|
: null,
|
|
removed: log.removed,
|
|
} as Rpc as never
|
|
}
|
|
|
|
export declare namespace toRpc {
|
|
type Options<pending extends boolean = false> = {
|
|
pending?: pending | boolean | undefined
|
|
}
|
|
|
|
type ErrorType = Errors.GlobalErrorType
|
|
}
|