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.
334 lines
13 KiB
334 lines
13 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'
|
|
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
|
|
}
|