Skip to content

Batch Transactions

One of the most powerful features of ERC-4337 Smart Accounts is the ability to batch multiple transactions together into a single UserOperation.

In traditional Web3 applications, standard EOAs force users into frustrating UX patterns:

  1. “Approve this token” $\rightarrow$ Wait for block $\rightarrow$ Sign $\rightarrow$ Pay Gas
  2. “Now execute the swap” $\rightarrow$ Wait for block $\rightarrow$ Sign $\rightarrow$ Pay Gas

With Smart Accounts, you can group both the Approve and the Swap actions into a single array. The user signs once, pays gas once (or the Paymaster covers it entirely), and the entire batch executes atomically. If one call in the batch reverts, the entire batch reverts.

To send a batch, pass an array of transaction objects to smartAccount.sendTransaction or client.sendBatchTransactions (if using 0xgas-auth).

import { encodeFunctionData, parseAbi } from "viem";
const usdcContract = "0x...";
const swapRouter = "0x...";
// 1. Prepare Approve call
const approveData = encodeFunctionData({
abi: parseAbi(["function approve(address spender, uint256 amount)"]),
functionName: "approve",
args: [swapRouter, 1000000n], // Approve $1.00 USDC
});
// 2. Prepare Swap call
const swapData = encodeFunctionData({
abi: parseAbi(["function exactInputSingle(tuple params)"]),
functionName: "exactInputSingle",
args: [{ /* swap params */ }],
});
// 3. Send the batch
const userOpResponse = await smartAccount.sendTransaction([
{
to: usdcContract,
value: 0n,
data: approveData,
},
{
to: swapRouter,
value: 0n,
data: swapData,
}
]);
// 4. Wait for confirmation
const receipt = await userOpResponse.wait();
console.log("Batch executed atomically in tx:", receipt.receipt.transactionHash);

Batched transactions execute exactly in the order they appear in the array.

  1. Call 1: Sent to usdcContract (Approve)
  2. Call 2: Sent to swapRouter (Swap)

Because they are executed within the same Ethereum transaction (wrapped by the Bundler), they are atomic. The approval guarantees the router has allowance immediately in the next EVM execution step. You never have to wait for separate blocks.