From efcdc57e504a8469c63f944c28ff92e8095b43ad Mon Sep 17 00:00:00 2001 From: jxom <7336481+jxom@users.noreply.github.com> Date: Fri, 21 Feb 2025 09:54:41 +1100 Subject: [PATCH] feat(erc5792): allow nullish account --- .changeset/forty-suns-invite.md | 5 + site/pages/experimental/eip5792/sendCalls.mdx | 4 +- .../eip5792/actions/sendCalls.test.ts | 93 ++++++++++++++++++- src/experimental/eip5792/actions/sendCalls.ts | 10 +- src/types/eip1193.ts | 4 +- 5 files changed, 104 insertions(+), 12 deletions(-) create mode 100644 .changeset/forty-suns-invite.md diff --git a/.changeset/forty-suns-invite.md b/.changeset/forty-suns-invite.md new file mode 100644 index 0000000000..51742ecc69 --- /dev/null +++ b/.changeset/forty-suns-invite.md @@ -0,0 +1,5 @@ +--- +"viem": patch +--- + +**Experimental(ERC-5792):** Added support for nullish `account` in `sendCalls`. diff --git a/site/pages/experimental/eip5792/sendCalls.mdx b/site/pages/experimental/eip5792/sendCalls.mdx index 64b250e1b7..6e0cc258f3 100644 --- a/site/pages/experimental/eip5792/sendCalls.mdx +++ b/site/pages/experimental/eip5792/sendCalls.mdx @@ -187,9 +187,9 @@ The identifier can be any arbitrary string. The only requirement is that for a g ### account -- **Type:** `Account | Address` +- **Type:** `Account | Address | null` -The Account to sign & broadcast the call from. +The Account to sign & broadcast the call from. If set to `null`, it is assumed that the wallet will handle filling the sender of the calls. Accepts a [JSON-RPC Account](/docs/clients/wallet#json-rpc-accounts). diff --git a/src/experimental/eip5792/actions/sendCalls.test.ts b/src/experimental/eip5792/actions/sendCalls.test.ts index 6ce9a3649f..51567b5883 100644 --- a/src/experimental/eip5792/actions/sendCalls.test.ts +++ b/src/experimental/eip5792/actions/sendCalls.test.ts @@ -73,7 +73,9 @@ const getClient = ({ const callResult = await rpcClient.request({ body: { method: 'eth_call', - params: [{ ...call, from: params[0].from }], + params: [ + { ...call, from: params[0].from ?? accounts[0].address }, + ], id: 0, }, }) @@ -82,7 +84,9 @@ const getClient = ({ const { result, error } = await rpcClient.request({ body: { method: 'eth_sendTransaction', - params: [{ ...call, from: params[0].from }], + params: [ + { ...call, from: params[0].from ?? accounts[0].address }, + ], id: 0, }, }) @@ -274,6 +278,91 @@ test('behavior: chain on client', async () => { `) }) +test('behavior: inferred account', async () => { + const requests: unknown[] = [] + + const client = getClient({ + onRequest({ params }) { + requests.push(params) + }, + }) + + await reset(testClient, { + blockNumber: 16280770n, + jsonRpcUrl: anvilMainnet.forkUrl, + }) + + const id_ = await sendCalls(client, { + account: null, + chain: mainnet, + calls: [ + { + to: accounts[1].address, + value: parseEther('1'), + }, + { + to: accounts[2].address, + }, + { + data: '0xcafebabe', + to: accounts[3].address, + value: parseEther('100'), + }, + { + abi: wagmiContractConfig.abi, + functionName: 'mint', + to: wagmiContractConfig.address, + }, + { + abi: wagmiContractConfig.abi, + functionName: 'mint', + to: wagmiContractConfig.address, + }, + ], + }) + + expect(id_).toBeDefined() + expect(requests).toMatchInlineSnapshot(` + [ + [ + { + "calls": [ + { + "data": undefined, + "to": "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", + "value": "0xde0b6b3a7640000", + }, + { + "data": undefined, + "to": "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc", + "value": undefined, + }, + { + "data": "0xcafebabe", + "to": "0x90f79bf6eb2c4f870365e785982e1f101e93b906", + "value": "0x56bc75e2d63100000", + }, + { + "data": "0x1249c58b", + "to": "0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2", + "value": undefined, + }, + { + "data": "0x1249c58b", + "to": "0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2", + "value": undefined, + }, + ], + "capabilities": undefined, + "chainId": "0x1", + "from": undefined, + "version": "1.0", + }, + ], + ] + `) +}) + test('error: no account', async () => { const requests: unknown[] = [] diff --git a/src/experimental/eip5792/actions/sendCalls.ts b/src/experimental/eip5792/actions/sendCalls.ts index b67bab1c59..e1841f5c0a 100644 --- a/src/experimental/eip5792/actions/sendCalls.ts +++ b/src/experimental/eip5792/actions/sendCalls.ts @@ -1,4 +1,4 @@ -import type { Narrow } from 'abitype' +import type { Address, Narrow } from 'abitype' import { parseAccount } from '../../../accounts/utils/parseAccount.js' import type { Client } from '../../../clients/createClient.js' import type { Transport } from '../../../clients/transports/createTransport.js' @@ -31,7 +31,7 @@ export type SendCallsParameters< | WalletSendCallsParameters[number]['capabilities'] | undefined version?: WalletSendCallsParameters[number]['version'] | undefined -} & GetAccountParameter +} & GetAccountParameter export type SendCallsReturnType = string @@ -85,11 +85,11 @@ export async function sendCalls< version = '1.0', } = parameters - if (!account_) + if (typeof account_ === 'undefined') throw new AccountNotFoundError({ docsPath: '/experimental/eip5792/sendCalls', }) - const account = parseAccount(account_) + const account = account_ ? parseAccount(account_) : null const calls = parameters.calls.map((call_: unknown) => { const call = call_ as Call @@ -118,7 +118,7 @@ export async function sendCalls< calls, capabilities, chainId: numberToHex(chain!.id), - from: account.address, + from: account?.address, version, }, ], diff --git a/src/types/eip1193.ts b/src/types/eip1193.ts index 3e3b819ab0..f554c2e934 100644 --- a/src/types/eip1193.ts +++ b/src/types/eip1193.ts @@ -210,15 +210,13 @@ export type WalletSendCallsParameters< > = [ { calls: readonly { - chainId?: chainId | undefined to?: Address | undefined data?: Hex | undefined value?: quantity | undefined }[] capabilities?: capabilities | undefined - /** @deprecated Use `chainId` on `calls` instead. */ chainId?: chainId | undefined - from: Address + from?: Address | undefined version: string }, ]