wallet_sendCalls
Sends multiple contract calls as a single atomic batch. All calls execute together or none execute, preventing partial failures. This is ideal for multi-step operations like "approve + swap" that must succeed together. Gas is sponsored and the user signs once for the entire batch.
Try it
Parameters
| Position | Type | Description |
|---|---|---|
| 0 | object | The batch calls payload |
Payload Object
| Field | Type | Description |
|---|---|---|
chainId | number | Required: Target chain ID for execution |
calls | Call[] | Array of calls to execute |
tokenRequests | TokenRequest[] | Optional: tokens to receive (output-first model) |
Call Object
| Field | Type | Description |
|---|---|---|
to | string | The recipient address |
data | string | The calldata (optional) |
value | string | number | The value in wei (optional) |
TokenRequest Object
| Field | Type | Description |
|---|---|---|
token | string | ERC-20 token contract address |
amount | string | Amount in base units (e.g., "1000000" for 1 USDC) |
Returns
string - The calls ID (intent ID) for tracking status.
Example
The chainId parameter specifies which chain the calls execute on. This enables crosschain transactions - the user's funds can be on any chain and the orchestrator handles bridging automatically.
// Batch multiple contract calls
const callsId = await provider.request({
method: 'wallet_sendCalls',
params: [{
chainId: 8453, // Target chain is required!
calls: [
{
to: '0x...', // Token contract
data: '0x...', // approve()
},
{
to: '0x...', // DEX contract
data: '0x...', // swap()
},
],
}],
});
// Track the status
const status = await provider.request({
method: 'wallet_getCallsStatus',
params: [callsId],
});Crosschain execution
The chainId parameter is the key to crosschain transactions. Set it to the chain where you want the calls to execute:
// Execute on Base (chainId: 8453)
const callsId = await provider.request({
method: 'wallet_sendCalls',
params: [{
chainId: 8453, // Calls execute on Base
calls: [{
to: '0x...', // Contract on Base
data: '0x...',
}],
}],
});The orchestrator finds the cheapest route to fund the transaction, regardless of where the user's assets are. User signs once with their passkey.
Token requests (output-first)
Use tokenRequests to specify what tokens you want to receive. The orchestrator automatically determines the best path to deliver those tokens from the user's available assets across chains.
const callsId = await provider.request({
method: 'wallet_sendCalls',
params: [{
chainId: 8453, // Base
calls: [{ to: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', data: '0x' }],
tokenRequests: [
{
token: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
amount: '100000000', // 100 USDC (6 decimals)
},
],
}],
});This is useful for swaps, cross-chain transfers, or any operation where you want to specify the output rather than the input.
Notes
- All calls are executed atomically - if one fails, all fail
- User sees a summary of all calls before signing
- Gas is sponsored - no ETH needed for fees
- Use
wallet_getCallsStatusto track execution status tokenRequests.amountis a string at the RPC level; the SDK acceptsbigintand converts automatically