Smart Accounts with Payments

Learn how to leverage EIP7702 smart accounts to batch Payments transactions for optimal user experience. This approach enables gasless transactions, batched execution, and seamless cross-chain operations.

Smart accounts with EIP7702 allow you to upgrade any EOA (Externally Owned Account) into a smart account without code changes, enabling advanced features like transaction batching and gas sponsorship.


  • Install the SDK

    npm i thirdweb
  • Set up EIP7702 In-App Wallet

    Configure an in-app wallet with EIP7702 execution mode to enable smart account features:

    import { createThirdwebClient } from "thirdweb";
    import { inAppWallet } from "thirdweb/wallets/in-app";
    const client = createThirdwebClient({
    clientId: "your_client_id",
    });
    // Create in-app wallet with EIP7702 smart account features
    const wallet = inAppWallet({
    executionMode: {
    mode: "EIP7702",
    sponsorGas: true, // Enable gas sponsorship
    },
    });
    // Connect the wallet
    const account = await wallet.connect({
    client,
    strategy: "google", // or other auth strategies
    });
  • Prepare Batched Bridge Transactions

    Use Payments to prepare transactions, then batch them per step (since each step may be on a different chain):

    import { Bridge, NATIVE_TOKEN_ADDRESS, toWei } from "thirdweb";
    import { sendBatchTransaction } from "thirdweb";
    const bridgePreparation = await Bridge.Buy.prepare({
    originChainId: 1, // Ethereum
    originTokenAddress: NATIVE_TOKEN_ADDRESS,
    destinationChainId: 137, // Polygon
    destinationTokenAddress: NATIVE_TOKEN_ADDRESS,
    amount: toWei("0.1"), // 0.1 MATIC
    sender: account.address,
    receiver: account.address,
    client,
    });
  • Execute Batched Transactions

    Execute transactions in batches per step (same chain), proceeding through steps sequentially:

    import { sendBatchTransaction, waitForReceipt } from "thirdweb";
    // Execute each step's transactions as a batch (same chain)
    for (let i = 0; i < bridgePreparation.steps.length; i++) {
    const step = bridgePreparation.steps[i];
    // Batch all transactions within this step (they're all on the same chain)
    const stepBatchResult = await sendBatchTransaction({
    transactions: step.transactions,
    account,
    });
    console.log(
    `Step ${i + 1} batch sent:`,
    stepBatchResult.transactionHash,
    );
    const receipt = await waitForReceipt({
    client,
    chain: step.transactions[0].chain,
    transactionHash: stepBatchResult.transactionHash,
    });
    console.log(`Step ${i + 1} completed:`, receipt.status);
    // Monitor bridge completion status for this step
    let bridgeStatus;
    do {
    bridgeStatus = await Bridge.status({
    transactionHash: stepBatchResult.transactionHash,
    chainId: step.transactions[0].chainId,
    client,
    });
    if (bridgeStatus.status === "PENDING") {
    console.log(`Bridge step ${i + 1} still pending...`);
    await new Promise((resolve) => setTimeout(resolve, 5000));
    }
    } while (bridgeStatus.status === "PENDING");
    if (bridgeStatus.status === "COMPLETED") {
    console.log(`Bridge step ${i + 1} completed!`);
    } else if (bridgeStatus.status === "FAILED") {
    throw new Error(`Bridge step ${i + 1} failed`);
    }
    }

Next Steps