Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/eip-1898-block-identifier.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"viem": minor
---

Added EIP-1898 block identifier support (`blockHash` and `requireCanonical` parameters) for `call`, `getBalance`, `getCode`, `getProof`, `getStorageAt`, and `getTransactionCount` actions.
35 changes: 35 additions & 0 deletions site/pages/docs/actions/public/call.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,41 @@ const data = await publicClient.call({
})
```

### blockHash (optional)

- **Type:** `Hash`

The block hash to perform the call against. Implements [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898).

```ts twoslash
// [!include ~/snippets/publicClient.ts]
// ---cut---
const data = await publicClient.call({
blockHash: '0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d', // [!code focus]
account: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
data: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
})
```

### requireCanonical (optional)

- **Type:** `boolean`

Whether or not to throw an error if the block is not in the canonical chain. Only allowed in conjunction with `blockHash`. Implements [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898).

```ts twoslash
// [!include ~/snippets/publicClient.ts]
// ---cut---
const data = await publicClient.call({
blockHash: '0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d',
requireCanonical: true, // [!code focus]
account: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
data: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
})
```

### code (optional)

- **Type:**
Expand Down
31 changes: 31 additions & 0 deletions site/pages/docs/actions/public/getBalance.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,37 @@ const balance = await publicClient.getBalance({
})
```

### blockHash (optional)

- **Type:** `Hash`

The balance of the account at a block hash. Implements [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898).

```ts twoslash
// [!include ~/snippets/publicClient.ts]
// ---cut---
const balance = await publicClient.getBalance({
address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
blockHash: '0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d' // [!code focus]
})
```

### requireCanonical (optional)

- **Type:** `boolean`

Whether or not to throw an error if the block is not in the canonical chain. Only allowed in conjunction with `blockHash`. Implements [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898).

```ts twoslash
// [!include ~/snippets/publicClient.ts]
// ---cut---
const balance = await publicClient.getBalance({
address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
blockHash: '0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d',
requireCanonical: true // [!code focus]
})
```

## Tips

- You can convert the balance to ether units with [`formatEther`](/docs/utilities/formatEther).
Expand Down
33 changes: 33 additions & 0 deletions site/pages/docs/actions/public/getProof.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,39 @@ const proof = await publicClient.getProof({
})
```

### blockHash (optional)

- **Type:** `Hash`

Proof at a given block hash. Implements [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898).

```ts
const proof = await publicClient.getProof({
address: '0x4200000000000000000000000000000000000016',
storageKeys: [
'0x4a932049252365b3eedbc5190e18949f2ec11f39d3bef2d259764799a1b27d99',
],
blockHash: '0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d' // [!code focus]
})
```

### requireCanonical (optional)

- **Type:** `boolean`

Whether or not to throw an error if the block is not in the canonical chain. Only allowed in conjunction with `blockHash`. Implements [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898).

```ts
const proof = await publicClient.getProof({
address: '0x4200000000000000000000000000000000000016',
storageKeys: [
'0x4a932049252365b3eedbc5190e18949f2ec11f39d3bef2d259764799a1b27d99',
],
blockHash: '0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d',
requireCanonical: true // [!code focus]
})
```

## JSON-RPC Method

- Calls [`eth_getProof`](https://eips.ethereum.org/EIPS/eip-1186).
31 changes: 31 additions & 0 deletions site/pages/docs/actions/public/getTransactionCount.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,37 @@ const transactionCount = await publicClient.getTransactionCount({
})
```

### blockHash (optional)

- **Type:** `Hash`

Get the count at a block hash. Implements [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898).

```ts twoslash
// [!include ~/snippets/publicClient.ts]
// ---cut---
const transactionCount = await publicClient.getTransactionCount({
address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
blockHash: '0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d' // [!code focus]
})
```

### requireCanonical (optional)

- **Type:** `boolean`

Whether or not to throw an error if the block is not in the canonical chain. Only allowed in conjunction with `blockHash`. Implements [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898).

```ts twoslash
// [!include ~/snippets/publicClient.ts]
// ---cut---
const transactionCount = await publicClient.getTransactionCount({
address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
blockHash: '0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d',
requireCanonical: true // [!code focus]
})
```

## Notes

- The transaction count of an account can also be used as a nonce.
Expand Down
27 changes: 27 additions & 0 deletions site/pages/docs/contract/getCode.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,33 @@ const bytecode = await publicClient.getCode({
})
```

### blockHash (optional)

- **Type:** `Hash`

The block hash to perform the bytecode read against. Implements [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898).

```ts
const bytecode = await publicClient.getCode({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
blockHash: '0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d', // [!code focus]
})
```

### requireCanonical (optional)

- **Type:** `boolean`

Whether or not to throw an error if the block is not in the canonical chain. Only allowed in conjunction with `blockHash`. Implements [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898).

```ts
const bytecode = await publicClient.getCode({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
blockHash: '0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d',
requireCanonical: true, // [!code focus]
})
```

## JSON-RPC Method

[`eth_getCode`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getcode)
29 changes: 29 additions & 0 deletions site/pages/docs/contract/getStorageAt.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,35 @@ const bytecode = await publicClient.getStorageAt({
})
```

### blockHash (optional)

- **Type:** `Hash`

The block hash to perform the storage slot read against. Implements [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898).

```ts
const bytecode = await publicClient.getStorageAt({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
slot: toHex(0),
blockHash: '0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d', // [!code focus]
})
```

### requireCanonical (optional)

- **Type:** `boolean`

Whether or not to throw an error if the block is not in the canonical chain. Only allowed in conjunction with `blockHash`. Implements [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898).

```ts
const bytecode = await publicClient.getStorageAt({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
slot: toHex(0),
blockHash: '0x89644bbd5c8d682a2e9611170e6c1f02573d866d286f006cbf517eec7254ec2d',
requireCanonical: true, // [!code focus]
})
```

## JSON-RPC Method

[`eth_getStorageAt`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getstorageat)
36 changes: 36 additions & 0 deletions src/actions/public/call.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { parseGwei } from '../../utils/unit/parseGwei.js'
import { wait } from '../../utils/wait.js'
import { signAuthorization } from '../wallet/signAuthorization.js'
import { call, getRevertErrorData } from './call.js'
import { getBlock } from './getBlock.js'
import { readContract } from './readContract.js'

const client = anvilMainnet.getClient({ account: accounts[0].address })
Expand Down Expand Up @@ -200,6 +201,41 @@ test.skip('args: blockNumber', async () => {
expect(data).toMatchInlineSnapshot('undefined')
})

test('args: blockHash (EIP-1898)', async () => {
const block = await getBlock(client, {
blockNumber: anvilMainnet.forkBlockNumber,
})

const { data } = await call(client, {
blockHash: block.hash!,
data: name4bytes,
account: sourceAccount.address,
to: wagmiContractAddress,
})

expect(data).toMatchInlineSnapshot(
'"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000057761676d69000000000000000000000000000000000000000000000000000000"',
)
})

test('args: blockHash + requireCanonical (EIP-1898)', async () => {
const block = await getBlock(client, {
blockNumber: anvilMainnet.forkBlockNumber,
})

const { data } = await call(client, {
blockHash: block.hash!,
requireCanonical: true,
data: name4bytes,
account: sourceAccount.address,
to: wagmiContractAddress,
})

expect(data).toMatchInlineSnapshot(
'"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000057761676d69000000000000000000000000000000000000000000000000000000"',
)
})

test('args: override', async () => {
const fakeName = 'NotWagmi'

Expand Down
Loading