> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://v3.viem.sh/api/mcp` to find what you need.

# Send Calls \[wallet.sendCalls]

Requests the connected wallet to send a batch of calls
([EIP-5792](https://eips.ethereum.org/EIPS/eip-5792)) and waits for inclusion.

## Usage

Use `sendCallsSync` to send a batch of calls and wait for their receipts.

:::code-group
```ts twoslash [example.ts]
import { client } from './viem.config'

const status = await client.wallet.sendCallsSync({
  account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  calls: [
    {
      to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
      value: 69420n,
    },
  ],
})
// @log: {
// @log:   atomic: true,
// @log:   chainId: 1,
// @log:   id: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
// @log:   receipts: [{ blockNumber: 12345678n, gasUsed: 21000n, status: 'success', ... }],
// @log:   status: 'success',
// @log:   statusCode: 200,
// @log:   version: '2.0.0',
// @log: }
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, custom, walletActions } from 'viem'
import 'viem/window'

export const client = Client.create({
  transport: custom(window.ethereum!),
}).extend(walletActions())
```
:::

### Asynchronous Usage

Use `sendCalls` when the call bundle ID is needed immediately and status tracking happens
elsewhere.

:::code-group
```ts twoslash [example.ts]
import { client } from './viem.config'

const { id } = await client.wallet.sendCalls({
  account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  calls: [
    {
      data: '0xdeadbeef',
      to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
    },
    {
      to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
      value: 69420n,
    },
  ],
})
// @log: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, custom, walletActions } from 'viem'
import 'viem/window'

export const client = Client.create({
  transport: custom(window.ethereum!),
}).extend(walletActions())
```
:::

### Standalone Action

Call `Actions.wallet.sendCallsSync` directly by passing the Client as the first argument. Use
`Actions.wallet.sendCalls` for the asynchronous variant.

:::code-group
```ts twoslash [example.ts]
import { Actions } from 'viem'
import { client } from './viem.config'

const status = await Actions.wallet.sendCallsSync(client, {
  account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  calls: [
    {
      to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
      value: 69420n,
    },
  ],
})
// @log: {
// @log:   atomic: true,
// @log:   chainId: 1,
// @log:   id: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
// @log:   receipts: [{ blockNumber: 12345678n, gasUsed: 21000n, status: 'success', ... }],
// @log:   status: 'success',
// @log:   statusCode: 200,
// @log:   version: '2.0.0',
// @log: }
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, custom } from 'viem'
import { mainnet } from 'viem/chains'
import 'viem/window'

export const client = Client.create({
  chain: mainnet,
  transport: custom(window.ethereum!),
})
```
:::

## Recipes

### Require Successful Calls

Set `throwOnFailure` to reject when the wallet reports a failed call bundle.

:::code-group
```ts twoslash [example.ts]
import { client } from './viem.config'

const status = await client.wallet.sendCallsSync({
  calls: [
    {
      to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
      value: 69420n,
    },
  ],
  throwOnFailure: true, // [!code focus]
})
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, custom, walletActions } from 'viem'
import 'viem/window'

export const client = Client.create({
  transport: custom(window.ethereum!),
}).extend(walletActions())
```
:::

### Set a Polling Deadline

Set `pollingInterval` and `timeout` when the wallet needs a custom status polling window.

:::code-group
```ts twoslash [example.ts]
import { client } from './viem.config'

const status = await client.wallet.sendCallsSync({
  calls: [
    {
      to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
      value: 69420n,
    },
  ],
  pollingInterval: 1_000, // [!code focus]
  timeout: 30_000, // [!code focus]
})
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, custom, walletActions } from 'viem'
import 'viem/window'

export const client = Client.create({
  transport: custom(window.ethereum!),
}).extend(walletActions())
```
:::

### Batch Contract Calls

Provide an ABI and function name to encode contract calls without preparing calldata separately.

:::code-group
```ts twoslash [example.ts]
import { Abi } from 'viem/utils'
import { client } from './viem.config'

const { id } = await client.wallet.sendCalls({
  account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  calls: [ // [!code focus]
    { // [!code focus]
      abi: Abi.from(['function mint()']), // [!code focus]
      functionName: 'mint', // [!code focus]
      to: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', // [!code focus]
    }, // [!code focus]
  ], // [!code focus]
})
// @log: '0x...'
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, custom, walletActions } from 'viem'
import { mainnet } from 'viem/chains'
import 'viem/window'

export const client = Client.create({
  chain: mainnet,
  transport: custom(window.ethereum!),
}).extend(walletActions())
```
:::

### Require Atomic Execution

Set `forceAtomic` when every call must succeed or fail together. The wallet rejects the request if
it cannot guarantee atomic execution.

:::code-group
```ts twoslash [example.ts]
import { client } from './viem.config'

const { id } = await client.wallet.sendCalls({
  account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  calls: [
    {
      to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
      value: 1n,
    },
    {
      to: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC',
      value: 1n,
    },
  ],
  forceAtomic: true, // [!code focus]
})
// @log: '0x...'
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, custom, walletActions } from 'viem'
import { mainnet } from 'viem/chains'
import 'viem/window'

export const client = Client.create({
  chain: mainnet,
  transport: custom(window.ethereum!),
}).extend(walletActions())
```
:::

### Request a Paymaster Capability

Pass wallet-supported requirements through `capabilities`. This example accepts the paymaster URL
as an application value instead of assuming a service.

:::code-group
```ts twoslash [example.ts]
import { client } from './viem.config'

export async function sendSponsoredCalls(paymasterUrl: string) {
  return client.wallet.sendCalls({
    account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
    calls: [
      {
        to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
        value: 1n,
      },
    ],
    capabilities: { // [!code focus]
      paymasterService: { url: paymasterUrl }, // [!code focus]
    }, // [!code focus]
  })
}
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, custom, walletActions } from 'viem'
import { mainnet } from 'viem/chains'
import 'viem/window'

export const client = Client.create({
  chain: mainnet,
  transport: custom(window.ethereum!),
}).extend(walletActions())
```
:::

Define wallet-specific capability types through the
[`Capabilities` module](/docs/actions/capabilities).

### Fall Back to Transactions

Set `experimental_fallback` when the wallet might not support EIP-5792. Viem sends each call as a
separate `eth_sendTransaction` request, so the fallback is not atomic.

:::code-group
```ts twoslash [example.ts]
import { client } from './viem.config'

const { id } = await client.wallet.sendCalls({
  account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  calls: [
    {
      to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
      value: 1n,
    },
    {
      to: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC',
      value: 1n,
    },
  ],
  experimental_fallback: true, // [!code focus]
})
// @log: '0x...'
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, custom, walletActions } from 'viem'
import { mainnet } from 'viem/chains'
import 'viem/window'

export const client = Client.create({
  chain: mainnet,
  transport: custom(window.ethereum!),
}).extend(walletActions())
```
:::

Fallback is unavailable when a requested capability is required. Mark a capability as optional
only when sending without that capability is acceptable.

## Return Value

### Synchronous

`{ atomic: boolean; capabilities?: Capabilities.Extract<'getCallsStatus', 'ReturnType'>; chainId: number | undefined; id: string; receipts: readonly Receipt[]; status: 'pending' | 'success' | 'failure' | undefined; statusCode: number; version: string }`

The status and receipts of the call bundle. See
[`Actions.wallet.getCallsStatus`](/docs/actions/wallet/getCallsStatus#return-value).

### Asynchronous

`{ id: string; capabilities?: object }`

The identifier of the call batch (and any returned capabilities). Pass `id` to [`Actions.wallet.getCallsStatus`](/docs/actions/wallet/getCallsStatus) or [`Actions.wallet.waitForCallsStatus`](/docs/actions/wallet/waitForCallsStatus).

## Parameters

### account

* **Type:** `Account | Address | null`
* **Default:** `client.account`

The Account (or address) the calls are sent from.

```ts twoslash
import { Actions } from 'viem'
// [!include ~/snippets/docs/reference-client.ts:setup]
// ---cut---
const { id } = await Actions.wallet.sendCalls(client, {
  account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e', // [!code focus]
  calls: [{ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' }],
})
```

### calls

* **Type:** `Call[]`

The batch of calls to send.
Each call contains raw call data or contract function parameters.

```ts twoslash
import { Actions } from 'viem'
import { Abi } from 'viem/utils'
// [!include ~/snippets/docs/reference-client.ts:setup]
// ---cut---
const { id } = await Actions.wallet.sendCalls(client, {
  calls: [ // [!code focus]
    { to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8', value: 1n }, // [!code focus]
    { // [!code focus]
      abi: Abi.from(['function mint()']), // [!code focus]
      functionName: 'mint', // [!code focus]
      to: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', // [!code focus]
    }, // [!code focus]
  ], // [!code focus]
})
```

### capabilities

* **Type:** `Capabilities`

Capabilities to request from the wallet, such as a paymaster service.

```ts twoslash
import { Actions } from 'viem'
// [!include ~/snippets/docs/reference-client.ts:setup]
// ---cut---
const { id } = await Actions.wallet.sendCalls(client, {
  calls: [{ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' }],
  capabilities: { // [!code focus]
    paymasterService: { // [!code focus]
      url: 'https://...', // [!code focus]
    }, // [!code focus]
  }, // [!code focus]
})
```

### chain

* **Type:** `Chain`
* **Default:** `client.chain`

The chain the calls target.

```ts twoslash
import { Actions } from 'viem'
import { mainnet } from 'viem/chains'
// [!include ~/snippets/docs/reference-client.ts:setup]
// ---cut---
const { id } = await Actions.wallet.sendCalls(client, {
  calls: [{ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' }],
  chain: mainnet, // [!code focus]
})
```

### experimental\_fallback

* **Type:** `boolean`

Whether to fall back to `eth_sendTransaction` when the wallet does not support EIP-5792.

```ts twoslash
import { Actions } from 'viem'
// [!include ~/snippets/docs/reference-client.ts:setup]
// ---cut---
const { id } = await Actions.wallet.sendCalls(client, {
  calls: [{ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' }],
  experimental_fallback: true, // [!code focus]
})
```

### experimental\_fallbackDelay

* **Type:** `number`
* **Default:** `32`

Delay (in ms) between fallback transactions.

```ts twoslash
import { Actions } from 'viem'
// [!include ~/snippets/docs/reference-client.ts:setup]
// ---cut---
const { id } = await Actions.wallet.sendCalls(client, {
  calls: [{ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' }],
  experimental_fallback: true,
  experimental_fallbackDelay: 100, // [!code focus]
})
```

### forceAtomic

* **Type:** `boolean`
* **Default:** `false`

Whether the calls must be executed atomically.

```ts twoslash
import { Actions } from 'viem'
// [!include ~/snippets/docs/reference-client.ts:setup]
// ---cut---
const { id } = await Actions.wallet.sendCalls(client, {
  calls: [{ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' }],
  forceAtomic: true, // [!code focus]
})
```

### id

* **Type:** `string`

A caller-supplied identifier for the call batch.

```ts twoslash
import { Actions } from 'viem'
// [!include ~/snippets/docs/reference-client.ts:setup]
// ---cut---
const { id } = await Actions.wallet.sendCalls(client, {
  calls: [{ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' }],
  id: '0xdeadbeef', // [!code focus]
})
```

### pollingInterval

* **Type:** `number`
* **Default:** `client.pollingInterval`

Polling frequency, in milliseconds, while `sendCallsSync` waits for confirmation.

```ts twoslash
import { Actions } from 'viem'
// [!include ~/snippets/docs/reference-client.ts:setup]
// ---cut---
const status = await Actions.wallet.sendCallsSync(client, {
  calls: [{ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' }],
  pollingInterval: 1_000, // [!code focus]
})
```

### status

* **Type:** `(result: Actions.wallet.getCallsStatus.ReturnType) => boolean`
* **Default:** `({ statusCode }) => statusCode === 200 || statusCode >= 300`

The predicate that determines when `sendCallsSync` stops waiting.

```ts twoslash
import { Actions } from 'viem'
// [!include ~/snippets/docs/reference-client.ts:setup]
// ---cut---
const status = await Actions.wallet.sendCallsSync(client, {
  calls: [{ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' }],
  status: ({ status }) => status === 'success', // [!code focus]
})
```

### throwOnFailure

* **Type:** `boolean`
* **Default:** `false`

Whether `sendCallsSync` throws if the call bundle fails.

```ts twoslash
import { Actions } from 'viem'
// [!include ~/snippets/docs/reference-client.ts:setup]
// ---cut---
const status = await Actions.wallet.sendCallsSync(client, {
  calls: [{ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' }],
  throwOnFailure: true, // [!code focus]
})
```

### timeout

* **Type:** `number`
* **Default:** `Math.max((chain.blockTime ?? 0) * 3, 5_000)`

Timeout, in milliseconds, before `sendCallsSync` stops waiting.

```ts twoslash
import { Actions } from 'viem'
// [!include ~/snippets/docs/reference-client.ts:setup]
// ---cut---
const status = await Actions.wallet.sendCallsSync(client, {
  calls: [{ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' }],
  timeout: 30_000, // [!code focus]
})
```

### version

* **Type:** `string`
* **Default:** `'2.0.0'`

The EIP-5792 version to use.

```ts twoslash
import { Actions } from 'viem'
// [!include ~/snippets/docs/reference-client.ts:setup]
// ---cut---
const { id } = await Actions.wallet.sendCalls(client, {
  calls: [{ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' }],
  version: '2.0.0', // [!code focus]
})
```

## Errors

| Error | Description |
| --- | --- |
| `Actions.wallet.Errors.AtomicityNotSupportedError` | `forceAtomic` was set with multiple calls on fallback to `eth_sendTransaction`. |
| `Actions.wallet.Errors.BundleFailedError` | The call bundle failed and `throwOnFailure` was enabled. |
| `Actions.wallet.Errors.UnsupportedNonOptionalCapabilityError` | A non-optional capability was requested on fallback to `eth_sendTransaction`. |
| `Actions.wallet.Errors.WaitForCallsStatusTimeoutError` | Timed out while waiting for the call bundle to be confirmed. |
