先决条件
- 一个在 Base 上有 USDC 的钱包地址(即使是像 1 USDC 这样的少量金额也可以)
- Node.js 18+(用于 TypeScript 示例)或
curl
1
获取 Composer 报价
请求报价,将 关键参数:
响应包括
toToken 设置为金库代币地址: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=1000000'
import axios from 'axios';
const API_URL = 'https://li.quest/v1';
const getQuote = async (
fromChain: number,
toChain: number,
fromToken: string,
toToken: string,
fromAmount: string,
fromAddress: string
) => {
const result = await axios.get(`${API_URL}/quote`, {
params: {
fromChain,
toChain,
fromToken,
toToken,
fromAmount,
fromAddress,
toAddress: fromAddress,
},
});
return result.data;
};
const quote = await getQuote(
8453, // Base
8453, // Base (同链)
'0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // Base 上的 USDC
'0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A', // Morpho 金库代币
'1000000', // 1 USDC (6 位小数)
'0xYOUR_WALLET_ADDRESS'
);
console.log(quote);
| 参数 | 值 | 描述 |
|---|---|---|
fromChain | 8453 | Base 链 ID |
toChain | 8453 | Base (同链存款) |
fromToken | 0x8335...2913 | Base 上的 USDC |
toToken | 0x7BfA...34A | Morpho 金库代币地址 |
fromAmount | 1000000 | 1 USDC (6 位小数) |
toToken 始终是目标协议的金库代币地址。您可以在协议自己的应用或文档中找到金库代币地址。transactionRequest,一个准备签署的 EVM 交易,以及估计的输出金额和使用的工具。2
设置代币授权
在执行之前,确保 LI.FI 合约被授权使用您的代币。授权地址在报价响应的
quote.estimate.approvalAddress 中返回。如果您发送原生代币(例如 ETH),请跳过此步骤。原生代币不需要授权。
import { ethers } from 'ethers';
const ERC20_ABI = [
'function approve(address spender, uint256 amount) returns (bool)',
'function allowance(address owner, address spender) view returns (uint256)',
];
const checkAndSetAllowance = async (
signer: ethers.Signer,
tokenAddress: string,
approvalAddress: string,
amount: string
) => {
const erc20 = new ethers.Contract(tokenAddress, ERC20_ABI, signer);
const signerAddress = await signer.getAddress();
const allowance = await erc20.allowance(signerAddress, approvalAddress);
if (allowance.lt(amount)) {
const tx = await erc20.approve(approvalAddress, amount);
await tx.wait();
console.log('授权已设置。');
} else {
console.log('授权已足够。');
}
};
await checkAndSetAllowance(
signer,
quote.action.fromToken.address,
quote.estimate.approvalAddress,
quote.action.fromAmount
);
3
执行交易
使用报价响应中的 就这样。Composer 在单笔原子交易中处理兑换和存款。
transactionRequest 对象发送交易。const tx = await signer.sendTransaction(quote.transactionRequest);
console.log('交易已发送:', tx.hash);
const receipt = await tx.wait();
console.log('交易已确认:', receipt.transactionHash);
4
跟踪状态
对于同链交易,一旦确认交易就完成了。对于跨链 Composer 流程,轮询
完整状态参考,请参见交易状态跟踪。
/status 端点:const getStatus = async (txHash: string, fromChain: number, toChain: number) => {
const result = await axios.get(`${API_URL}/status`, {
params: { txHash, fromChain, toChain },
});
return result.data;
};
// 对于跨链转账,轮询直到完成
if (quote.action.fromChainId !== quote.action.toChainId) {
let status;
do {
status = await getStatus(tx.hash, quote.action.fromChainId, quote.action.toChainId);
console.log('状态:', status.status, status.substatus);
if (status.status !== 'DONE' && status.status !== 'FAILED') {
await new Promise((resolve) => setTimeout(resolve, 5000)); // 等待 5 秒
}
} while (status.status !== 'DONE' && status.status !== 'FAILED');
console.log('最终状态:', status.status);
}
| 状态 | 含义 |
|---|---|
NOT_FOUND | 交易不存在或尚未挖矿 |
INVALID | 哈希与请求的工具无关 |
PENDING | 交易进行中 |
DONE | 成功完成 |
FAILED | 交易失败 |
完整工作示例
复制粘贴此完整示例来运行您的第一笔 Composer 交易:import { ethers } from 'ethers';
import axios from 'axios';
const API_URL = 'https://li.quest/v1';
// --- 配置 ---
const PRIVATE_KEY = 'YOUR_PRIVATE_KEY';
const RPC_URL = 'https://mainnet.base.org';
const FROM_CHAIN = 8453; // Base
const FROM_TOKEN = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'; // Base 上的 USDC
const TO_TOKEN = '0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A'; // Morpho 金库代币
const FROM_AMOUNT = '1000000'; // 1 USDC
// --- 设置 ---
const provider = new ethers.JsonRpcProvider(RPC_URL);
const signer = new ethers.Wallet(PRIVATE_KEY, provider);
// --- 辅助函数 ---
const getQuote = async (fromAddress: string) => {
const result = await axios.get(`${API_URL}/quote`, {
params: {
fromChain: FROM_CHAIN,
toChain: FROM_CHAIN,
fromToken: FROM_TOKEN,
toToken: TO_TOKEN,
fromAmount: FROM_AMOUNT,
fromAddress,
toAddress: fromAddress,
},
});
return result.data;
};
const ERC20_ABI = [
'function approve(address spender, uint256 amount) returns (bool)',
'function allowance(address owner, address spender) view returns (uint256)',
];
const ensureAllowance = async (
tokenAddress: string,
approvalAddress: string,
amount: string
) => {
const erc20 = new ethers.Contract(tokenAddress, ERC20_ABI, signer);
const address = await signer.getAddress();
const allowance = await erc20.allowance(address, approvalAddress);
if (allowance < BigInt(amount)) {
console.log('设置授权...');
const tx = await erc20.approve(approvalAddress, amount);
await tx.wait();
console.log('授权已设置。');
}
};
// --- 主函数 ---
const run = async () => {
const address = await signer.getAddress();
console.log('钱包:', address);
// 1. 获取报价
console.log('请求 Composer 报价...');
const quote = await getQuote(address);
console.log('收到报价。工具:', quote.tool);
console.log('估计输出:', quote.estimate.toAmount);
// 2. 授权
await ensureAllowance(
quote.action.fromToken.address,
quote.estimate.approvalAddress,
quote.action.fromAmount
);
// 3. 执行
console.log('发送交易...');
const tx = await signer.sendTransaction(quote.transactionRequest);
console.log('交易哈希:', tx.hash);
const receipt = await tx.wait();
console.log('在区块中确认:', receipt.blockNumber);
console.log('完成!USDC 已存入 Morpho 金库。');
};
run().catch(console.error);
刚才发生了什么?
在幕后,Composer:- 识别最优路径 — LI.FI 的路由引擎确定了将 USDC 转换为 Morpho 金库代币的最佳方式
- 编译 eDSL 指令 — Composer 编译器为链上 VM 生成了字节码
- 模拟执行 — 完整路径在返回报价之前被模拟,确保它会成功
- 原子执行 — 您的单笔交易在一笔原子操作中兑换了 USDC 并存入了 Morpho
下一步
跨链 Composer
在单个流程中存入其他链上的协议
SDK 集成
使用 LI.FI SDK 进行托管执行,包含钩子和事件
金库存款配方
Morpho、Aave、Euler 等的复制粘贴配方

