Bridge Aggregation with LI.FI
Use LI.FI as a bridge aggregator on the Tenzro Network to find the best route across 30+ bridges and 66+ chains. LI.FI compares Stargate, Across, Hop, Celer, Connext, and many more to find the cheapest or fastest path for your cross-chain transfer. This tutorial covers chain discovery, route comparison, fee optimization, transfer execution, status tracking, and gas price queries.
What You'll Build
- Query 66+ supported chains via LI.FI
- Get a quick quote (single best route) or all available routes
- Compare fees across 30+ bridges for the same transfer
- Execute the optimal bridge transfer
- Track transfer status until completion
- Query gas prices across multiple chains
- Handle multi-hop routes for exotic chain pairs
LI.FI vs Direct Adapters
Tenzro includes direct adapters for LayerZero, Chainlink CCIP, and deBridge. LI.FI adds aggregation on top — it queries 30+ bridges simultaneously and returns the best routes. Use LI.FI when you want automatic bridge selection, and direct adapters when you need fine-grained control over a specific bridge protocol.
Prerequisites
[dependencies]
tenzro-sdk = "0.1"
tokio = { version = "1", features = ["full"] }Step 1: Get Supported Chains
// LI.FI supports 66+ chains including:
// Ethereum, Arbitrum, Optimism, Base, Polygon, BSC, Avalanche,
// Fantom, Gnosis, zkSync, Linea, Scroll, Mantle, Blast,
// Solana, Cosmos chains, and more
// Get all supported chains
let chains = client.bridge().list_supported_chains("lifi").await?;
println!("LI.FI supports {} chains:", chains.len());
for chain in &chains[..10] {
println!(" {} (chain_id: {})", chain.name, chain.chain_id);
}LI.FI supports 66 chains:
Ethereum (chain_id: 1)
Arbitrum (chain_id: 42161)
Optimism (chain_id: 10)
Base (chain_id: 8453)
Polygon (chain_id: 137)
BSC (chain_id: 56)
Avalanche (chain_id: 43114)
zkSync Era (chain_id: 324)
Linea (chain_id: 59144)
Scroll (chain_id: 534352)Step 2: Get a Quick Quote
A quote returns the single best route. Use this when you just want the optimal path without comparing alternatives:
// Get a quick quote (single best route)
let quote = client.bridge().get_quote(
"ethereum", // source chain
"arbitrum", // destination chain
"USDC", // token
"1000000000", // 1000 USDC
&wallet.address, // sender
&wallet.address, // recipient
Some("lifi"), // use LI.FI
).await?;
println!("Best Route (Quote):");
println!(" Bridge: {}", quote.bridge_name);
println!(" Fee: {} USD", quote.fee_usd);
println!(" Output: {} USDC", quote.estimated_output);
println!(" Time: ~{}s", quote.estimated_time_seconds);
println!(" Gas: {} USD", quote.gas_cost_usd);Best Route (Quote):
Bridge: Stargate V2
Fee: 0.38 USD
Output: 999.62 USDC
Time: ~60s
Gas: 0.85 USDStep 3: Compare All Routes
Get all available routes for a detailed comparison. LI.FI queries every supported bridge for the chain pair:
// Get all available routes (for comparison)
let routes = client.bridge().get_all_routes(
"ethereum",
"arbitrum",
"USDC",
"1000000000",
&wallet.address,
&wallet.address,
Some("lifi"),
).await?;
println!("Available Routes ({} found):", routes.len());
for (i, route) in routes.iter().enumerate() {
println!(" Route {}: {} via {}", i + 1, route.bridge_name, route.tool_name);
println!(" Fee: {} USD", route.fee_usd);
println!(" Output: {} USDC", route.estimated_output);
println!(" Time: ~{}s", route.estimated_time_seconds);
println!(" Steps: {}", route.steps.len());
}Available Routes (5 found):
Route 1: Stargate V2 via stargate
Fee: 0.38 USD
Output: 999.62 USDC
Time: ~60s
Steps: 1
Route 2: Across via across
Fee: 0.45 USD
Output: 999.55 USDC
Time: ~120s
Steps: 1
Route 3: Hop via hop
Fee: 0.52 USD
Output: 999.48 USDC
Time: ~300s
Steps: 1
Route 4: Celer cBridge via cbridge
Fee: 0.61 USD
Output: 999.39 USDC
Time: ~180s
Steps: 1
Route 5: Connext via connext
Fee: 0.73 USD
Output: 999.27 USDC
Time: ~240s
Steps: 2Step 4: Compare Fees Across Bridges
// Compare fees across all bridges for the same transfer
let fee_comparison = routes.iter()
.map(|r| (r.bridge_name.clone(), r.fee_usd, r.estimated_time_seconds))
.collect::<Vec<_>>();
// Sort by fee
let mut by_fee = fee_comparison.clone();
by_fee.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
println!("\nBy Fee (cheapest first):");
for (name, fee, _time) in &by_fee {
println!(" {}: {} USD", name, fee);
}
// Sort by time
let mut by_time = fee_comparison.clone();
by_time.sort_by_key(|r| r.2);
println!("\nBy Time (fastest first):");
for (name, _fee, time) in &by_time {
println!(" {}: ~{}s", name, time);
}By Fee (cheapest first):
Stargate V2: 0.38 USD
Across: 0.45 USD
Hop: 0.52 USD
Celer cBridge: 0.61 USD
Connext: 0.73 USD
By Time (fastest first):
Stargate V2: ~60s
Across: ~120s
Celer cBridge: ~180s
Connext: ~240s
Hop: ~300sStep 5: Execute Bridge Transfer
// Execute the bridge transfer using the best route
let result = client.bridge().bridge_tokens(
"ethereum",
"arbitrum",
"USDC",
"1000000000",
&wallet.address,
Some("lifi"), // LI.FI selects the best bridge internally
).await?;
println!("Transfer initiated:");
println!(" Tx Hash: {}", result.transaction_hash);
println!(" Bridge: {}", result.bridge_used);
println!(" Order ID: {}", result.order_id);Transfer initiated:
Tx Hash: 0x3c8f...b2a7
Bridge: stargate (via LI.FI)
Order ID: lifi-3c8f-b2a7Step 6: Track Status
// Track bridge transfer status
loop {
let status = client.bridge().get_status(&result.order_id).await?;
println!("Status: {} (substatus: {})",
status.state, status.substatus.unwrap_or_default());
match status.state.as_str() {
"DONE" | "Completed" | "Fulfilled" => {
println!("Transfer complete!");
println!(" Source tx: {}", status.source_tx.unwrap_or_default());
println!(" Destination tx: {}", status.destination_tx.unwrap_or_default());
println!(" Received: {} USDC", status.received_amount.unwrap_or_default());
break;
}
"FAILED" => {
eprintln!("Transfer failed: {}", status.error.unwrap_or_default());
break;
}
_ => {
// PENDING, NOT_FOUND, INVALID
tokio::time::sleep(std::time::Duration::from_secs(15)).await;
}
}
}Status: PENDING (substatus: BRIDGE_NOT_STARTED)
Status: PENDING (substatus: BRIDGE_STARTED)
Status: DONE (substatus: COMPLETED)
Transfer complete!
Source tx: 0x3c8f...b2a7
Destination tx: 0x9d4e...7f1c
Received: 999.62 USDCStep 7: Gas Price Queries
Query gas prices across multiple chains to factor into bridge cost calculations:
// Query gas prices across chains
let gas_prices = client.bridge().get_gas_prices(
&["ethereum", "arbitrum", "base", "optimism", "polygon"],
Some("lifi"),
).await?;
println!("Gas Prices:");
for gp in &gas_prices {
println!(" {}: {} gwei ({} USD for transfer)",
gp.chain, gp.gas_price_gwei, gp.transfer_cost_usd);
}Gas Prices:
ethereum: 12.5 gwei ($3.42 for transfer)
arbitrum: 0.1 gwei ($0.05 for transfer)
base: 0.012 gwei ($0.003 for transfer)
optimism: 0.004 gwei ($0.001 for transfer)
polygon: 30.0 gwei ($0.02 for transfer)Multi-Hop Routes
When no direct bridge exists between two chains, LI.FI finds multi-step paths automatically:
// Multi-hop route: when no direct bridge exists
// LI.FI automatically finds multi-step paths
let complex_route = client.bridge().get_all_routes(
"polygon", // source
"scroll", // destination (less common)
"USDC",
"500000000",
&wallet.address,
&wallet.address,
Some("lifi"),
).await?;
for route in &complex_route {
println!("Route: {} ({} steps)", route.bridge_name, route.steps.len());
for (i, step) in route.steps.iter().enumerate() {
println!(" Step {}: {} -> {} via {}",
i + 1, step.from_chain, step.to_chain, step.tool);
}
}
// Example output for a 2-step route:
// Route: stargate+scroll-bridge (2 steps)
// Step 1: polygon -> ethereum via stargate
// Step 2: ethereum -> scroll via scroll-bridgeTypeScript Example
import { TenzroClient } from "@tenzro/sdk";
const client = new TenzroClient({ network: "testnet" });
const wallet = await client.wallet.createWallet();
// Get all routes via LI.FI
const routes = await client.bridge.getAllRoutes({
sourceChain: "ethereum",
destinationChain: "base",
token: "USDC",
amount: "500000000",
sender: wallet.address,
recipient: wallet.address,
adapter: "lifi",
});
console.log(`Found ${routes.length} routes:`);
for (const route of routes) {
console.log(` ${route.bridgeName}: ${route.feeUsd} USD, ~${route.estimatedTimeSeconds}s`);
}
// Execute the cheapest route
const result = await client.bridge.bridgeTokens({
sourceChain: "ethereum",
destinationChain: "base",
token: "USDC",
amount: "500000000",
recipient: wallet.address,
adapter: "lifi",
});
console.log(`Transfer: ${result.transactionHash}`);
// Track status
let status;
do {
status = await client.bridge.getStatus(result.orderId);
console.log(`Status: ${status.state}`);
if (status.state !== "DONE" && status.state !== "FAILED") {
await new Promise(r => setTimeout(r, 15000));
}
} while (status.state !== "DONE" && status.state !== "FAILED");What You Learned
- Bridge aggregation — how LI.FI queries 30+ bridges simultaneously
- Quote vs routes — quick single-route quotes vs detailed multi-route comparison
- Fee comparison — sorting routes by cost and time
- Transfer execution — submitting transfers with automatic bridge selection
- Status tracking — polling until completion or failure
- Gas prices — querying gas costs across multiple chains
- Multi-hop paths — automatic route discovery for exotic chain pairs
Next Steps
- See the deBridge Cross-Chain Swap tutorial for intent-based bridging
- See the Cross-Chain DeFi App tutorial for the complete multi-adapter flow
- Read the Custody Application tutorial for multi-chain key management