Overview
Wagmi is a collection of React hooks for Ethereum Virtual Machine (EVM) compatible networks that makes it easy to work with wallets, contracts, transactions, and signing. Base Account integrates perfectly with Wagmi, allowing you to use all your familiar hooks. You can jump ahead and use the Base Account Wagmi Template to get started.Base Account Wagmi Templatehttps://github.com/base/demos/tree/master/base-account/base-account-wagmi-template
Setup
Make sure you have set up Wagmi with Base Account before following this guide.Basic Batch Transaction
Send multiple ETH transfers in a single transaction by creating a component that uses thesendCalls method and adding a button to trigger the transaction.
"use client";
import { useState } from "react";
import { useSendCalls } from "wagmi";
import { encodeFunctionData, parseUnits } from "viem";
import { baseSepolia } from "wagmi/chains";
// USDC contract address on Base Sepolia
const USDC_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e";
// ERC20 ABI for the transfer function
const erc20Abi = [
{
inputs: [
{ name: "to", type: "address" },
{ name: "amount", type: "uint256" },
],
name: "transfer",
outputs: [{ name: "", type: "bool" }],
stateMutability: "nonpayable",
type: "function",
},
] as const;
export function BatchTransactions() {
const { sendCalls, data, isPending, isSuccess, error } = useSendCalls();
const [amount1, setAmount1] = useState("1");
const [amount2, setAmount2] = useState("1");
const [usePaymaster, setUsePaymaster] = useState(false);
async function handleBatchTransfer() {
try {
// Encode the first transfer call
const call1Data = encodeFunctionData({
abi: erc20Abi,
functionName: "transfer",
args: [
"0x2211d1D0020DAEA8039E46Cf1367962070d77DA9",
parseUnits(amount1, 6), // USDC has 6 decimals
],
});
// Encode the second transfer call
const call2Data = encodeFunctionData({
abi: erc20Abi,
functionName: "transfer",
args: [
"0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
parseUnits(amount2, 6), // USDC has 6 decimals
],
});
// Prepare capabilities object if paymaster is enabled
const capabilities = usePaymaster
? {
paymasterService: {
url: process.env.NEXT_PUBLIC_PAYMASTER_URL || "https://api.developer.coinbase.com/rpc/v1/base-sepolia",
},
}
: undefined;
// Send the batch of calls
sendCalls({
calls: [
{
to: USDC_ADDRESS,
data: call1Data,
},
{
to: USDC_ADDRESS,
data: call2Data,
},
],
chainId: baseSepolia.id,
capabilities,
});
} catch (err) {
console.error("Error batching transactions:", err);
}
}
return (
<div>
<h2>Batch USDC Transfers</h2>
<div>
<div>
<label>Amount 1 (USDC):</label>
<input
type="number"
value={amount1}
onChange={(e) => setAmount1(e.target.value)}
placeholder="1"
step="0.000001"
min="0"
/>
</div>
<div>
<label>Amount 2 (USDC):</label>
<input
type="number"
value={amount2}
onChange={(e) => setAmount2(e.target.value)}
placeholder="1"
step="0.000001"
min="0"
/>
</div>
<div>
<label>
<input
type="checkbox"
checked={usePaymaster}
onChange={(e) => setUsePaymaster(e.target.checked)}
/>
Use Paymaster (sponsor gas fees)
</label>
</div>
<button onClick={handleBatchTransfer} disabled={isPending}>
{isPending ? "Sending..." : "Send Batch Transfer"}
</button>
</div>
{isPending && <div>Transaction pending...</div>}
{isSuccess && data && (
<div>
<p>Batch sent successfully!</p>
<p>Batch ID: {data.id}</p>
</div>
)}
{error && <div>Error: {error.message}</div>}
</div>
);
}
"use client";
import { useAccount, useConnect, useDisconnect } from "wagmi";
import { SignInWithBase } from "../components/SignInWithBase";
import { BatchTransactions } from "../components/BatchTransactions";
function App() {
const account = useAccount();
const { connectors, connect, status, error } = useConnect();
const { disconnect } = useDisconnect();
return (
<>
<div>
<h2>Account</h2>
<div>
status: {account.status}
<br />
addresses: {JSON.stringify(account.addresses)}
<br />
chainId: {account.chainId}
</div>
{account.status === "connected" && (
<button type="button" onClick={() => disconnect()}>
Disconnect
</button>
)}
</div>
<div>
<h2>Connect</h2>
{connectors.map((connector) => {
if (connector.name === "Base Account") {
return (
<SignInWithBase key={connector.uid} connector={connector} />
);
} else {
return (
<button
key={connector.uid}
onClick={() => connect({ connector })}
type="button"
>
{connector.name}
</button>
);
}
})}
<div>{status}</div>
<div>{error?.message}</div>
</div>
{account.status === "connected" && <BatchTransactions />}
</>
);
}
export default App;
You don’t need to “Connect the wallet” firstBase Account allows you to prompt the user for sending the transaction using the
sendCalls method without needing to “Connect the wallet” (ie. using eth_requestAccounts) first.