> ## 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.

# 端到端交易示例

<Info>
  **想要超越交换和桥接吗？** 通过 [Composer](/composer/overview)，您可以一次性存入金库、质押和借贷 —— 所有操作都使用下面展示的相同API模式。参见 [Composer 快速开始](/composer/quickstart)。
</Info>

## 逐步指南

<Steps>
  <Step title="请求报价或路径">
    <CodeGroup>
      ```ts TypeScript theme={"system"}
      const getQuote = async (fromChain, toChain, fromToken, toToken, fromAmount, fromAddress) => {
          const result = await axios.get('https://li.quest/v1/quote', {
              params: {
                  fromChain,
                  toChain,
                  fromToken,
                  toToken,
                  fromAmount,
                  fromAddress,
              }
          });
          return result.data;
      }

      const fromChain = 42161;
      const fromToken = 'USDC';
      const toChain = 100;
      const toToken = 'USDC';
      const fromAmount = '1000000';
      const fromAddress = YOUR_WALLET_ADDRESS;

      const quote = await getQuote(fromChain, toChain, fromToken, toToken, fromAmount, fromAddress);
      ```
    </CodeGroup>
  </Step>

  <Step title="如果使用了 `/advanced/routes`，选择所需路径并从 `/advanced/stepTransaction` 检索交易数据">
    <Note>
      仅当使用了 `/advanced/routes` 端点时才需要此步骤。`/quote` 已在响应中返回交易数据。`/quote` 与 `/advanced/routes` 之间的区别在 [这里](/introduction/user-flows-and-examples/difference-between-quote-and-route) 描述
    </Note>
  </Step>

  <Step title="设置许可">
    在发送任何交易之前，必须确保用户被允许从钱包发送请求的金额。

    <CodeGroup>
      ```ts TypeScript theme={"system"}
      const { Contract } = require('ethers');

      const ERC20_ABI = [
          {
              "name": "approve",
              "inputs": [
                  {
                      "internalType": "address",
                      "name": "spender",
                      "type": "address"
                  },
                  {
                      "internalType": "uint256",
                      "name": "amount",
                      "type": "uint256"
                  }
              ],
              "outputs": [
                  {
                      "internalType": "bool",
                      "name": "",
                      "type": "bool"
                  }
              ],
              "stateMutability": "nonpayable",
              "type": "function"
          },
          {
              "name": "allowance",
              "inputs": [
                  {
                      "internalType": "address",
                      "name": "owner",
                      "type": "address"
                  },
                  {
                      "internalType": "address",
                      "name": "spender",
                      "type": "address"
                  }
              ],
              "outputs": [
                  {
                      "internalType": "uint256",
                      "name": "",
                      "type": "uint256"
                  }
              ],
              "stateMutability": "view",
              "type": "function"
          }
      ];

      // 获取当前许可并在需要时更新
      const checkAndSetAllowance = async (wallet, tokenAddress, approvalAddress, amount) => {
          // 使用原生代币的交易不需要批准
          if (tokenAddress === ethers.constants.AddressZero) {
              return
          }

          const erc20 = new Contract(tokenAddress, ERC20_ABI, wallet);
          const allowance = await erc20.allowance(await wallet.getAddress(), approvalAddress);

          if (allowance.lt(amount)) {
              const approveTx = await erc20.approve(approvalAddress, amount);
              await approveTx.wait();
          }
      }

      await checkAndSetAllowance(wallet, quote.action.fromToken.address, quote.estimate.approvalAddress, fromAmount);
      ```
    </CodeGroup>
  </Step>

  <Step title="发送交易">
    收到报价后，必须发送交易以触发转账。

    首先，必须配置钱包。以下示例将您的钱包连接到 Gnosis Chain。

    <CodeGroup>
      ```ts TypeScript theme={"system"}
      const provider = new ethers.providers.JsonRpcProvider('https://rpc.xdaichain.com/', 100);
      const wallet = ethers.Wallet.fromMnemonic(YOUR_PERSONAL_MNEMONIC).connect(
          provider
      );
      ```
    </CodeGroup>

    然后，可以使用之前检索到的报价中的 `transactionRequest` 发送交易：

    <CodeGroup>
      ```ts TypeScript theme={"system"}
      const tx = await wallet.sendTransaction(quote.transactionRequest);
      await tx.wait();
      ```
    </CodeGroup>
  </Step>

  <Step title="如果适用，执行第二步">
    如果使用了两步路径，第一步完成后必须执行第二步。像下一步中描述的那样获取第一步的状态，然后从 `/advanced/stepTransaction` 端点请求 transactionData。
  </Step>

  <Step title="获取转账状态">
    要检查代币是否已成功发送到接收链，可以调用 /status 端点：

    <CodeGroup>
      ```ts TypeScript theme={"system"}
      const getStatus = async (bridge, fromChain, toChain, txHash) => {
          const result = await axios.get('https://li.quest/v1/status', {
              params: {
                  bridge,
                  fromChain,
                  toChain,
                  txHash,
              }
          });
          return result.data;
      }

      result = await getStatus(quote.tool, fromChain, toChain, tx.hash);
      ```
    </CodeGroup>
  </Step>
</Steps>

## 完整示例

<CodeGroup>
  ```ts TypeScript theme={"system"}
  const ethers = require('ethers');
  const axios = require('axios');

  const API_URL = 'https://li.quest/v1';

  // 获取您所需转账的报价
  const getQuote = async (fromChain, toChain, fromToken, toToken, fromAmount, fromAddress) => {
      const result = await axios.get(`${API_URL}/quote`, {
          params: {
              fromChain,
              toChain,
              fromToken,
              toToken,
              fromAmount,
              fromAddress,
          }
      });
      return result.data;
  }

  // 检查您的转账状态
  const getStatus = async (bridge, fromChain, toChain, txHash) => {
      const result = await axios.get(`${API_URL}/status`, {
          params: {
              bridge,
              fromChain,
              toChain,
              txHash,
          }
      });
      return result.data;
  }

  const fromChain = 42161;
  const fromToken = 'USDC';
  const toChain = 100;
  const toToken = 'USDC';
  const fromAmount = '1000000';
  const fromAddress = YOUR_WALLET_ADDRESS;

  // 设置您的钱包
  const provider = new ethers.providers.JsonRpcProvider('https://rpc.xdaichain.com/', 100);
  const wallet = ethers.Wallet.fromMnemonic(YOUR_PERSONAL_MNEMONIC).connect(
      provider
  );

  const run = async () => {
      const quote = await getQuote(fromChain, toChain, fromToken, toToken, fromAmount, fromAddress);
      const tx = await wallet.sendTransaction(quote.transactionRequest);

      await tx.wait();

      // 仅适用于跨链转账
      if (fromChain !== toChain) {
          let result;
          do {
              result = await getStatus(quote.tool, fromChain, toChain, tx.hash);
          } while (result.status !== 'DONE' && result.status !== 'FAILED')
      }
  }

  run().then(() => {
      console.log('DONE!')
  });
  ```
</CodeGroup>
