LI.FI Cross-Chain Aggregator
LI.FI is a cross-chain aggregation protocol that unifies 27+ bridge protocols and 31+ DEX aggregators across 58+ blockchains behind a single API. Tenzro integrates LI.FI as an aggregator layer alongside its direct bridge adapters (LayerZero, Chainlink CCIP, deBridge, Canton), giving users access to the widest possible set of cross-chain routes while preserving the ability to use purpose-built adapters when specific guarantees are required.
Why an Aggregator Layer?
Direct bridge adapters give Tenzro fine-grained control over message signing, fee quoting, and status tracking. However, no single bridge covers every chain pair or token. LI.FI fills the gaps by sourcing routes from dozens of bridges and DEXes simultaneously, selecting the best path by cost, speed, or security, and returning a single executable transaction.
Aggregator vs Direct — The BridgeRouter tries direct adapters first (LayerZero, CCIP, deBridge, Canton) because they offer deeper protocol integration and lower overhead. When no direct adapter supports the requested chain pair or token, the router falls back to LI.FI to find a viable route across its full bridge and DEX catalog.
Architecture
The LI.FI integration sits inside the tenzro-bridge crate as a LiFiAdapter that implements the same BridgeAdapter trait as the direct adapters. The BridgeRouter treats it as a first-class adapter with a dedicated routing strategy.
┌─────────────────────────────────────────────────┐
│ BridgeRouter │
│ Strategy: Cost | Speed | Availability | LiFi │
└───────┬──────┬──────┬──────┬──────┬──────────────┘
│ │ │ │ │
┌────▼──┐ ┌▼────┐ ┌▼────┐ ┌▼───┐ ┌▼──────────┐
│Layer │ │CCIP │ │deBr.│ │Can.│ │LI.FI │
│Zero V2│ │ │ │DLN │ │ │ │Aggregator │
└───────┘ └─────┘ └─────┘ └────┘ └─────┬─────┘
│
┌─────────────▼──────────────┐
│ li.quest REST API v1 │
│ 27+ bridges, 31+ DEXes │
│ 58+ chains │
└────────────────────────────┘API Integration
LI.FI exposes a REST API at https://li.quest/v1. The LiFiAdapter uses three primary endpoints:
| Endpoint | Method | Purpose |
|---|---|---|
/v1/quote | GET | Get the best route for a token transfer with estimated fees and duration |
/v1/routes | POST | Fetch multiple route options ranked by cost, speed, or fewest steps |
/v1/status | GET | Track transfer status by transaction hash |
/v1/chains | GET | List all supported chains with chain IDs and metadata |
/v1/tokens | GET | List supported tokens on a given chain |
/v1/connections | GET | Query available bridge/DEX connections between two chains |
Configuration
use tenzro_bridge::lifi::{LiFiConfig, LiFiAdapter};
// Configure the LI.FI adapter
let config = LiFiConfig::new()
.with_api_url("https://li.quest/v1")
.with_api_key("your-api-key") // Optional — higher rate limits
.with_integrator("tenzro") // Integrator ID for attribution
.with_fee_bps(25) // 0.25% integrator fee
.with_slippage_percent(0.5) // 0.5% max slippage
.with_allowed_bridges(vec![ // Optional: restrict to specific bridges
"stargate", "hop", "across", "cbridge",
])
.with_denied_bridges(vec![ // Optional: exclude specific bridges
"multichain",
])
.with_timeout_secs(30);
// Create the adapter (implements BridgeAdapter trait)
let lifi = LiFiAdapter::new(config)?;
// Use directly or register with the BridgeRouter
let router = BridgeRouter::new()?
.with_adapter("lifi", Box::new(lifi))
.with_strategy(BridgeStrategy::Cost);Fee Model
LI.FI supports an integrator fee model where Tenzro collects a configurable percentage on each transfer. The default is 0.25% (25 basis points), which is added on top of the underlying bridge and DEX fees. The fee is deducted from the input amount before the swap executes.
| Fee Component | Paid To | Typical Range |
|---|---|---|
| Integrator fee | Tenzro treasury | 0.25% (configurable) |
| Bridge protocol fee | Underlying bridge (Stargate, Hop, etc.) | 0.01% - 0.5% |
| DEX swap fee | DEX liquidity providers | 0.01% - 0.3% |
| Gas fees | Source and destination chain validators | Varies by chain |
Routing Strategies
The BridgeRouter supports a dedicated LiFiAggregator routing strategy alongside the standard strategies. When selected, the router queries LI.FI first before falling back to direct adapters.
use tenzro_bridge::{BridgeRouter, BridgeStrategy};
// Standard strategies try direct adapters first, LI.FI as fallback
let router = BridgeRouter::new()?
.with_strategy(BridgeStrategy::Cost); // Cheapest across all adapters
// or BridgeStrategy::Speed // Fastest estimated delivery
// or BridgeStrategy::Availability // Most reliable adapter
// LI.FI-first strategy queries the aggregator before direct adapters
let router = BridgeRouter::new()?
.with_strategy(BridgeStrategy::LiFiAggregator);
// Get a quote (works with any strategy)
let quote = router.quote(
"USDC", // Token symbol
1000.0, // Amount
1, // Source chain ID (Ethereum)
42161, // Destination chain ID (Arbitrum)
"0xfrom...abc", // Sender address
"0xto...def", // Recipient address
).await?;
println!("Estimated output: {} USDC", quote.estimated_output);
println!("Fee: {} USDC", quote.total_fee);
println!("Duration: ~{}s", quote.estimated_duration_secs);
println!("Route: {} steps via {}", quote.steps.len(), quote.bridge_name);MCP Server
LI.FI provides an official MCP server at mcp.li.quest/mcp that exposes cross-chain tools to AI agents. Tenzro registers this as an external tool in the Tools Registry, making it discoverable via the tenzro skill search and tenzro tool search CLI commands.
// MCP client connection to LI.FI
use tenzro_agent::mcp::McpClient;
let client = McpClient::connect("https://mcp.li.quest/mcp").await?;
// List available tools
let tools = client.list_tools().await?;
// Tools include: lifi_get_quote, lifi_get_routes, lifi_get_status,
// lifi_get_chains, lifi_get_tokens, lifi_execute_route
// Execute a cross-chain quote via MCP
let result = client.call_tool("lifi_get_quote", serde_json::json!({
"fromChain": "ETH",
"toChain": "ARB",
"fromToken": "USDC",
"toToken": "USDC",
"fromAmount": "1000000000", // 1000 USDC (6 decimals)
"fromAddress": "0xfrom...abc",
})).await?;CLI Usage
The Tenzro CLI exposes LI.FI routes through the bridge subcommand. When the --via lifi flag is passed, the CLI forces routing through the LI.FI aggregator.
# Get a quote for bridging USDC from Ethereum to Arbitrum
tenzro bridge quote --token USDC --amount 1000 \
--from-chain ethereum --to-chain arbitrum --via lifi
# Execute the transfer
tenzro bridge execute --token USDC --amount 1000 \
--from-chain ethereum --to-chain arbitrum \
--recipient 0xto...def --via lifi
# Check transfer status
tenzro bridge status --tx-hash 0xabc...123
# List supported chains via LI.FI
tenzro bridge chains --via lifi
# List available tokens on a specific chain
tenzro bridge tokens --chain arbitrum --via lifiComparison: LI.FI vs Direct Adapters
| Feature | LI.FI Aggregator | Direct Adapters |
|---|---|---|
| Chain coverage | 58+ EVM and non-EVM chains | Chains supported by each adapter |
| Bridge coverage | 27+ bridges aggregated | 1 bridge per adapter |
| DEX support | 31+ DEX aggregators (swap before/after bridge) | No native DEX integration |
| Fee quoting | Real-time via REST API | On-chain eth_call (LayerZero, CCIP) or API |
| Message signing | Handled by LI.FI contracts | Tenzro Ed25519/Secp256k1 signing |
| Protocol control | Abstracted — LI.FI selects bridge | Full control over adapter behavior |
| Enterprise (Canton) | Not supported | Canton adapter with DAML 3.x |
| Latency | +200-500ms (API call overhead) | Direct on-chain interaction |
Supported Chains
LI.FI supports a wide range of EVM and non-EVM chains. The following is a subset of the most commonly used chains available through the integration:
Error Handling
The LI.FI adapter maps API errors to typed BridgeError variants so the BridgeRouter can handle failures gracefully and fall back to other adapters when appropriate.
// LI.FI-specific error mapping
match lifi.quote(request).await {
Ok(quote) => execute(quote),
Err(BridgeError::NoRouteFound { src, dst, token }) => {
// No viable route — try direct adapters
router.fallback_to_direct(request).await
}
Err(BridgeError::InsufficientLiquidity { available, required }) => {
// Reduce amount or try later
}
Err(BridgeError::SlippageExceeded { max, actual }) => {
// Price moved — requote
}
Err(BridgeError::RateLimited { retry_after_secs }) => {
// Back off and retry
}
Err(e) => Err(e),
}