---
name: li-fi-sdk
description: |
TypeScript/JavaScript SDK for cross-chain and same-chain token swaps, bridging, and DeFi operations.
USE THIS SKILL TO:
- Swap tokens between different blockchains (e.g., "swap USDC on Ethereum to ETH on Arbitrum")
- Bridge tokens to another chain (e.g., "transfer my ETH from mainnet to Base")
- Swap tokens on the same chain with best DEX rates (e.g., "swap ETH to DAI on Polygon")
- Get quotes or compare routes for token swaps across any chains
- Execute 1-click DeFi workflows (zap into LP, bridge+swap+deposit, cross-chain yield entry)
- Build a dApp, wallet, or frontend that supports multi-chain token operations
- Create payment flows that accept any token and convert to a specific token
- Build React, Next.js, Vue, or Node.js apps with cross-chain swap functionality
- Handle cross-chain transaction lifecycle (status tracking, retries, refunds)
- Find available bridges, DEXs, chains, or tokens for cross-chain operations
---
# LI.FI SDK Integration
The LI.FI SDK (`@lifi/sdk`) is a TypeScript/JavaScript toolkit for cross-chain and on-chain swaps and bridging. It provides complete functionality from obtaining routes/quotes to executing transactions across 30+ blockchain networks.
## Installation
```bash
# Using yarn
yarn add @lifi/sdk
# Using npm
npm install @lifi/sdk
# Using pnpm
pnpm add @lifi/sdk
# Using bun
bun add @lifi/sdk
```
## Quick Start
### 1. Configure the SDK
```typescript
import { createConfig } from '@lifi/sdk';
createConfig({
integrator: 'YourAppName', // Required: identifies your application
});
```
### 2. Request a Quote
```typescript
import { getQuote } from '@lifi/sdk';
const quote = await getQuote({
fromChain: 42161, // Arbitrum
toChain: 10, // Optimism
fromToken: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', // USDC on Arbitrum
toToken: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', // DAI on Optimism
fromAmount: '10000000', // 10 USDC (6 decimals)
fromAddress: '0xYourWalletAddress',
});
```
### 3. Execute the Transfer
```typescript
import { executeRoute, convertQuoteToRoute } from '@lifi/sdk';
const route = convertQuoteToRoute(quote);
const executedRoute = await executeRoute(route, {
updateRouteHook(updatedRoute) {
console.log('Route updated:', updatedRoute);
},
});
```
## Core Concepts
### Routes vs Quotes
- **`getQuote()`**: Returns single best option with transaction data ready. Use for simple transfers.
- **`getRoutes()`**: Returns multiple options for comparison. Use when presenting choices to users.
See [references/REFERENCE.md](references/REFERENCE.md) for chain IDs, token addresses, and parameter tables.
## SDK Configuration
### Basic Configuration
```typescript
import { createConfig } from '@lifi/sdk';
createConfig({
integrator: 'YourAppName',
apiKey: 'your-api-key', // Optional: for higher rate limits
});
```
### Advanced Configuration
```typescript
import { createConfig, ChainType } from '@lifi/sdk';
createConfig({
integrator: 'YourAppName',
apiKey: 'your-api-key',
rpcUrls: {
1: ['https://your-ethereum-rpc.com'],
137: ['https://your-polygon-rpc.com'],
},
chains: {
allow: [1, 10, 137, 42161], // Only allow specific chains
},
preloadChains: true, // Preload chain data for faster initial requests
});
```
## Requesting Routes and Quotes
### Get Multiple Routes
```typescript
import { getRoutes, RoutesRequest } from '@lifi/sdk';
const routesRequest: RoutesRequest = {
fromChainId: 42161,
toChainId: 10,
fromTokenAddress: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
toTokenAddress: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1',
fromAmount: '10000000',
fromAddress: '0xYourAddress', // Optional for routes
options: {
slippage: 0.005, // 0.5% slippage
order: 'CHEAPEST', // or 'FASTEST'
},
};
const result = await getRoutes(routesRequest);
const routes = result.routes;
```
### Get Single Best Quote
```typescript
import { getQuote, QuoteRequest } from '@lifi/sdk';
const quoteRequest: QuoteRequest = {
fromChain: 42161,
toChain: 10,
fromToken: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
toToken: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1',
fromAmount: '10000000',
fromAddress: '0xYourAddress', // Required for quotes
slippage: 0.005,
};
const quote = await getQuote(quoteRequest);
```
### Route Options
```typescript
const options = {
slippage: 0.005, // 0.5% slippage tolerance
order: 'CHEAPEST', // 'CHEAPEST' or 'FASTEST'
maxPriceImpact: 0.3, // Hide routes with >30% price impact
allowSwitchChain: true, // Allow 2-step routes
integrator: 'YourApp',
fee: 0.03, // 3% integrator fee (requires verification)
// Bridge/exchange preferences
bridges: {
allow: ['stargate', 'hop'], // Only use these bridges
deny: ['multichain'], // Never use these bridges
prefer: ['stargate'], // Prefer if available
},
exchanges: {
allow: ['1inch', 'uniswap'],
deny: ['sushiswap'],
},
};
```
## Executing Transactions
### Basic Execution
```typescript
import { executeRoute } from '@lifi/sdk';
const executedRoute = await executeRoute(route, {
updateRouteHook(updatedRoute) {
// Called on every route state change
console.log('Status:', updatedRoute.steps[0]?.execution?.status);
},
});
```
### Execution with All Hooks
```typescript
import { executeRoute } from '@lifi/sdk';
const executedRoute = await executeRoute(route, {
// Track route updates
updateRouteHook(updatedRoute) {
const step = updatedRoute.steps[0];
const process = step?.execution?.process;
const latestProcess = process?.[process.length - 1];
console.log('Status:', latestProcess?.status);
console.log('TX Hash:', latestProcess?.txHash);
},
// Handle exchange rate changes (important!)
acceptExchangeRateUpdateHook(toToken, oldAmount, newAmount) {
const oldValue = parseFloat(oldAmount);
const newValue = parseFloat(newAmount);
const percentChange = ((newValue - oldValue) / oldValue) * 100;
// Accept if change is less than 2%
if (Math.abs(percentChange) < 2) {
return Promise.resolve(true);
}
// Prompt user for larger changes
return promptUserToAccept(percentChange);
},
// Handle chain switching (for 2-step routes)
async switchChainHook(chainId) {
await walletClient.switchChain({ id: chainId });
return walletClient;
},
// Modify transaction before sending (advanced)
async updateTransactionRequestHook(txRequest) {
return {
...txRequest,
gas: txRequest.gas ? BigInt(txRequest.gas) * 120n / 100n : undefined,
};
},
});
```
### Execute a Quote
```typescript
import { getQuote, convertQuoteToRoute, executeRoute } from '@lifi/sdk';
// Get quote
const quote = await getQuote(quoteRequest);
// Convert to route for execution
const route = convertQuoteToRoute(quote);
// Execute
const result = await executeRoute(route);
```
## Managing Execution Lifecycle
### Resume Interrupted Execution
```typescript
import { resumeRoute } from '@lifi/sdk';
// Resume from the last saved route state
const resumedRoute = await resumeRoute(savedRoute, {
updateRouteHook(route) {
console.log('Resumed execution:', route);
},
});
```
### Background Execution
```typescript
import { executeRoute, updateRouteExecution } from '@lifi/sdk';
// Start execution
const routePromise = executeRoute(route, {
updateRouteHook(route) {
saveRouteState(route); // Persist state
},
});
// Move to background (e.g., user navigates away)
updateRouteExecution(route, { executeInBackground: true });
// Later: resume in foreground
const resumedRoute = await resumeRoute(savedRoute, {
executeInBackground: false,
});
```
### Stop Execution
```typescript
import { stopRouteExecution } from '@lifi/sdk';
// Stop execution (already-sent transactions will complete on-chain)
const stoppedRoute = stopRouteExecution(route);
```
### Get Active Routes
```typescript
import { getActiveRoutes, getActiveRoute } from '@lifi/sdk';
// Get all active routes
const activeRoutes = getActiveRoutes();
// Get specific active route
const activeRoute = getActiveRoute(routeId);
```
## Chain and Token Discovery
### Get Available Chains
```typescript
import { getChains, ChainType } from '@lifi/sdk';
// Get all chains
const allChains = await getChains();
// Get only EVM chains
const evmChains = await getChains({ chainTypes: [ChainType.EVM] });
```
### Get Available Tokens
```typescript
import { getTokens, getToken } from '@lifi/sdk';
// Get all tokens for a chain
const tokens = await getTokens({ chains: [1, 137] });
// Get specific token
const usdc = await getToken(1, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48');
```
### Get Available Tools (Bridges/DEXs)
```typescript
import { getTools } from '@lifi/sdk';
const tools = await getTools();
console.log('Bridges:', tools.bridges);
console.log('Exchanges:', tools.exchanges);
```
### Get Connections
```typescript
import { getConnections } from '@lifi/sdk';
// Find all possible routes from ETH on Ethereum
const connections = await getConnections({
fromChain: 1,
fromToken: '0x0000000000000000000000000000000000000000', // Native ETH
});
```
## Multi-VM Provider Setup
### EVM Provider (Viem)
```typescript
import { createConfig, EVM } from '@lifi/sdk';
import { createWalletClient, http } from 'viem';
import { mainnet } from 'viem/chains';
const walletClient = createWalletClient({
chain: mainnet,
transport: http(),
});
createConfig({
integrator: 'YourApp',
providers: [
EVM({ getWalletClient: () => Promise.resolve(walletClient) }),
],
});
```
### Solana Provider
```typescript
import { createConfig, Solana } from '@lifi/sdk';
createConfig({
integrator: 'YourApp',
providers: [
Solana({ getWalletAdapter: () => Promise.resolve(walletAdapter) }),
],
});
```
## Contract Calls (Composer)
Execute contract calls on the destination chain after bridging:
```typescript
import { getContractCallsQuote } from '@lifi/sdk';
const contractCallQuote = await getContractCallsQuote({
fromAddress: '0xYourAddress',
fromChain: 10, // Optimism
fromToken: '0x0000000000000000000000000000000000000000',
toAmount: '8500000000000',
toChain: 8453, // Base
toToken: '0x0000000000000000000000000000000000000000',
contractCalls: [{
fromAmount: '8500000000000',
fromTokenAddress: '0x0000000000000000000000000000000000000000',
toContractAddress: '0xTargetContract',
toContractCallData: '0x...', // Encoded function call
toContractGasLimit: '210000',
}],
});
```
## Error Handling
```typescript
import { executeRoute } from '@lifi/sdk';
try {
const result = await executeRoute(route, {
acceptExchangeRateUpdateHook: () => Promise.resolve(true),
});
} catch (error) {
if (error.message.includes('Exchange rate has changed')) {
// Handle rate change rejection
} else if (error.message.includes('insufficient funds')) {
// Handle balance issues
} else if (error.message.includes('user rejected')) {
// Handle user cancellation
} else {
// Handle other errors
console.error('Execution failed:', error);
}
}
```
## Best Practices
1. **Always implement `acceptExchangeRateUpdateHook`** - Exchange rates can change during execution. Without this hook, execution fails on rate changes.
2. **Persist route state** - Use `updateRouteHook` to save route state for recovery after page refreshes or app restarts.
3. **Handle chain switching** - For cross-chain routes, implement `switchChainHook` to handle wallet chain switches.
4. **Use appropriate slippage** - Default 0.5% (0.005) works for most cases. Increase for volatile tokens or low-liquidity pairs.
5. **Set integrator name** - Always configure `integrator` for analytics and potential monetization.
6. **Check token allowances** - The SDK handles allowances automatically, but you may want to show approval UI to users.
7. **Monitor gas prices** - Use `updateTransactionRequestHook` to adjust gas if needed.
See [references/REFERENCE.md](references/REFERENCE.md) for detailed parameter tables and TypeScript interfaces.