> ## Documentation Index
> Fetch the complete documentation index at: https://docs.li.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# API 集成

> 通过 REST API 集成 LI.FI Composer 的分步指南。涵盖同链存款、跨链流程、参数和错误处理。

本指南将带您完成通过 LI.FI REST API 直接集成 Composer。这种方法让您完全控制请求/响应流程，非常适合后端服务、自定义前端或任何您想自己管理交易的环境。

<Note>
  **已经在使用 LI.FI SDK 或 Widget？** Composer 自动工作。请参见 [SDK 指南](/composer/guides/sdk-integration) 或 [Widget 指南](/composer/guides/widget-integration)。
</Note>

***

## 概览

集成流程：

1. **请求报价** — `GET /v1/quote` 或 `POST /v1/advanced/routes`
2. **设置代币授权** — 授权 LI.FI 合约使用您的代币
3. **发送交易** — 提交报价响应中的 `transactionRequest`
4. **跟踪状态** — 为跨链转账轮询 `GET /v1/status`

***

## 请求 Composer 报价

### 使用 `GET /quote`（推荐）

获取 Composer 交易的最简单方法。返回包含交易数据的单个最佳路由。

<CodeGroup>
  ```bash curl theme={"system"}
  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'
  ```

  ```ts TypeScript theme={"system"}
  import axios from 'axios';

  const getQuote = async (params: {
    fromChain: number;
    toChain: number;
    fromToken: string;
    toToken: string;
    fromAmount: string;
    fromAddress: string;
  }) => {
    const result = await axios.get('https://li.quest/v1/quote', {
      params: {
        ...params,
        toAddress: params.fromAddress,
      },
    });
    return result.data;
  };

  const quote = await getQuote({
    fromChain: 8453,                                              // Base
    toChain: 8453,                                                // Base (同链)
    fromToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',     // Base 上的 USDC
    toToken: '0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A',       // Morpho 金库代币
    fromAmount: '1000000',                                        // 1 USDC (6 位小数)
    fromAddress: '0xYOUR_WALLET_ADDRESS',
  });
  ```

  ```python Python theme={"system"}
  import requests

  response = requests.get('https://li.quest/v1/quote', params={
      'fromChain': 8453,
      'toChain': 8453,
      'fromToken': '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
      'toToken': '0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A',
      'fromAmount': '1000000',
      'fromAddress': '0xYOUR_WALLET_ADDRESS',
      'toAddress': '0xYOUR_WALLET_ADDRESS',
  })

  quote = response.json()
  ```
</CodeGroup>

### 使用 `POST /advanced/routes`

返回多个路由选项。当您想向用户展示选择或需要更多路由选择控制时很有用。

<CodeGroup>
  ```ts TypeScript theme={"system"}
  const getRoutes = async (params: {
    fromChainId: number;
    toChainId: number;
    fromTokenAddress: string;
    toTokenAddress: string;
    fromAmount: string;
    fromAddress: string;
  }) => {
    const result = await axios.post('https://li.quest/v1/advanced/routes', {
      ...params,
      toAddress: params.fromAddress,
      options: {
        order: 'RECOMMENDED',
      },
    });
    return result.data;
  };

  const routes = await getRoutes({
    fromChainId: 8453,
    toChainId: 8453,
    fromTokenAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
    toTokenAddress: '0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A',
    fromAmount: '1000000',
    fromAddress: '0xYOUR_WALLET_ADDRESS',
  });
  ```
</CodeGroup>

***

## 设置代币授权

在执行交易之前，您需要授权 LI.FI 合约使用您的代币。授权地址在报价响应中提供。

<CodeGroup>
  ```ts TypeScript theme={"system"}
  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
  );
  ```
</CodeGroup>

<Note>
  对于原生代币（如 ETH），跳过此步骤。原生代币不需要授权。
</Note>

***

## 执行交易

使用报价响应中的 `transactionRequest` 对象发送交易。

<CodeGroup>
  ```ts TypeScript theme={"system"}
  // 对于 GET /quote 响应
  const tx = await signer.sendTransaction(quote.transactionRequest);
  console.log('交易已发送：', tx.hash);

  // 对于 POST /advanced/routes 响应，需要先获取交易数据
  const selectedRoute = routes.routes[0]; // 选择最佳路由
  const tx = await signer.sendTransaction(selectedRoute.transactionRequest);
  console.log('交易已发送：', tx.hash);

  const receipt = await tx.wait();
  console.log('交易已确认：', receipt.transactionHash);
  ```
</CodeGroup>

***

## 跟跨链交易状态

对于跨链 Composer 流程，轮询状态端点以跟踪进度。

<CodeGroup>
  ```ts TypeScript theme={"system"}
  const getStatus = async (txHash: string, fromChain: number, toChain: number) => {
    const result = await axios.get('https://li.quest/v1/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);
  }
  ```
</CodeGroup>

| 状态          | 含义         |
| ----------- | ---------- |
| `NOT_FOUND` | 交易不存在或尚未挖矿 |
| `INVALID`   | 哈希与请求的工具无关 |
| `PENDING`   | 交易进行中      |
| `DONE`      | 成功完成       |
| `FAILED`    | 交易失败       |

***

## 错误处理

Composer 使用标准的 LI.FI API 错误格式。常见错误包括：

| 错误                       | 原因     | 解决方案                      |
| ------------------------ | ------ | ------------------------- |
| `NO_POSSIBLE_ROUTE`      | 没有找到路径 | 检查 `toToken` 是否是支持的金库代币地址 |
| `INSUFFICIENT_LIQUIDITY` | 流动性不足  | 尝试较小的金额或稍后重试              |
| `TRANSACTION_FAILED`     | 模拟失败   | 检查协议状态（如金库是否已满）           |

<CodeGroup>
  ```ts TypeScript theme={"system"}
  try {
    const quote = await getQuote(params);
    // ... 处理报价
  } catch (error) {
    if (error.response?.data?.code === 'NO_POSSIBLE_ROUTE') {
      console.error('没有找到路径。请检查 toToken 地址。');
    } else if (error.response?.data?.code === 'INSUFFICIENT_LIQUIDITY') {
      console.error('流动性不足。请尝试较小金额。');
    } else {
      console.error('未知错误：', error.message);
    }
  }
  ```
</CodeGroup>

***

## 完整示例

这是一个完整的同链 Composer 集成示例：

<CodeGroup>
  ```ts TypeScript theme={"system"}
  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 signer = new ethers.Wallet(PRIVATE_KEY, new ethers.JsonRpcProvider(RPC_URL));

  // 获取报价
  async function getComposerQuote(fromAddress: string) {
    const response = await axios.get(`${API_URL}/quote`, {
      params: {
        fromChain: 8453,
        toChain: 8453,
        fromToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
        toToken: '0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A',
        fromAmount: '1000000',
        fromAddress,
        toAddress: fromAddress,
      },
    });
    return response.data;
  }

  // 设置授权
  async function ensureAllowance(tokenAddress: string, approvalAddress: string, amount: string) {
    const ERC20_ABI = ['function approve(address, uint256)', 'function allowance(address, address) view returns (uint256)'];
    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)) {
      const tx = await erc20.approve(approvalAddress, amount);
      await tx.wait();
      console.log('授权已设置');
    }
  }

  // 主函数
  async function main() {
    const address = await signer.getAddress();
    
    try {
      // 1. 获取报价
      const quote = await getComposerQuote(address);
      console.log('收到报价，工具：', quote.tool);
      
      // 2. 设置授权
      await ensureAllowance(
        quote.action.fromToken.address,
        quote.estimate.approvalAddress,
        quote.action.fromAmount
      );
      
      // 3. 执行交易
      const tx = await signer.sendTransaction(quote.transactionRequest);
      console.log('交易已发送：', tx.hash);
      
      const receipt = await tx.wait();
      console.log('交易已确认：', receipt.transactionHash);
      
    } catch (error) {
      console.error('错误：', error.response?.data || error.message);
    }
  }

  main();
  ```
</CodeGroup>

***

## 下一步

<CardGroup cols={2}>
  <Card title="SDK 集成" icon="cube" href="/composer/guides/sdk-integration">
    使用 LI.FI SDK 进行托管执行
  </Card>

  <Card title="跨链模式" icon="bridge" href="/composer/guides/cross-chain-compose">
    了解跨链 Composer 流程
  </Card>

  <Card title="错误处理" icon="triangle-exclamation" href="/composer/reference/error-handling">
    完整错误参考
  </Card>

  <Card title="支持的协议" icon="list" href="/composer/reference/supported-protocols">
    查看所有支持的协议
  </Card>
</CardGroup>
