UNPKG

ox

Version:

Ethereum Standard Library

334 lines (318 loc) 13.5 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' import * as Log from './Log.js' /** An Transaction Receipt as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/main/src/schemas/receipt.yaml). */ export type TransactionReceipt< status = Status, type = Type, bigintType = bigint, numberType = number, > = Compute<{ /** The actual value per gas deducted from the sender's account for blob gas. Only specified for blob transactions as defined by EIP-4844. */ blobGasPrice?: bigintType | undefined /** The amount of blob gas used. Only specified for blob transactions as defined by EIP-4844. */ blobGasUsed?: bigintType | undefined /** Hash of block containing this transaction */ blockHash: Hex.Hex /** Number of block containing this transaction */ blockNumber: bigintType /** Address of new contract or `null` if no contract was created */ contractAddress?: Address.Address | null | undefined /** Gas used by this and all preceding transactions in this block */ cumulativeGasUsed: bigintType /** Pre-London, it is equal to the transaction's gasPrice. Post-London, it is equal to the actual gas price paid for inclusion. */ effectiveGasPrice: bigintType /** Transaction sender */ from: Address.Address /** Gas used by this transaction */ gasUsed: bigintType /** List of log objects generated by this transaction */ logs: Log.Log<false, bigintType, numberType>[] /** Logs bloom filter */ logsBloom: Hex.Hex /** The post-transaction state root. Only specified for transactions included before the Byzantium upgrade. */ root?: Hex.Hex | undefined /** `success` if this transaction was successful or `reverted` if it failed */ status: status /** Transaction recipient or `null` if deploying a contract */ to: Address.Address | null /** Hash of this transaction */ transactionHash: Hex.Hex /** Index of this transaction in the block */ transactionIndex: numberType /** Transaction type */ type: type }> /** An RPC Transaction Receipt as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/main/src/schemas/receipt.yaml). */ export type Rpc = TransactionReceipt<RpcStatus, RpcType, Hex.Hex, Hex.Hex> /** * Union of Transaction Receipt statuses. * * - `success` * - `reverted` */ export type Status = 'success' | 'reverted' /** * Union of RPC Transaction Receipt statuses. * * - `0x0` * - `0x1` */ export type RpcStatus = '0x0' | '0x1' /** * Union of Transaction Receipt types. * * - `legacy` * - `eip1559` * - `eip2930` * - `eip4844` * - `eip7702` * - any other string */ export type Type = | 'legacy' | 'eip1559' | 'eip2930' | 'eip4844' | 'eip7702' | (string & {}) /** * Union of RPC Transaction Receipt types. * * - `0x0`: legacy transactions * - `0x1`: EIP-1559 transactions * - `0x2`: EIP-2930 transactions * - `0x3`: EIP-4844 transactions * - `0x4`: EIP-7702 transactions * - any other string */ export type RpcType = '0x0' | '0x1' | '0x2' | '0x3' | '0x4' | (string & {}) /** RPC status to status mapping. */ export const fromRpcStatus = { '0x0': 'reverted', '0x1': 'success', } as const /** Status to RPC status mapping. */ export const toRpcStatus = { reverted: '0x0', success: '0x1', } as const /** RPC type to type mapping. */ export const fromRpcType = { '0x0': 'legacy', '0x1': 'eip2930', '0x2': 'eip1559', '0x3': 'eip4844', '0x4': 'eip7702', } as const /** Type to RPC type mapping. */ export const toRpcType = { legacy: '0x0', eip2930: '0x1', eip1559: '0x2', eip4844: '0x3', eip7702: '0x4', } as const /** * Converts a {@link ox#TransactionReceipt.Rpc} to an {@link ox#TransactionReceipt.TransactionReceipt}. * * @example * ```ts twoslash * import { TransactionReceipt } from 'ox' * * const receipt = TransactionReceipt.fromRpc({ * blobGasPrice: '0x42069', * blobGasUsed: '0x1337', * blockHash: * '0xc350d807505fb835650f0013632c5515592987ba169bbc6626d9fc54d91f0f0b', * blockNumber: '0x12f296f', * contractAddress: null, * cumulativeGasUsed: '0x82515', * effectiveGasPrice: '0x21c2f6c09', * from: '0x814e5e0e31016b9a7f138c76b7e7b2bb5c1ab6a6', * gasUsed: '0x2abba', * logs: [], * logsBloom: * '0x00200000000000000000008080000000000000000040000000000000000000000000000000000000000000000000000022000000080000000000000000000000000000080000000000000008000000200000000000000000000200008020400000000000000000280000000000100000000000000000000000000010000000000000000000020000000000000020000000000001000000080000004000000000000000000000000000000000000000000000400000000000001000000000000000000002000000000000000020000000000000000000001000000000000000000000200000000000000000000000000000001000000000c00000000000000000', * status: '0x1', * to: '0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad', * transactionHash: * '0x353fdfc38a2f26115daadee9f5b8392ce62b84f410957967e2ed56b35338cdd0', * transactionIndex: '0x2', * type: '0x2', * }) * // @log: { * // @log: blobGasPrice: 270441n, * // @log: blobGasUsed: 4919n, * // @log: blockHash: "0xc350d807505fb835650f0013632c5515592987ba169bbc6626d9fc54d91f0f0b", * // @log: blockNumber: 19868015n, * // @log: contractAddress: null, * // @log: cumulativeGasUsed: 533781n, * // @log: effectiveGasPrice: 9062804489n, * // @log: from: "0x814e5e0e31016b9a7f138c76b7e7b2bb5c1ab6a6", * // @log: gasUsed: 175034n, * // @log: logs: [], * // @log: logsBloom: "0x00200000000000000000008080000000000000000040000000000000000000000000000000000000000000000000000022000000080000000000000000000000000000080000000000000008000000200000000000000000000200008020400000000000000000280000000000100000000000000000000000000010000000000000000000020000000000000020000000000001000000080000004000000000000000000000000000000000000000000000400000000000001000000000000000000002000000000000000020000000000000000000001000000000000000000000200000000000000000000000000000001000000000c00000000000000000", * // @log: root: undefined, * // @log: status: "success", * // @log: to: "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", * // @log: transactionHash: "0x353fdfc38a2f26115daadee9f5b8392ce62b84f410957967e2ed56b35338cdd0", * // @log: transactionIndex: 2, * // @log: type: "eip1559", * // @log: } * ``` * * @example * ### End-to-end * * Below is an example of how to use the `TransactionReceipt.fromRpc` method to convert an RPC transaction receipt to a {@link ox#TransactionReceipt.TransactionReceipt} object. * * ```ts twoslash * import 'ox/window' * import { TransactionReceipt } from 'ox' * * const receipt = await window.ethereum! * .request({ * method: 'eth_getTransactionReceipt', * params: [ * '0x353fdfc38a2f26115daadee9f5b8392ce62b84f410957967e2ed56b35338cdd0', * ], * }) * .then(TransactionReceipt.fromRpc) // [!code hl] * // @log: { * // @log: blobGasPrice: 270441n, * // @log: blobGasUsed: 4919n, * // @log: blockHash: "0xc350d807505fb835650f0013632c5515592987ba169bbc6626d9fc54d91f0f0b", * // @log: blockNumber: 19868015n, * // @log: contractAddress: null, * // @log: cumulativeGasUsed: 533781n, * // @log: effectiveGasPrice: 9062804489n, * // @log: from: "0x814e5e0e31016b9a7f138c76b7e7b2bb5c1ab6a6", * // @log: gasUsed: 175034n, * // @log: logs: [], * // @log: logsBloom: "0x00200000000000000000008080000000000000000040000000000000000000000000000000000000000000000000000022000000080000000000000000000000000000080000000000000008000000200000000000000000000200008020400000000000000000280000000000100000000000000000000000000010000000000000000000020000000000000020000000000001000000080000004000000000000000000000000000000000000000000000400000000000001000000000000000000002000000000000000020000000000000000000001000000000000000000000200000000000000000000000000000001000000000c00000000000000000", * // @log: root: undefined, * // @log: status: "success", * // @log: to: "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", * // @log: transactionHash: "0x353fdfc38a2f26115daadee9f5b8392ce62b84f410957967e2ed56b35338cdd0", * // @log: transactionIndex: 2, * // @log: type: "eip1559", * // @log: } * ``` * * :::note * * For simplicity, the above example uses `window.ethereum.request`, but you can use any * type of JSON-RPC interface. * * ::: * * @param receipt - The RPC receipt to convert. * @returns An instantiated {@link ox#TransactionReceipt.TransactionReceipt}. */ export function fromRpc<const receipt extends Rpc | null>( receipt: receipt | Rpc | null, ): receipt extends Rpc ? TransactionReceipt : null { if (!receipt) return null as never return { ...receipt, blobGasPrice: receipt.blobGasPrice ? BigInt(receipt.blobGasPrice) : undefined, blobGasUsed: receipt.blobGasUsed ? BigInt(receipt.blobGasUsed) : undefined, blockNumber: BigInt(receipt.blockNumber ?? 0n), cumulativeGasUsed: BigInt(receipt.cumulativeGasUsed ?? 0n), effectiveGasPrice: BigInt(receipt.effectiveGasPrice ?? 0n), gasUsed: BigInt(receipt.gasUsed ?? 0n), logs: receipt.logs.map((log) => Log.fromRpc(log, { pending: false })), status: fromRpcStatus[receipt.status], transactionIndex: Number(receipt.transactionIndex ?? 0), type: (fromRpcType as any)[receipt.type] || receipt.type, } as never } export declare namespace fromRpc { export type ErrorType = Log.fromRpc.ErrorType | Errors.GlobalErrorType } /** * Converts a {@link ox#TransactionReceipt.TransactionReceipt} to a {@link ox#TransactionReceipt.Rpc}. * * @example * ```ts twoslash * import { TransactionReceipt } from 'ox' * * const receipt = TransactionReceipt.toRpc({ * blobGasPrice: 270441n, * blobGasUsed: 4919n, * blockHash: * '0xc350d807505fb835650f0013632c5515592987ba169bbc6626d9fc54d91f0f0b', * blockNumber: 19868015n, * contractAddress: null, * cumulativeGasUsed: 533781n, * effectiveGasPrice: 9062804489n, * from: '0x814e5e0e31016b9a7f138c76b7e7b2bb5c1ab6a6', * gasUsed: 175034n, * logs: [], * logsBloom: * '0x00200000000000000000008080000000000000000040000000000000000000000000000000000000000000000000000022000000080000000000000000000000000000080000000000000008000000200000000000000000000200008020400000000000000000280000000000100000000000000000000000000010000000000000000000020000000000000020000000000001000000080000004000000000000000000000000000000000000000000000400000000000001000000000000000000002000000000000000020000000000000000000001000000000000000000000200000000000000000000000000000001000000000c00000000000000000', * root: undefined, * status: 'success', * to: '0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad', * transactionHash: * '0x353fdfc38a2f26115daadee9f5b8392ce62b84f410957967e2ed56b35338cdd0', * transactionIndex: 2, * type: 'eip1559', * }) * // @log: { * // @log: blobGasPrice: "0x042069", * // @log: blobGasUsed: "0x1337", * // @log: blockHash: "0xc350d807505fb835650f0013632c5515592987ba169bbc6626d9fc54d91f0f0b", * // @log: blockNumber: "0x012f296f", * // @log: contractAddress: null, * // @log: cumulativeGasUsed: "0x082515", * // @log: effectiveGasPrice: "0x021c2f6c09", * // @log: from: "0x814e5e0e31016b9a7f138c76b7e7b2bb5c1ab6a6", * // @log: gasUsed: "0x02abba", * // @log: logs: [], * // @log: logsBloom: "0x00200000000000000000008080000000000000000040000000000000000000000000000000000000000000000000000022000000080000000000000000000000000000080000000000000008000000200000000000000000000200008020400000000000000000280000000000100000000000000000000000000010000000000000000000020000000000000020000000000001000000080000004000000000000000000000000000000000000000000000400000000000001000000000000000000002000000000000000020000000000000000000001000000000000000000000200000000000000000000000000000001000000000c00000000000000000", * // @log: root: undefined, * // @log: status: "0x1", * // @log: to: "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad", * // @log: transactionHash: "0x353fdfc38a2f26115daadee9f5b8392ce62b84f410957967e2ed56b35338cdd0", * // @log: transactionIndex: "0x02", * // @log: type: "eip1559", * // @log: } * ``` * * @param receipt - The receipt to convert. * @returns An RPC receipt. */ export function toRpc(receipt: TransactionReceipt): Rpc { return { blobGasPrice: receipt.blobGasPrice ? Hex.fromNumber(receipt.blobGasPrice) : undefined, blobGasUsed: receipt.blobGasUsed ? Hex.fromNumber(receipt.blobGasUsed) : undefined, blockHash: receipt.blockHash, blockNumber: Hex.fromNumber(receipt.blockNumber), contractAddress: receipt.contractAddress, cumulativeGasUsed: Hex.fromNumber(receipt.cumulativeGasUsed), effectiveGasPrice: Hex.fromNumber(receipt.effectiveGasPrice), from: receipt.from, gasUsed: Hex.fromNumber(receipt.gasUsed), logs: receipt.logs.map(Log.toRpc as never), logsBloom: receipt.logsBloom, root: receipt.root, status: toRpcStatus[receipt.status], to: receipt.to, transactionHash: receipt.transactionHash, transactionIndex: Hex.fromNumber(receipt.transactionIndex), type: (toRpcType as any)[receipt.type] ?? receipt.type, } } export declare namespace toRpc { export type ErrorType = Hex.fromNumber.ErrorType | Errors.GlobalErrorType }