UNPKG

ox

Version:

Ethereum Standard Library

241 lines (232 loc) 8.49 kB
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 }