Batching transactions is the ability to include a number of transactions within one block to save the user both gas, time, and clicks.

Here we’ll show a code example of how easy it is to batch transactions using the Modular SDK.

We’ll be using the addUserOpsToBatch function for this.

import { ethers } from 'ethers';
import { ModularSdk } from '@etherspot/modular-sdk';
import { printOp } from '../src/sdk/common/OperationUtils';

const recipient1: string = '0x10a1874E1046B1cc5deFdf4D3153838B72fF94Ac'; // recipient1 wallet address
const recipient2: string = '0x20a1874E1046B1cc5deFdf4D3153838B72fF94Ac'; // recipient2 wallet address
const recipient3: string = '0x30a1874E1046B1cc5deFdf4D3153838B72fF94Ac'; // recipient3 wallet address
const value: string = '0.01'; // transfer value

async function main() {
  // initializating sdk...
  const modularSdk = new ModularSdk(
    { 
      privateKey: process.env.WALLET_PRIVATE_KEY 
    }, 
    { 
      chainId: Number(process.env.CHAIN_ID), 
      bundlerProvider: new EtherspotBundler(Number(process.env.CHAIN_ID), 
      bundlerApiKey, customBundlerUrl) 
    }
  );

  // add transaction 1 to the batch
  let transactionBatch = await modularSdk.addUserOpsToBatch({to: recipient1, value: ethers.utils.parseEther(value)});

  // add transaction 2 to the batch
  transactionBatch = await modularSdk.addUserOpsToBatch({to: recipient2, value: ethers.utils.parseEther(value)});

  // add transaction 3 to the batch
  transactionBatch = await modularSdk.addUserOpsToBatch({to: recipient3, value: ethers.utils.parseEther(value)});

  // estimate transactions added to the batch and get the fee data for the UserOp
  const op = await modularSdk.estimate();
  console.log(`Estimate UserOp: ${await printOp(op)}`);

  // sign the UserOp and sending to the bundler...
  const uoHash = await modularSdk.send(op);
  console.log(`UserOpHash: ${uoHash}`);

  // get transaction hash...
  console.log('Waiting for transaction...');
  let userOpsReceipt = null;
  const timeout = Date.now() + 60000; // 1 minute timeout
  while((userOpsReceipt == null) && (Date.now() < timeout)) {
    await sleep(2);
    userOpsReceipt = await modularSdk.getUserOpReceipt(uoHash);
  }
  console.log('\x1b[33m%s\x1b[0m', `Transaction Receipt: `, userOpsReceipt);
}

main()
  .catch(console.error)
  .finally(() => process.exit());