Skip to content

Commit 2d7e8fd

Browse files
azf20jxom
andauthored
feat: add dataSuffix to calls in sendCalls and simulateBlocks (#3741)
* add dataSuffix to calls * Update perfect-snakes-lick.md --------- Co-authored-by: jxom <[email protected]>
1 parent 92c4219 commit 2d7e8fd

File tree

8 files changed

+180
-2
lines changed

8 files changed

+180
-2
lines changed

.changeset/perfect-snakes-lick.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"viem": patch
3+
---
4+
5+
Added dataSuffix to `sendCalls` and `simulateBlocks`.

site/pages/docs/actions/public/simulateCalls.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,37 @@ const { results } = await client.simulateCalls({
386386
})
387387
```
388388

389+
#### calls.dataSuffix
390+
391+
- **Type:** Hex
392+
393+
Data to append to the end of the calldata.
394+
395+
```ts twoslash [example.ts]
396+
import { parseAbi } from 'viem'
397+
import { client } from './config'
398+
399+
const abi = parseAbi([
400+
'function approve(address, uint256) returns (bool)',
401+
])
402+
// ---cut---
403+
const { id } = await client.simulateCalls({
404+
calls: [
405+
{
406+
to: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
407+
abi,
408+
functionName: 'approve',
409+
args: [
410+
'0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
411+
100n
412+
],
413+
dataSuffix: '0xdeadbeef' // [!code focus]
414+
}
415+
],
416+
})
417+
```
418+
419+
389420
### account (optional)
390421

391422
- **Type:** `Account | Address`

site/pages/docs/actions/wallet/sendCalls.mdx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,36 @@ const { id } = await walletClient.sendCalls({
409409
})
410410
```
411411

412+
#### calls.dataSuffix
413+
414+
- **Type:** Hex
415+
416+
Data to append to the end of the calldata. Useful for adding a "domain" tag.
417+
418+
```ts twoslash [example.ts]
419+
import { parseAbi } from 'viem'
420+
import { walletClient } from './config'
421+
422+
const abi = parseAbi([
423+
'function approve(address, uint256) returns (bool)',
424+
])
425+
// ---cut---
426+
const { id } = await walletClient.sendCalls({
427+
calls: [
428+
{
429+
to: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
430+
abi,
431+
functionName: 'approve',
432+
args: [
433+
'0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
434+
100n
435+
],
436+
dataSuffix: '0xdeadbeef' // [!code focus]
437+
}
438+
],
439+
})
440+
```
441+
412442
### capabilities
413443

414444
- **Type:** `WalletCapabilities`

src/actions/public/simulateBlocks.test.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { expect, test } from 'vitest'
22

3+
import { createPublicClient } from '~viem/clients/createPublicClient.js'
4+
import { custom } from '~viem/clients/transports/custom.js'
35
import {
46
baycContractConfig,
57
usdcContractConfig,
@@ -352,3 +354,61 @@ test('behavior: contract revert', async () => {
352354
`,
353355
)
354356
})
357+
358+
test('behavior: dataSuffix', async () => {
359+
const requests: unknown[] = []
360+
361+
const client = anvilMainnet.getClient()
362+
363+
const proxyClient = createPublicClient({
364+
chain: client.chain,
365+
transport: custom({
366+
async request({ method, params }) {
367+
requests.push(params)
368+
return client.request({ method, params })
369+
},
370+
}),
371+
})
372+
373+
const result = await simulateBlocks(proxyClient, {
374+
blocks: [
375+
{
376+
calls: [
377+
{
378+
abi: wagmiContractConfig.abi,
379+
functionName: 'name',
380+
to: wagmiContractConfig.address,
381+
dataSuffix: '0x1234',
382+
},
383+
],
384+
},
385+
],
386+
})
387+
388+
// validate that the dataSuffix is appended to the data in the request
389+
expect(requests[0]).toMatchInlineSnapshot(`
390+
[
391+
{
392+
"blockStateCalls": [
393+
{
394+
"blockOverrides": undefined,
395+
"calls": [
396+
{
397+
"data": "0x06fdde031234",
398+
"to": "0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2",
399+
},
400+
],
401+
"stateOverrides": undefined,
402+
},
403+
],
404+
"returnFullTransactions": undefined,
405+
"traceTransfers": undefined,
406+
"validation": undefined,
407+
},
408+
"latest",
409+
]
410+
`)
411+
412+
// confirm that the result is still as expected
413+
expect(result[0].calls[0].result).toEqual('wagmi')
414+
})

src/actions/public/simulateBlocks.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
type EncodeFunctionDataErrorType,
3131
encodeFunctionData,
3232
} from '../../utils/abi/encodeFunctionData.js'
33+
import { concat } from '../../utils/data/concat.js'
3334
import {
3435
type NumberToHexErrorType,
3536
numberToHex,
@@ -201,9 +202,12 @@ export async function simulateBlocks<
201202
const calls = block.calls.map((call_) => {
202203
const call = call_ as Call<unknown, CallExtraProperties>
203204
const account = call.account ? parseAccount(call.account) : undefined
205+
const data = call.abi ? encodeFunctionData(call) : call.data
204206
const request = {
205207
...call,
206-
data: call.abi ? encodeFunctionData(call) : call.data,
208+
data: call.dataSuffix
209+
? concat([data || '0x', call.dataSuffix])
210+
: data,
207211
from: call.from ?? account?.address,
208212
} as const
209213
assertRequest(request)

src/actions/wallet/sendCalls.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,3 +687,49 @@ test('error: insufficient funds', async () => {
687687
688688
`)
689689
})
690+
691+
test('args: dataSuffix', async () => {
692+
const requests: unknown[] = []
693+
694+
const client = getClient({
695+
onRequest({ params }) {
696+
requests.push(params)
697+
},
698+
})
699+
700+
const response = await sendCalls(client, {
701+
account: accounts[0].address,
702+
chain: mainnet,
703+
calls: [
704+
{
705+
abi: wagmiContractConfig.abi,
706+
functionName: 'mint',
707+
to: wagmiContractConfig.address,
708+
dataSuffix: '0x12345678',
709+
},
710+
],
711+
})
712+
713+
expect(response.id).toBeDefined()
714+
expect(requests).toMatchInlineSnapshot(`
715+
[
716+
[
717+
{
718+
"atomicRequired": false,
719+
"calls": [
720+
{
721+
"data": "0x1249c58b12345678",
722+
"to": "0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2",
723+
"value": undefined,
724+
},
725+
],
726+
"capabilities": undefined,
727+
"chainId": "0x1",
728+
"from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
729+
"id": undefined,
730+
"version": "2.0.0",
731+
},
732+
],
733+
]
734+
`)
735+
})

src/actions/wallet/sendCalls.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ export async function sendCalls<
120120
: call.data
121121

122122
return {
123-
data,
123+
data: call.dataSuffix && data ? concat([data, call.dataSuffix]) : data,
124124
to: call.to,
125125
value: call.value ? numberToHex(call.value) : undefined,
126126
}

src/types/calls.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export type Call<
1010
| Assign<
1111
{
1212
data?: Hex | undefined
13+
dataSuffix?: Hex | undefined
1314
to: Address
1415
value?: bigint | undefined
1516
},
@@ -22,6 +23,7 @@ export type Call<
2223
> & {
2324
to: Address
2425
value?: bigint | undefined
26+
dataSuffix?: Hex | undefined
2527
},
2628
extraProperties
2729
>

0 commit comments

Comments
 (0)