Skip to content

How to submit batch transactions

One benefit of Smart Contract Accounts is that it is possible to batch transactions in one UserOperation (UO). Not all Smart Contract Accounts support batching. But, if the SmartContractAccount implementation you are using has the encodeBatchExecute method, then implementations of SmartAccountClient will allow you to make those calls.

There are two ways you can batch transactions using SmartAccountClient:

  1. via sendUserOperation
  2. via sendTransactions

Note 1: LightSmartContractAccount, and MultiOwnerModularAccount

Both LightSmartContractAccount and MultiOwnerModularAccount implement encodeBatchExecute, thus supports batching UserOperations out of the box.

Note 2: Transactions Batched as a Single User Operation

When you batch transactions, the transaction actions (targets and calldatas) are batched into a single UO, where the sender is the account itself.

Note 3: Batched Transactions Ordering

The batched UO gets executed by the account calling the executeBatch method on LightAccount or Modular Account smart contracts. executeBatch processes the input array of transactions data linearly, guaranteeing the execution order of those transactions to be sequential.

Batching using sendUserOperation

The SmartAccountClient supports passing either a single UO or an array of UOs to sendUserOperation. If you pass an array, the client will batch the transactions into a single User Operation and submit it to the bundler. Let's see an example:

ts
import { smartAccountClient } from "./smartAccountClient";

// the hash returned here is the hash of the User Operation
const { hash } = await smartAccountClient.sendUserOperation({
  uo: [
    {
      target: "0x...",
      data: "0xcallDataTransacation1",
    },
    {
      target: "0x...",
      data: "0xcallDataTransacation2",
    },
  ],
});
ts
import { createModularAccountAlchemyClient } from "@alchemy/aa-alchemy";
import { LocalAccountSigner, sepolia } from "@alchemy/aa-core";

export const chain = sepolia;

export const smartAccountClient = await createModularAccountAlchemyClient({
  apiKey: "YOUR_API_KEY",
  chain,
  // you can swap this out for any SmartAccountSigner
  signer: LocalAccountSigner.mnemonicToAccountSigner("OWNER_MNEMONIC"),
});

Batching using sendTransactions

The SmartAccountClient supports sending UOs and waiting for them to be mined in a transaction via the sendTransaction and sendTransactions methods. The latter allows for batching in the same way sendUserOperation:

ts
import { smartAccountClient } from "./smartAccountClient";

// the hash returned here is the hash of the mined Tx that includes the UserOperation
const hash = await smartAccountClient.sendTransactions({
  requests: [
    {
      to: "0x...",
      data: "0xcallDataTransacation1",
    },
    {
      to: "0x...",
      data: "0xcallDataTransacation2",
    },
  ],
});
ts
import { createModularAccountAlchemyClient } from "@alchemy/aa-alchemy";
import { LocalAccountSigner, sepolia } from "@alchemy/aa-core";

export const chain = sepolia;

export const smartAccountClient = await createModularAccountAlchemyClient({
  apiKey: "YOUR_API_KEY",
  chain,
  // you can swap this out for any SmartAccountSigner
  signer: LocalAccountSigner.mnemonicToAccountSigner("OWNER_MNEMONIC"),
});