Why Batching?
- One signature for complex flows
- Atomic execution—no stuck states
- Lower gas costs than separate transactions
- Composable—output of one call feeds into the next
Basic Batch
Copy
Ask AI
const approveInstruction = await account.buildComposable({
type: "approve",
data: {
spender: UNISWAP_ROUTER,
tokenAddress: USDC,
chainId: base.id,
amount: parseUnits("100", 6)
}
});
const swapInstruction = await account.buildComposable({
type: "default",
data: {
chainId: base.id,
to: UNISWAP_ROUTER,
abi: UniswapAbi,
functionName: "exactInputSingle",
args: [{ tokenIn: USDC, tokenOut: WETH, amountIn: parseUnits("100", 6), /* ... */ }]
}
});
// Execute both in one transaction
const quote = await meeClient.getQuote({
instructions: [approveInstruction, swapInstruction],
feeToken: { address: USDC, chainId: base.id }
});
const { hash } = await meeClient.executeQuote({ quote });
Composable Operations
Use runtime injection when the next step depends on the previous output:Copy
Ask AI
import { runtimeERC20BalanceOf } from "@biconomy/abstractjs";
import { balanceNotZeroConstraint } from "../utils/balanceNotZero.util";
// Step 1: Swap USDC → WETH
const swap = await account.buildComposable({
type: "default",
data: {
chainId: base.id,
to: UNISWAP_ROUTER,
abi: UniswapAbi,
functionName: "exactInputSingle",
args: [{
tokenIn: USDC,
tokenOut: WETH,
amountIn: parseUnits("100", 6),
amountOutMinimum: 0n,
// ...
}]
}
});
// Step 2: Deposit ALL received WETH into Morpho
const deposit = await account.buildComposable({
type: "default",
data: {
chainId: base.id,
to: MORPHO_POOL,
abi: MorphoAbi,
functionName: "deposit",
args: [
runtimeERC20BalanceOf({
tokenAddress: WETH,
targetAddress: account.addressOn(base.id, true),
constraints: [balanceNotZeroConstraint]
}),
account.addressOn(base.id, true)
]
}
});
const quote = await meeClient.getQuote({
instructions: [swap, deposit],
feeToken: { address: USDC, chainId: base.id }
});
Fusion Mode (External Wallets)
For MetaMask/Rabby users, use a trigger to fund the operation:Copy
Ask AI
const trigger = {
chainId: base.id,
tokenAddress: USDC,
amount: parseUnits("100", 6)
};
const quote = await meeClient.getFusionQuote({
trigger,
instructions: [approveInstruction, swapInstruction, depositInstruction],
feeToken: { address: USDC, chainId: base.id }
});
const { hash } = await meeClient.executeFusionQuote({ fusionQuote: quote });
Example: Swap → Stake in One Click
Copy
Ask AI
import { runtimeERC20BalanceOf } from "@biconomy/abstractjs";
import { balanceNotZeroConstraint } from "../utils/balanceNotZero.util";
const USDC = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
const WETH = "0x4200000000000000000000000000000000000006";
const MORPHO_POOL = "0xA2Cac0023a4797b4729Db94783405189a4203AFc";
// 1. Approve Uniswap
const approve = await account.buildComposable({
type: "approve",
data: { spender: UNISWAP_ROUTER, tokenAddress: USDC, chainId: base.id, amount: inputAmount }
});
// 2. Swap USDC → WETH
const swap = await account.buildComposable({
type: "default",
data: {
chainId: base.id,
to: UNISWAP_ROUTER,
abi: UniswapAbi,
functionName: "exactInputSingle",
args: [{ tokenIn: USDC, amountIn: inputAmount, tokenOut: WETH, /* ... */ }]
}
});
// 3. Approve Morpho
const approveMorpho = await account.buildComposable({
type: "approve",
data: {
spender: MORPHO_POOL,
tokenAddress: WETH,
chainId: base.id,
amount: runtimeERC20BalanceOf({
tokenAddress: WETH,
targetAddress: account.addressOn(base.id, true),
constraints: [balanceNotZeroConstraint]
})
}
});
// 4. Deposit to Morpho
const deposit = await account.buildComposable({
type: "default",
data: {
chainId: base.id,
to: MORPHO_POOL,
abi: [{ name: "deposit", inputs: [{ name: "assets", type: "uint256" }, { name: "receiver", type: "address" }], type: "function" }],
functionName: "deposit",
args: [
runtimeERC20BalanceOf({
tokenAddress: WETH,
targetAddress: account.addressOn(base.id, true),
constraints: [balanceNotZeroConstraint]
}),
account.addressOn(base.id, true)
]
}
});
// Execute all four operations with one signature
const quote = await meeClient.getQuote({
instructions: [approve, swap, approveMorpho, deposit],
feeToken: { address: USDC, chainId: base.id }
});
const { hash } = await meeClient.executeQuote({ quote });
Next Steps
Cross-Chain Orchestration
Execute flows across multiple chains