Documentation Index
Fetch the complete documentation index at: https://docs.enso.build/llms.txt
Use this file to discover all available pages before exploring further.
This workflow demonstrates bridging tokens using Chainlink’s CCIP protocol with automatic post-bridge execution. CCIP supports larger callback payloads (up to 30KB), making it ideal for complex post-bridge operations.
Route Mechanics:
This bundle bridges SolvBTC from BNB Chain to Base using CCIP, then automatically swaps it to native ETH:
- Bridge SolvBTC from BNB Chain to Base using Chainlink CCIP
- Check SolvBTC balance on Base after successful bridge completion
- Swap bridged SolvBTC to native ETH using Enso’s routing
Use the GET /ccip/router API to get the CCIP Router address for the primaryAddress parameter.
ccipBridgeWithCallback.ts
import { EnsoClient } from "@ensofinance/sdk";
import { parseUnits } from "viem";
// Chain IDs
const BNB_CHAIN_ID = 56;
const BASE_CHAIN_ID = 8453;
// Common addresses
const WALLET_ADDRESS = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045";
// Token addresses
const SOLVBTC_BNB = "0x4aae823a6a0b376De6A78e74eCC5b079d38cBCf7";
const SOLVBTC_BASE = "0x3B86Ad95859b6AB773f55f8d94B4b9d443EE931f";
const NATIVE_TOKEN = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
const client = new EnsoClient({
apiKey: process.env.ENSO_API_KEY!,
});
// Get CCIP Router address for BNB Chain
const ccipRouter = await client.getCcipRouter({
chainId: BNB_CHAIN_ID,
});
const bundle = await client.getBundleData(
{
chainId: BNB_CHAIN_ID,
fromAddress: WALLET_ADDRESS,
routingStrategy: "router",
receiver: WALLET_ADDRESS,
},
[
{
protocol: "ccip",
action: "bridge",
args: {
primaryAddress: ccipRouter.router,
destinationChainId: BASE_CHAIN_ID,
tokenIn: SOLVBTC_BNB,
amountIn: "100000000000000", // 0.0001 SolvBTC
receiver: WALLET_ADDRESS,
callback: [
// Step 1: Check SolvBTC balance on Base after bridge
{
protocol: "enso",
action: "balance",
args: {
token: SOLVBTC_BASE,
},
},
// Step 2: Swap SolvBTC to native ETH on Base
{
protocol: "enso",
action: "route",
args: {
slippage: "100", // 1%
tokenIn: SOLVBTC_BASE,
tokenOut: NATIVE_TOKEN,
amountIn: { useOutputOfCallAt: 0 },
},
},
],
},
},
]
);
return bundle;
Important Considerations:
- CCIP only supports ERC20 tokens - native token bridging is not available
- Callback data limit is approximately 30KB, allowing for complex post-bridge operations
- The callback gas limit ranges from 200k (default) to 3M (max)
- CCIP fees are paid in native token (wrapped)
- If callback execution fails, tokens are sent to
refundReceiver (defaults to receiver)
Finalization timing: CCIP waits for source chain finalization before executing callbacks. This ensures transaction irreversibility but timing varies significantly by chain (sub-second to hours).See Chainlink’s Finality By Blockchain for current finalization times per chain.For time-sensitive swaps with tight slippage protection on slower chains, consider using Relay or Stargate instead.
Without Callback (Simple Transfer)
For simple cross-chain transfers without post-bridge execution:
const bundle = await client.getBundleData(
{
chainId: BNB_CHAIN_ID,
fromAddress: WALLET_ADDRESS,
routingStrategy: "router",
receiver: WALLET_ADDRESS,
},
[
{
protocol: "ccip",
action: "bridge",
args: {
primaryAddress: ccipRouter.router,
destinationChainId: BASE_CHAIN_ID,
tokenIn: SOLVBTC_BNB,
amountIn: "100000000000000",
receiver: WALLET_ADDRESS,
// No callback - tokens sent directly to receiver on Base
},
},
]
);
Resources