Skip to main content
Batch transactions allow your app to send multiple operations in a single request. This is useful for executing multi-step workflows — such as approving and swapping tokens, distributing funds to multiple recipients, or performing complex DeFi operations — without requiring separate transactions for each step.

How it works

Privy supports batch transactions on both EVM and Solana chains, but the mechanism differs for each.

EVM

On EVM chains, Privy uses the wallet_sendCalls RPC method to send multiple calls in a single atomic batch. Under the hood, Privy leverages EIP-7702 to upgrade your user’s wallet to a Kernel smart contract, which enables batched execution.
  • Without sponsorship: The wallet executes a self.execute call on the upgraded Kernel contract, bundling all calls into a single atomic transaction.
  • With sponsorship: Privy routes the batch through a bundler and paymaster, which covers the gas fees on behalf of the user. Set sponsor to true in the request body to enable this.
In both cases, batch calls are atomic — either all calls succeed, or the entire batch reverts. This ensures consistent state and prevents partial execution.

Solana

On Solana, batch behavior is achieved by adding multiple instructions to a single Transaction. The Solana runtime processes all instructions in a transaction sequentially, and the transaction is atomic — if any instruction fails, the entire transaction is reverted. Learn more about sending Solana transactions in the Solana recipes.

Sending batch transactions on EVM

Use the wallet_sendCalls method via the Privy wallets RPC endpoint to send multiple calls in a single batch.

Example: sending two transfers

Example: approve and swap in one batch

A common use case is combining an ERC-20 approval with a swap in a single atomic batch:
import {encodeFunctionData, erc20Abi} from 'viem';

// Encode the approval call
const approveData = encodeFunctionData({
  abi: erc20Abi,
  functionName: 'approve',
  args: ['0xSwapRouterAddress', BigInt(1000000)] // Approve 1 USDC (6 decimals)
});

// Encode the swap call (example ABI)
const swapData = encodeFunctionData({
  abi: swapRouterAbi,
  functionName: 'exactInputSingle',
  args: [swapParams]
});

const response = await privy.wallets().rpc({
  walletId: 'insert-wallet-id',
  method: 'wallet_sendCalls',
  caip2: 'eip155:8453',
  params: {
    calls: [
      {
        to: '0xUSDCContractAddress',
        data: approveData
      },
      {
        to: '0xSwapRouterAddress',
        data: swapData
      }
    ]
  }
});

With gas sponsorship

To sponsor gas for the batch transaction, set sponsor to true:
curl --request POST \
  --url https://api.privy.io/v1/wallets/{wallet_id}/rpc \
  --header 'Authorization: Basic <encoded-value>' \
  --header 'Content-Type: application/json' \
  --header 'privy-app-id: <privy-app-id>' \
  --data '{
  "method": "wallet_sendCalls",
  "caip2": "eip155:8453",
  "chain_type": "ethereum",
  "sponsor": true,
  "params": {
    "calls": [
      {
        "to": "0xRecipientAddress1",
        "value": "0x2386F26FC10000"
      },
      {
        "to": "0xRecipientAddress2",
        "value": "0x2386F26FC10000"
      }
    ]
  }
}'

Response

A successful request returns a transaction_id and the caip2 chain identifier:
{
  "method": "wallet_sendCalls",
  "data": {
    "transaction_id": "b4966a89-8983-4b1b-a93a-b104799527f5",
    "caip2": "eip155:8453"
  }
}
Use the transaction_id to track the status of the transaction.

Sending batch transactions on Solana

On Solana, batching is done by adding multiple instructions to a single transaction. See the Sending SOL recipe for a complete walkthrough. Here is an example of batching two SOL transfers in a single transaction: Then sign and send the transaction using any of the Privy SDKs as shown in the Sending SOL recipe.

Next steps