跳转到主要内容
跨链 Composer 让用户将资产存入与他们的资产所在链不同的协议中,全部在单个流程中完成。本指南涵盖跨链 Composer 操作的模式、示例和注意事项。

跨链 Composer 工作原理

fromChaintoChain 不同时,LI.FI 的路由引擎自动组合:
  1. 源链操作 — 如果需要则兑换代币
  2. 跨链桥 — 将资产转移到目标链
  3. 目标链操作 — 兑换到所需代币并通过 Composer 存入目标协议
从开发者的角度来看,API 调用与同链 Composer 完全相同。您只需使用不同的链 ID。LI.FI 处理跨链桥选择、中间兑换和最终的 Composer 存款。
下面的模式说明了可能的执行路径。您不控制路由引擎选择哪种模式。它会自动优化成本、速度和流动性。只有在收到路由响应时您才会知道确切的执行路径。
源链(例如 Ethereum)          目标链(例如 Base)
┌──────────────────────────┐          ┌──────────────────────────┐
│  1. 兑换 ETH → USDC      │          │  4. 接收跨链 USDC  │
│     (如果需要)           │          │  5. 将 USDC 存入     │
│  2. 授权跨链桥        │─── 跨链桥 ──▶│     Morpho 金库       │
│  3. 发送到跨链桥        │          │  6. 返还金库代币   │
└──────────────────────────┘          └──────────────────────────┘

常见跨链模式

这些模式描述路由引擎可能满足跨链 Composer 请求的典型方式。实际路径在报价时根据可用流动性、跨链桥选项和 gas 成本确定。

跨链桥 + 存款

用户在错误的链上有正确的代币。 示例: Arbitrum 上的 USDC → Base 上的 Morpho 金库
curl -X GET 'https://li.quest/v1/quote?\
fromChain=42161&\
toChain=8453&\
fromToken=0xaf88d065e77c8cC2239327C5EDb3A432268e5831&\
toToken=0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A&\
fromAddress=0xYOUR_WALLET_ADDRESS&\
toAddress=0xYOUR_WALLET_ADDRESS&\
fromAmount=10000000'
可能发生的情况:
  1. 将 USDC 从 Arbitrum 跨链到 Base
  2. 将 USDC 存入 Base 上的 Morpho 金库
  3. 用户收到金库代币
确切的步骤取决于 API 返回的路由。如果产生更好的结果,路由引擎可能会选择不同的跨链桥或插入中间兑换。

兑换 + 跨链桥 + 存款

用户在不同链上有不同的代币。 示例: Ethereum 上的 ETH → Optimism 上的 Aave USDC 借贷
curl -X GET 'https://li.quest/v1/quote?\
fromChain=1&\
toChain=10&\
fromToken=0x0000000000000000000000000000000000000000&\
toToken=AAVE_AUSDC_TOKEN_ADDRESS_ON_OPTIMISM&\
fromAddress=0xYOUR_WALLET_ADDRESS&\
toAddress=0xYOUR_WALLET_ADDRESS&\
fromAmount=100000000000000000'
可能发生的情况:
  1. 在 Ethereum 上将 ETH 兑换为 USDC
  2. 将 USDC 从 Ethereum 跨链到 Optimism
  3. 将 USDC 存入 Optimism 上的 Aave
  4. 用户收到 aUSDC 代币

多跳跨链

当没有直接的跨链桥可用时,路由引擎可能使用多跳路径。 示例: Polygon 上的 MATIC → Avalanche 上的 Yield Yak 金库
const quote = await getQuote({
  fromChain: 137,                                                // Polygon
  toChain: 43114,                                               // Avalanche
  fromToken: '0x0000000000000000000000000000000000001010',     // MATIC
  toToken: 'YIELD_YAK_VAULT_ADDRESS_ON_AVALANCHE',             // Avalanche 上的 Yield Yak 金库
  fromAmount: '1000000000000000000',                            // 1 MATIC
  fromAddress: '0xYOUR_WALLET_ADDRESS',
});
可能发生的情况:
  1. 在 Polygon 上将 MATIC 兑换为桥接代币
  2. 跨链到中间链(如 Ethereum)
  3. 从中间链跨链到 Avalanche
  4. 在 Avalanche 上兑换为目标代币
  5. 存入 Yield Yak 金库

执行跨链 Composer

API 集成

import axios from 'axios';

const executeCrossChainComposer = async () => {
  // 1. 获取跨链 Composer 报价
  const quote = await axios.get('https://li.quest/v1/quote', {
    params: {
      fromChain: 1,                                                 // Ethereum
      toChain: 8453,                                                // Base
      fromToken: '0x0000000000000000000000000000000000000000',       // ETH
      toToken: '0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A',       // Morpho 金库
      fromAmount: '100000000000000000',                             // 0.1 ETH
      fromAddress: '0xYOUR_WALLET_ADDRESS',
      toAddress: '0xYOUR_WALLET_ADDRESS',
    },
  });

  const quoteData = quote.data;
  
  // 2. 设置授权(如果需要)
  if (quoteData.estimate.approvalAddress) {
    // 授权逻辑...
  }

  // 3. 执行源链交易
  const tx = await signer.sendTransaction(quoteData.transactionRequest);
  console.log('源链交易:', tx.hash);

  // 4. 跟踪跨链状态
  const trackStatus = async () => {
    const status = await axios.get('https://li.quest/v1/status', {
      params: {
        txHash: tx.hash,
        fromChain: 1,
        toChain: 8453,
      },
    });

    const statusData = status.data;
    console.log('状态:', statusData.status, statusData.substatus);

    if (statusData.status !== 'DONE' && statusData.status !== 'FAILED') {
      setTimeout(trackStatus, 5000); // 5 秒后重试
    } else {
      console.log('跨链 Composer 完成!');
    }
  };

  trackStatus();
};

SDK 集成

import { getQuote, convertQuoteToRoute, executeRoute } from '@lifi/sdk';

const executeCrossChainComposerWithSDK = async () => {
  // 1. 获取跨链报价
  const quote = await getQuote({
    fromChain: 1,                                                 // Ethereum
    toChain: 8453,                                                // Base
    fromToken: '0x0000000000000000000000000000000000000000',       // ETH
    toToken: '0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A',       // Morpho 金库
    fromAmount: '100000000000000000',                             // 0.1 ETH
    fromAddress: '0xYOUR_WALLET_ADDRESS',
  });

  // 2. 转换并执行 - SDK 处理所有复杂性
  const route = convertQuoteToRoute(quote);
  const executedRoute = await executeRoute(route, {
    updateRouteHook(updatedRoute) {
      console.log('路由更新:', updatedRoute);
    },
    onChainSwitch(chainId) {
      console.log('切换到链:', chainId);
    },
  });

  console.log('跨链 Composer 完成:', executedRoute);
};

状态跟踪

跨链 Composer 需要状态跟踪来监控两阶段执行:
阶段状态描述
源链PENDING源链交易进行中
跨链桥PENDING资产正在跨链
目标链PENDINGComposer 执行进行中
完成DONE所有步骤完成
const trackCrossChainStatus = async (txHash: string, fromChain: number, toChain: number) => {
  const status = await getStatus(txHash, fromChain, toChain);
  
  switch (status.status) {
    case 'PENDING':
      if (status.substatus?.includes('bridge')) {
        console.log('跨链进行中...');
      } else if (status.substatus?.includes('composer')) {
        console.log('Composer 执行进行中...');
      } else {
        console.log('源链交易进行中...');
      }
      break;
      
    case 'DONE':
      console.log('跨链 Composer 完成!');
      break;
      
    case 'FAILED':
      console.error('执行失败:', status.substatus);
      break;
      
    default:
      console.log('状态:', status.status);
  }
};

成本和速度考虑

成本因素

  • Gas 费用:两笔交易(源链 + 目标链)
  • 跨链桥费用:跨链桥收取的费用
  • DEX 费用:中间兑换的费用
  • Slippage:跨链和兑换的价格影响

速度因素

  • 跨链桥时间:从几秒(LayerZero)到几分钟(传统跨链桥)
  • 目标链确认:取决于目标链的出块时间
  • 拥堵:网络拥堵可能延迟执行

优化建议

// 在报价请求中包含选项以优化
const quote = await getQuote({
  fromChain: 1,
  toChain: 8453,
  fromToken: '0x0000000000000000000000000000000000000000',
  toToken: '0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A',
  fromAmount: '100000000000000000',
  fromAddress: '0xYOUR_WALLET_ADDRESS',
  options: {
    slippage: 0.005, // 0.5% slippage
    bridges: {
      allow: ['layerzero', 'stargate'], // 偏好快速跨链桥
    },
  },
});

错误处理

常见跨链 Composer 错误:
错误原因解决方案
BRIDGE_NOT_AVAILABLE没有可用的跨链桥尝试不同的源链或代币
INSUFFICIENT_BRIDGE_LIQUIDITY跨链桥流动性不足等待或使用较小的金额
COMPOSER_EXECUTION_FAILED目标链 Composer 失败检查协议状态,重试
TIMEOUT跨链时间过长检查状态,可能已完成
try {
  const executedRoute = await executeRoute(route);
} catch (error) {
  if (error.code === 'BRIDGE_NOT_AVAILABLE') {
    console.error('此路径没有可用的跨链桥');
  } else if (error.code === 'COMPOSER_EXECUTION_FAILED') {
    console.error('目标链执行失败,请检查协议状态');
  }
}

最佳实践

  1. 显示进度:向用户显示两阶段执行进度
  2. 设置合理超时:跨链可能需要几分钟
  3. 处理部分失败:源链成功但目标链失败的情况
  4. 提供反馈:清晰的状态更新和错误消息
  5. 测试跨链桥:在主网之前在测试网上测试
const executeWithProgress = async (route) => {
  try {
    const executedRoute = await executeRoute(route, {
      updateRouteHook(updatedRoute) {
        // 向用户显示进度
        const currentStep = updatedRoute.steps.find(step => 
          step.execution?.status === 'PENDING'
        );
        
        if (currentStep) {
          updateUI(`正在执行:${currentStep.tool} 在链 ${currentStep.action.toChainId}`);
        }
      },
    });
    
    updateUI('跨链 Composer 完成!');
    return executedRoute;
    
  } catch (error) {
    updateUI(`错误:${error.message}`);
    throw error;
  }
};

下一步