Bridge and Execute
Bridge a token and execute a contract call on the destination chain in a single transaction.
Note
SET UP THE SDK BEFORE YOU START:Install and initialize the client first — see Installation and SDK Setup.
bridgeAndExecute() function to bridge a token and execute a contract function on the recipient chain in a single flow.
Use the simulateBridgeAndExecute() function to simulate bridgeAndExecute() before sending an actual transaction.
Method signature
bridgeAndExecute(
params: BridgeAndExecuteParams,
options?: BridgeAndExecuteOptions,
): Promise<BridgeAndExecuteResult>
simulateBridgeAndExecute(
params: BridgeAndExecuteParams,
): Promise<BridgeAndExecuteSimulationResult>Parameters
export interface BridgeAndExecuteParams {
toChainId: number;
toTokenSymbol: string;
toAmountRaw: bigint;
sources?: number[];
execute: Omit<ExecuteParams, 'toChainId'>;
enableTransactionPolling?: boolean;
transactionTimeout?: number;
waitForReceipt?: boolean;
receiptTimeout?: number;
requiredConfirmations?: number;
recentApprovalTxHash?: string;
}
export interface ExecuteParams {
toChainId: number;
to: Hex;
value?: bigint;
data?: Hex;
gas?: bigint;
gasPrice?: 'low' | 'medium' | 'high';
enableTransactionPolling?: boolean;
transactionTimeout?: number;
// Transaction receipt confirmation options
waitForReceipt?: boolean;
receiptTimeout?: number;
requiredConfirmations?: number;
tokenApproval?: {
toTokenSymbol: string;
amount: bigint;
spender: Hex;
};
}BridgeAndExecuteParams: Parameters for using thebridgeAndExecute()function.toChainId(number, required): The chain ID of the destination chain.toTokenSymbol(string, required): The symbol of the token to be bridged in this flow (e.g.'USDC').toAmountRaw(bigint, required): The amount of tokens to be used in this flow, in raw integer units.sources(number[], optional): The chain IDs of the source chains to be used for the bridge. Useful if you want to maintain your holdings on some chains.execute(Omit<ExecuteParams, 'toChainId'>, required): The contract call on the destination chain.toChainIdis inherited from the top-leveltoChainId.enableTransactionPolling(boolean, optional): Whether to enable transaction polling. Defaults tofalse.transactionTimeout(number, optional)waitForReceipt(boolean, optional)receiptTimeout(number, optional)requiredConfirmations(number, optional)recentApprovalTxHash(string, optional)
options:BridgeAndExecuteOptions(optional): Top-level intent hook, abeforeExecutehook, event listener, and fill timeout.
export type BridgeAndExecuteOptions = {
onIntent?: (data: BridgeAndExecuteOnIntentHookData) => void;
beforeExecute?: () => Promise<{ value?: bigint; data?: Hex; gas?: bigint }>;
onEvent?: (event: BridgeAndExecuteEvent) => void;
fillTimeoutMinutes?: number;
};onIntent(optional): Called at the top level (not underhooks) with the composite intent before execution. Calldata.allow()/data.deny(), ordata.refresh(sources?)to re-quote. Readdata.intent.bridgeRequiredto detect whether a bridge is needed. When omitted, the intent is auto-approved.beforeExecute(optional): Called just before the execute transaction is sent; return overrides forvalue/data/gas(for example, to inject freshly quoted calldata).onEvent(optional): Callback that receives the typedBridgeAndExecuteEventunion as the operation progresses.fillTimeoutMinutes(optional): How long to wait for the bridge to be filled before timing out. Defaults to2.
Note
The
onEvent callback receives a typed discriminated union. In addition to the bridge step types, bridgeAndExecute emits execute_approval and execute_transaction progress steps. See the Bridge Events page for the full event shapes.Example
import type {
BridgeAndExecuteParams,
BridgeAndExecuteResult,
} from '@avail-project/nexus-core';
// Bridge and execute
const bridgeAndExecuteResult: BridgeAndExecuteResult = await client.bridgeAndExecute(
{
toTokenSymbol: 'USDC',
toAmountRaw: 100_000_000n, // 100 USDC (6 decimals)
toChainId: 1,
sources: [8453],
execute: {
to: '0x...',
data: '0x...',
tokenApproval: {
toTokenSymbol: 'USDC',
amount: 100_000_000n, // 100 USDC (6 decimals)
spender: '0x...',
},
},
},
{
onIntent: (data) => data.allow(),
onEvent: (event) => {
if (event.type === 'plan_preview') console.log('Bridge+Execute steps:', event.plan.steps);
if (event.type === 'plan_progress') console.log('Step progress:', event.stepType, event.state);
},
},
);
console.log('Bridge and execute result:', bridgeAndExecuteResult);
const bridgeAndExecuteSimulation = await client.simulateBridgeAndExecute({
toTokenSymbol: 'USDC',
toAmountRaw: 100_000_000n, // 100 USDC (6 decimals)
toChainId: 1,
sources: [8453],
execute: {
to: '0x...',
data: '0x...',
// tokenApproval optional for simulation
},
});
console.log('Bridge and execute simulation:', bridgeAndExecuteSimulation);Warning
bridgeAndExecute() throws typed NexusError subclasses on failure. Branch on error.category / error.code.Return Value
BridgeAndExecuteResult object — a discriminated union on bridgeSkipped. When the destination already holds enough funds, the bridge is skipped and bridgeResult is absent.
export type TxResult = {
txHash: Hex;
txExplorerUrl: string;
receipt?: TransactionReceipt;
};
export type BridgeAndExecuteResult = {
approval?: TxResult; // present when an ERC-20 approval was needed for execute
execute: TxResult;
} & (
| { bridgeSkipped: false; bridgeResult: BridgeResult }
| { bridgeSkipped: true; bridgeResult?: undefined }
);
export type BridgeAndExecuteSimulationResult = {
bridgeSimulation: BridgeSimulationResult | null; // null if bridging is skipped
executeSimulation: ExecuteSimulation;
};
export type ExecuteFeeParams =
| { type: 'eip1559'; maxFeePerGas: bigint; maxPriorityFeePerGas: bigint }
| { type: 'legacy'; gasPrice: bigint };
export type ExecuteSimulation = {
feeParams: ExecuteFeeParams;
estimatedGasUnits: bigint; // combined across approval (if any) and execute
estimatedTotalCost: bigint; // combined estimated cost
};Note
Detect a skipped bridge via
result.bridgeSkipped (there is no *_SKIPPED event). See the full type definitions on GitHub.How is this guide?