跳转到主要内容
本快速入门将带您完成一个同链 Composer 交易:将 USDC 存入 Base 上的 Morpho 金库。完成后,您将了解完整的 Composer 流程:报价、授权、执行、跟踪。

先决条件

  • 一个在 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'
关键参数:
参数描述
fromChain8453Base 链 ID
toChain8453Base (同链存款)
fromToken0x8335...2913Base 上的 USDC
toToken0x7BfA...34AMorpho 金库代币地址
fromAmount10000001 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

执行交易

使用报价响应中的 transactionRequest 对象发送交易。
const tx = await signer.sendTransaction(quote.transactionRequest);
console.log('交易已发送:', tx.hash);

const receipt = await tx.wait();
console.log('交易已确认:', receipt.transactionHash);
就这样。Composer 在单笔原子交易中处理兑换和存款。
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:
  1. 识别最优路径 — LI.FI 的路由引擎确定了将 USDC 转换为 Morpho 金库代币的最佳方式
  2. 编译 eDSL 指令 — Composer 编译器为链上 VM 生成了字节码
  3. 模拟执行 — 完整路径在返回报价之前被模拟,确保它会成功
  4. 原子执行 — 您的单笔交易在一笔原子操作中兑换了 USDC 并存入了 Morpho

下一步