Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion packages/core/src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,16 @@ export type {
export { mine, setBalance } from './test'
export type { MineArgs, SetBalanceArgs } from './test'

export { fetchTransaction, sendTransaction } from './transaction'
export {
fetchTransaction,
fetchTransactionReceipt,
sendTransaction,
} from './transaction'
export type {
FetchTransactionArgs,
FetchTransactionResponse,
FetchTransactionReceiptArgs,
FetchTransactionReceiptResponse,
SendTransactionArgs,
SendTransactionResponse,
} from './transaction'
154 changes: 154 additions & 0 deletions packages/core/src/actions/transaction/fetchTransactionReceipt.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { assertType, expect, test } from 'vitest'

import { publicClient } from '../../../test'
import { celo, defineTransactionReceipt, localhost } from '../../chains'
import { createPublicClient, http } from '../../clients'
import type { TransactionReceipt } from '../../types'

import { fetchTransactionReceipt } from './fetchTransactionReceipt'

test('fetches transaction receipt', async () => {
const receipt = await fetchTransactionReceipt(publicClient, {
hash: '0xa4b1f606b66105fa45cb5db23d2f6597075701e7f0e2367f4e6a39d17a8cf98b',
})
assertType<TransactionReceipt>(receipt)
expect(receipt).toMatchInlineSnapshot(`
{
"blockHash": "0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d",
"blockNumber": 15131999n,
"contractAddress": null,
"cumulativeGasUsed": 5814407n,
"effectiveGasPrice": 11789405161n,
"from": "0xa152f8bb749c55e9943a3a0a3111d18ee2b3f94e",
"gasUsed": 37976n,
"logs": [
{
"address": "0x15d4c048f83bd7e37d49ea4c83a07267ec4203da",
"blockHash": "0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d",
"blockNumber": 15131999n,
"data": "0x0000000000000000000000000000000000000000000000000000002b3b6fb3d0",
"logIndex": 108n,
"removed": false,
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000a00f99bc38b1ecda1fd70eaa1cd31d576a9f46b0",
"0x000000000000000000000000f16e9b0d03470827a95cdfd0cb8a8a3b46969b91",
],
"transactionHash": "0xa4b1f606b66105fa45cb5db23d2f6597075701e7f0e2367f4e6a39d17a8cf98b",
"transactionIndex": 69n,
},
{
"address": "0x15d4c048f83bd7e37d49ea4c83a07267ec4203da",
"blockHash": "0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d",
"blockNumber": 15131999n,
"data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffd4c4904c2f",
"logIndex": 109n,
"removed": false,
"topics": [
"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925",
"0x000000000000000000000000a00f99bc38b1ecda1fd70eaa1cd31d576a9f46b0",
"0x000000000000000000000000a152f8bb749c55e9943a3a0a3111d18ee2b3f94e",
],
"transactionHash": "0xa4b1f606b66105fa45cb5db23d2f6597075701e7f0e2367f4e6a39d17a8cf98b",
"transactionIndex": 69n,
},
],
"logsBloom": "0x08000000000000000000000000000000000000000000000000001000002000000000000000000000000000000000000000000000080000000000000000200000000000000000000000000008400000000000000000000000000000000000100000000000000000000040000008000000000004000000000000000010000000000000000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000002090000000000000000000000000000000000000000000000000000000000000",
"status": "success",
"to": "0x15d4c048f83bd7e37d49ea4c83a07267ec4203da",
"transactionHash": "0xa4b1f606b66105fa45cb5db23d2f6597075701e7f0e2367f4e6a39d17a8cf98b",
"transactionIndex": 69,
"type": "eip1559",
}
`)
})

test('chain w/ custom block type', async () => {
const client = createPublicClient({
chain: {
...celo,
rpcUrls: localhost.rpcUrls,
formatters: {
transactionReceipt: defineTransactionReceipt({
exclude: ['effectiveGasPrice'],
format: () => ({
foo: 'bar' as const,
}),
}),
},
},
transport: http(),
})
const receipt = await fetchTransactionReceipt(client, {
hash: '0xa4b1f606b66105fa45cb5db23d2f6597075701e7f0e2367f4e6a39d17a8cf98b',
})

assertType<
Omit<TransactionReceipt, 'effectiveGasPrice'> & {
foo: 'bar'
}
>(receipt)

expect(receipt).toMatchInlineSnapshot(`
{
"blockHash": "0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d",
"blockNumber": 15131999n,
"contractAddress": null,
"cumulativeGasUsed": 5814407n,
"foo": "bar",
"from": "0xa152f8bb749c55e9943a3a0a3111d18ee2b3f94e",
"gasUsed": 37976n,
"logs": [
{
"address": "0x15d4c048f83bd7e37d49ea4c83a07267ec4203da",
"blockHash": "0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d",
"blockNumber": 15131999n,
"data": "0x0000000000000000000000000000000000000000000000000000002b3b6fb3d0",
"logIndex": 108n,
"removed": false,
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000a00f99bc38b1ecda1fd70eaa1cd31d576a9f46b0",
"0x000000000000000000000000f16e9b0d03470827a95cdfd0cb8a8a3b46969b91",
],
"transactionHash": "0xa4b1f606b66105fa45cb5db23d2f6597075701e7f0e2367f4e6a39d17a8cf98b",
"transactionIndex": 69n,
},
{
"address": "0x15d4c048f83bd7e37d49ea4c83a07267ec4203da",
"blockHash": "0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d",
"blockNumber": 15131999n,
"data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffd4c4904c2f",
"logIndex": 109n,
"removed": false,
"topics": [
"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925",
"0x000000000000000000000000a00f99bc38b1ecda1fd70eaa1cd31d576a9f46b0",
"0x000000000000000000000000a152f8bb749c55e9943a3a0a3111d18ee2b3f94e",
],
"transactionHash": "0xa4b1f606b66105fa45cb5db23d2f6597075701e7f0e2367f4e6a39d17a8cf98b",
"transactionIndex": 69n,
},
],
"logsBloom": "0x08000000000000000000000000000000000000000000000000001000002000000000000000000000000000000000000000000000080000000000000000200000000000000000000000000008400000000000000000000000000000000000100000000000000000000040000008000000000004000000000000000010000000000000000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000002090000000000000000000000000000000000000000000000000000000000000",
"status": "success",
"to": "0x15d4c048f83bd7e37d49ea4c83a07267ec4203da",
"transactionHash": "0xa4b1f606b66105fa45cb5db23d2f6597075701e7f0e2367f4e6a39d17a8cf98b",
"transactionIndex": 69,
"type": "eip1559",
}
`)
})

test('throws if transaction not found', async () => {
await expect(
fetchTransactionReceipt(publicClient, {
hash: '0xa4b1f606b66105fa45cb5db23d2f6597075701e7f0e2367f4e6a39d17a8cf98a',
}),
).rejects.toThrowErrorMatchingInlineSnapshot(`
"Transaction with hash \\"0xa4b1f606b66105fa45cb5db23d2f6597075701e7f0e2367f4e6a39d17a8cf98a\\" could not be found.

Details: transaction not found
Version: viem@1.0.2"
`)
})
35 changes: 35 additions & 0 deletions packages/core/src/actions/transaction/fetchTransactionReceipt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { Chain } from '../../chains'
import type { PublicClient } from '../../clients'
import type { Data } from '../../types'
import { format } from '../../utils'
import type {
FormattedTransactionReceipt,
TransactionReceiptFormatter,
} from '../../utils/formatters/transactionReceipt'
import { formatTransactionReceipt } from '../../utils/formatters/transactionReceipt'
import { TransactionNotFoundError } from './fetchTransaction'

export type FetchTransactionReceiptArgs = {
/** The hash of the transaction. */
hash: Data
}

export type FetchTransactionReceiptResponse<TChain extends Chain = Chain> =
FormattedTransactionReceipt<TransactionReceiptFormatter<TChain>>

export async function fetchTransactionReceipt<TChain extends Chain>(
client: PublicClient<any, TChain>,
{ hash }: FetchTransactionReceiptArgs,
) {
const receipt = await client.request({
method: 'eth_getTransactionReceipt',
params: [hash],
})

if (!receipt) throw new TransactionNotFoundError({ hash })

return format(receipt, {
formatter:
client.chain?.formatters?.transactionReceipt || formatTransactionReceipt,
}) as FetchTransactionReceiptResponse<TChain>
}
1 change: 1 addition & 0 deletions packages/core/src/actions/transaction/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ test('exports actions', () => {
expect(actions).toMatchInlineSnapshot(`
{
"fetchTransaction": [Function],
"fetchTransactionReceipt": [Function],
"sendTransaction": [Function],
}
`)
Expand Down
6 changes: 6 additions & 0 deletions packages/core/src/actions/transaction/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ export type {
FetchTransactionResponse,
} from './fetchTransaction'

export { fetchTransactionReceipt } from './fetchTransactionReceipt'
export type {
FetchTransactionReceiptArgs,
FetchTransactionReceiptResponse,
} from './fetchTransactionReceipt'

export { sendTransaction } from './sendTransaction'
export type {
SendTransactionArgs,
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/chains.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,11 @@ test('exports chains', () => {
},
},
},
"defineBlock": [Function],
"defineChain": [Function],
"defineTransaction": [Function],
"defineTransactionReceipt": [Function],
"defineTransactionRequest": [Function],
"fantom": {
"blockExplorers": {
"default": {
Expand Down
13 changes: 10 additions & 3 deletions packages/core/src/chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,18 @@ import type {
Quantity,
RpcBlock,
RpcTransaction,
RpcTransactionReceipt,
RpcTransactionRequest,
Transaction,
TransactionReceipt,
TransactionRequest,
} from './types'
import {
formatBlock,
formatTransaction,
formatTransactionRequest,
} from './utils'
import { formatTransactionReceipt } from './utils/formatters/transactionReceipt'

export type Formatter<TSource = any, TTarget = any> = (
value: TSource & { [key: string]: unknown },
Expand All @@ -46,6 +49,7 @@ export type Formatter<TSource = any, TTarget = any> = (
export type Formatters = {
block?: Formatter<RpcBlock, Block>
transaction?: Formatter<RpcTransaction, Transaction>
transactionReceipt?: Formatter<RpcTransactionReceipt, TransactionReceipt>
transactionRequest?: Formatter<TransactionRequest, RpcTransactionRequest>
}

Expand Down Expand Up @@ -94,11 +98,14 @@ function defineFormatter<TSource extends Record<string, unknown>, TFormatted>({
}
}

const defineBlock = defineFormatter({ format: formatBlock })
const defineTransaction = defineFormatter({ format: formatTransaction })
const defineTransactionRequest = defineFormatter({
export const defineBlock = defineFormatter({ format: formatBlock })
export const defineTransaction = defineFormatter({ format: formatTransaction })
export const defineTransactionRequest = defineFormatter({
format: formatTransactionRequest,
})
export const defineTransactionReceipt = defineFormatter({
format: formatTransactionReceipt,
})

export const arbitrumGoerli = defineChain(arbitrumGoerli_)
export const arbitrum = defineChain(arbitrum_)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ test('exports constants', () => {
"ether": -9,
"wei": 9,
},
"transactionType": {
"0x0": "legacy",
"0x1": "eip2930",
"0x2": "eip1559",
},
"weiUnits": {
"ether": -18,
"gwei": -9,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@ export const weiUnits = {
ether: -18,
gwei: -9,
}

export const transactionType = {
'0x0': 'legacy',
'0x1': 'eip2930',
'0x2': 'eip1559',
} as const
9 changes: 5 additions & 4 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export type {
FetchBlockResponse,
FetchTransactionArgs,
FetchTransactionResponse,
FetchTransactionReceiptArgs,
FetchTransactionReceiptResponse,
MineArgs,
SendTransactionArgs,
SendTransactionResponse,
Expand All @@ -22,6 +24,7 @@ export {
fetchBlock,
fetchBlockNumber,
fetchTransaction,
fetchTransactionReceipt,
mine,
requestAccounts,
sendTransaction,
Expand Down Expand Up @@ -60,6 +63,8 @@ export {
webSocket,
} from './clients'

export { etherUnits, gweiUnits, transactionType, weiUnits } from './constants'

export type {
Address,
AccessList,
Expand Down Expand Up @@ -123,17 +128,13 @@ export {
checksumAddress,
displayToValue,
etherToValue,
etherUnits,
formatBlock,
formatTransaction,
formatTransactionRequest,
gweiToValue,
gweiUnits,
hexToNumber,
numberToHex,
transactionType,
valueAsEther,
valueAsGwei,
valueToDisplay,
weiUnits,
} from './utils'
9 changes: 8 additions & 1 deletion packages/core/src/types/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import type {

export type Index = `0x${string}`
export type Quantity = `0x${string}`
export type Status = '0x0' | '0x1'
export type TransactionType = '0x0' | '0x1' | '0x2'

export type RpcBlock = Block<Quantity>
export type RpcBlockNumber = BlockNumber<Quantity>
Expand All @@ -19,7 +21,12 @@ export type RpcUncle = Uncle<Quantity>
export type RpcFeeHistory = FeeHistory<Quantity>
export type RpcFeeValues = FeeValues<Quantity>
export type RpcLog = Log<Quantity, Index>
export type RpcTransactionReceipt = TransactionReceipt<Quantity, Index>
export type RpcTransactionReceipt = TransactionReceipt<
Quantity,
Index,
Status,
TransactionType
>
export type RpcTransactionRequest = TransactionRequest<Quantity, Index>
export type RpcTransaction =
| TransactionLegacy<Quantity, Index, '0x0'>
Expand Down
Loading