End-to-end recipe: find the best yield vaults for a token using the Earn Data API, then deposit via Composer in a single transaction.
This recipe walks through a complete LI.FI Earn integration: use the Earn Data API to find the highest-yielding vaults for a specific token, display them to a user, and then execute a deposit via Composer.
Two layers, one flow. This recipe uses the Earn Data API for discovery and Composer for execution. The Earn Data API tells you where to deposit. Composer handles how.
Use apy30d alongside apy.total to give users a sense of yield stability. A vault with a high current APY but low 30-day average may be experiencing a temporary spike.
When the user selects a vault, use its contract address as the toToken in a Composer quote request. This is the handoff from Earn to Composer.
# User selected the first vault, deposit 100 USDCcurl -X GET 'https://li.quest/v1/quote?\fromChain=8453&\toChain=8453&\fromToken=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913&\toToken=0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A&\fromAddress=0xYOUR_WALLET_ADDRESS&\toAddress=0xYOUR_WALLET_ADDRESS&\fromAmount=100000000'
The Composer quote endpoint is https://li.quest/v1/quote. This is the Composer layer of LI.FI Earn, not the Earn Data API. See the Composer API Integration Guide for full details on parameters, token approvals, and transaction submission.
Submit the transaction from the quote response. See the Composer API Integration Guide for the full execution flow including token approvals and status tracking.
TypeScript
// Using ethers.js v6import { ethers } from 'ethers';const provider = new ethers.BrowserProvider(window.ethereum);const signer = await provider.getSigner();// Send the transaction from the Composer quoteconst tx = await signer.sendTransaction(quote.transactionRequest);console.log('Transaction sent:', tx.hash);const receipt = await tx.wait();console.log('Confirmed in block:', receipt.blockNumber);
Vaults are chain-specific, but Composer handles cross-chain deposits seamlessly. To deposit from a different chain, change fromChain and fromToken in the quote request:
TypeScript
// Deposit ETH from Ethereum into a USDC vault on Base// Note: fromChain differs from vault's chain. Composer handles the bridge automatically.const params = new URLSearchParams({ fromChain: '1', // Ethereum (where the user's funds are) toChain: '8453', // Base (where the vault lives) fromToken: '0x0000000000000000000000000000000000000000', // ETH (native) toToken: selectedVault.address, // Vault contract address on Base fromAddress: '0xYOUR_WALLET_ADDRESS', toAddress: '0xYOUR_WALLET_ADDRESS', fromAmount: '100000000000000000', // 0.1 ETH});const response = await fetch(`https://li.quest/v1/quote?${params}`);const crossChainQuote = await response.json();// Composer routes: bridge ETH to Base, swap to USDC, deposit into vault, all in one transaction
Composer’s routing engine automatically determines the optimal bridge and swap path. See Cross-Chain Compose for details.