**两个层次,一个流程。**本配方使用 Earn Data API 进行发现,使用 Composer 进行执行。Earn Data API 告诉你_在哪里_存入。Composer 负责_如何_存入。
步骤 1:找到 Base 上最佳的 USDC 金库
向 Earn Data API 查询 Base 上按 APY 排序的 USDC 金库:curl -X GET 'https://earn.li.fi/v1/vaults?chainId=8453&asset=USDC&sortBy=apy&minTvlUsd=100000&limit=5'
const discoverVaults = async (chainId: number, asset: string) => {
const params = new URLSearchParams({
chainId: String(chainId),
asset,
sortBy: 'apy',
minTvlUsd: '100000', // Only vaults with $100k+ TVL
limit: '5',
});
const response = await fetch(`https://earn.li.fi/v1/vaults?${params}`);
const { data } = await response.json();
return data;
};
const vaults = await discoverVaults(8453, 'USDC');
步骤 2:筛选可存入的金库
并非所有金库都支持通过 Composer 存入。使用isTransactional 标志进行筛选:
TypeScript
const depositableVaults = vaults.filter((vault) => vault.isTransactional);
// Display to user
depositableVaults.forEach((vault) => {
console.log(`${vault.name} (${vault.protocol.name})`);
console.log(` APY: ${(vault.analytics.apy.total * 100).toFixed(2)}%`);
console.log(` TVL: $${Number(vault.analytics.tvl.usd).toLocaleString()}`);
console.log(` 30d avg APY: ${(vault.analytics.apy30d * 100).toFixed(2)}%`);
console.log(` Deposit token: ${vault.address}`);
});
将
apy30d 与 apy.total 结合使用,让用户了解收益的稳定性。一个当前 APY 很高但 30 天平均值较低的金库,可能正处于暂时的飙升期。步骤 3:获取 Composer 报价
当用户选定一个金库时,将其合约地址用作 Composer 报价请求中的toToken。这是从 Earn 到 Composer 的交接。
# User selected the first vault, deposit 100 USDC
curl -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'
const depositIntoVault = async (
vault: any,
fromToken: string,
fromAmount: string,
userAddress: string
) => {
const params = new URLSearchParams({
fromChain: String(vault.chainId),
toChain: String(vault.chainId),
fromToken,
toToken: vault.address, // Vault contract address triggers Composer deposit
fromAddress: userAddress,
toAddress: userAddress,
fromAmount,
});
const response = await fetch(`https://li.quest/v1/quote?${params}`);
return response.json();
};
// Deposit 100 USDC into the top vault
const selectedVault = depositableVaults[0];
const quote = await depositIntoVault(
selectedVault,
'0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
'100000000', // 100 USDC (6 decimals)
'0xYOUR_WALLET_ADDRESS'
);
console.log('Estimated output:', quote.estimate);
console.log('Transaction to sign:', quote.transactionRequest);
Composer 报价端点为
https://li.quest/v1/quote。这是 LI.FI Earn 的 Composer 层,而非 Earn Data API。有关参数、代币授权和交易提交的完整详情,请参阅 Composer API 集成指南。步骤 4:执行交易
提交报价响应中的交易。有关包含代币授权和状态追踪在内的完整执行流程,请参阅 Composer API 集成指南。TypeScript
// Using viem
import { createPublicClient, createWalletClient, custom, http } from 'viem';
import type { Address, Hex } from 'viem';
import { base } from 'viem/chains';
const publicClient = createPublicClient({ chain: base, transport: http() });
const walletClient = createWalletClient({ chain: base, transport: custom(window.ethereum) });
const [account] = await walletClient.getAddresses();
// Send the transaction from the Composer quote
const hash = await walletClient.sendTransaction({
account,
to: quote.transactionRequest.to as Address,
data: quote.transactionRequest.data as Hex,
value: BigInt(quote.transactionRequest.value),
gas: BigInt(quote.transactionRequest.gasLimit),
gasPrice: BigInt(quote.transactionRequest.gasPrice),
});
console.log('Transaction sent:', hash);
const receipt = await publicClient.waitForTransactionReceipt({ hash });
console.log('Confirmed in block:', receipt.blockNumber);
步骤 5:验证持仓
存入确认后,使用 Earn 投资组合端点验证用户的新持仓:curl -X GET 'https://earn.li.fi/v1/portfolio/0xYOUR_WALLET_ADDRESS/positions'
const response = await fetch(
`https://earn.li.fi/v1/portfolio/0xYOUR_WALLET_ADDRESS/positions`
);
const { positions } = await response.json();
// Find the position in the vault we just deposited into
const newPosition = positions.find(
(pos) => pos.address?.toLowerCase() === selectedVault.address.toLowerCase()
);
if (newPosition) {
const usd = newPosition.balanceUsd ?? 'N/A';
const protocol = newPosition.protocolName ?? 'unknown';
console.log(`Position: $${usd} in ${protocol}`);
}
跨链存入
金库是特定于链的,但 Composer 可无缝处理跨链存入。要从不同的链存入,请更改报价请求中的fromChain 和 fromToken:
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
完整示例
以下是单个函数中的完整流程:TypeScript
const discoverAndDeposit = async (
chainId: number,
asset: string,
fromToken: string,
fromAmount: string,
userAddress: string
) => {
// 1. Discover vaults
const vaultParams = new URLSearchParams({
chainId: String(chainId),
asset,
sortBy: 'apy',
minTvlUsd: '100000',
limit: '5',
});
const { data: vaults } = await fetch(
`https://earn.li.fi/v1/vaults?${vaultParams}`
).then((r) => r.json());
// 2. Filter for depositable vaults
const depositable = vaults.filter((v) => v.isTransactional);
if (depositable.length === 0) throw new Error('No depositable vaults found');
// 3. Pick the highest-APY vault
const bestVault = depositable[0];
console.log(
`Best vault: ${bestVault.name} at ${(bestVault.analytics.apy.total * 100).toFixed(2)}% APY`
);
// 4. Get Composer quote
const quoteParams = new URLSearchParams({
fromChain: String(chainId),
toChain: String(chainId),
fromToken,
toToken: bestVault.address,
fromAddress: userAddress,
toAddress: userAddress,
fromAmount,
});
const quote = await fetch(
`https://li.quest/v1/quote?${quoteParams}`
).then((r) => r.json());
return { vault: bestVault, quote };
};
// Usage
const { vault, quote } = await discoverAndDeposit(
8453,
'USDC',
'0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
'100000000', // 100 USDC
'0xYOUR_WALLET_ADDRESS'
);
相关内容
Earn API 参考
包含所有参数的完整端点参考
Composer 金库存入
更多包含协议特定示例的金库存入配方
Composer API 指南
完整的 Composer 集成指南,包含授权和状态追踪
跨链 Compose
跨链存入模式和桥接选择

