buildComposable
Build a composable instruction with support for runtime injection, conditions, and automatic encoding.
const instruction = await account.buildComposable(options);
Instruction Types
| Type | Description |
|---|
default | Generic contract call |
transfer | ERC-20 token transfer |
approve | ERC-20 approval |
nativeTokenTransfer | Native token (ETH) transfer |
Default Type
Call any contract function.
const instruction = await account.buildComposable({
type: "default",
data: {
chainId: number;
to: Address;
abi: Abi;
functionName: string;
args: any[];
value?: bigint;
gasLimit?: bigint;
conditions?: Condition[];
}
});
Parameters
| Parameter | Type | Required | Description |
|---|
chainId | number | Yes | Target chain |
to | Address | Yes | Contract address |
abi | Abi | Yes | Contract ABI |
functionName | string | Yes | Function to call |
args | any[] | Yes | Function arguments |
value | bigint | No | Native value to send |
gasLimit | bigint | No | Custom gas limit |
conditions | Condition[] | No | Execution conditions |
Example
const swap = await account.buildComposable({
type: "default",
data: {
chainId: 8453,
to: UNISWAP_ROUTER,
abi: UniswapAbi,
functionName: "exactInputSingle",
args: [{
tokenIn: USDC,
tokenOut: WETH,
amountIn: parseUnits("100", 6),
amountOutMinimum: 0n,
recipient: account.addressOn(8453, true),
fee: 500,
sqrtPriceLimitX96: 0n
}]
}
});
Transfer Type
Simplified ERC-20 token transfer.
const instruction = await account.buildComposable({
type: "transfer",
data: {
chainId: number;
tokenAddress: Address;
recipient: Address;
amount: bigint | RuntimeValue;
conditions?: Condition[];
}
});
Example
const transfer = await account.buildComposable({
type: "transfer",
data: {
chainId: 8453,
tokenAddress: USDC,
recipient: "0x...",
amount: parseUnits("50", 6)
}
});
Approve Type
Simplified ERC-20 approval.
const instruction = await account.buildComposable({
type: "approve",
data: {
chainId: number;
tokenAddress: Address;
spender: Address;
amount: bigint | RuntimeValue;
}
});
Example
const approve = await account.buildComposable({
type: "approve",
data: {
chainId: 8453,
tokenAddress: USDC,
spender: UNISWAP_ROUTER,
amount: parseUnits("100", 6)
}
});
Native Token Transfer
Send ETH or native tokens.
const instruction = await account.buildComposable({
type: "nativeTokenTransfer",
data: {
chainId: number;
to: Address;
value: bigint | RuntimeValue;
}
});
Example
const sendEth = await account.buildComposable({
type: "nativeTokenTransfer",
data: {
chainId: 8453,
to: "0x...",
value: parseEther("0.1")
}
});
Bridge Operations
To bridge tokens (e.g. via Across Protocol), use type: "default" and encode the bridge protocol’s contract call directly. See the Across integration guide for a complete example.
const bridge = await account.buildComposable({
type: "default",
data: {
chainId: 42161, // Source chain
to: ACROSS_SPOKE_POOL, // Bridge contract
abi: acrossSpokePoolAbi, // Bridge ABI
functionName: "depositV3",
args: [
account.addressOn(42161, true), // depositor
account.addressOn(8453, true), // recipient
USDC_ARBITRUM, // inputToken
USDC_BASE, // outputToken
parseUnits("100", 6), // inputAmount
outputAmount, // outputAmount (from bridge quote API)
8453, // destinationChainId
zeroAddress, // exclusiveRelayer
quoteTimestamp, // quoteTimestamp
fillDeadline, // fillDeadline
0, // exclusivityDeadline
"0x" // message
]
}
});
Bridge operations use the same type: "default" as any other contract call. Get bridge parameters (output amount, timestamps, deadlines) from the bridge protocol’s quote API before building the instruction.
build (Simple)
Build a simple instruction without composability.
const instruction = await account.build({
type: "nativeTokenTransfer",
data: {
chainId: 8453,
to: "0x...",
value: 1n,
lowerBoundTimestamp: Math.floor(Date.now() / 1000),
upperBoundTimestamp: Math.floor(Date.now() / 1000) + 300
}
});
Time Bounds
Add time constraints to instructions:
const instruction = await account.buildComposable({
type: "default",
data: {
chainId: 8453,
to: "0x...",
abi: [...],
functionName: "doSomething",
args: [],
lowerBoundTimestamp: Math.floor(Date.now() / 1000) + 60, // Start in 1 min
upperBoundTimestamp: Math.floor(Date.now() / 1000) + 300 // Expire in 5 min
}
});
| Parameter | Description |
|---|
lowerBoundTimestamp | Earliest execution time (unix seconds) |
upperBoundTimestamp | Latest execution time (unix seconds) |