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

# 执行路由/报价

> 我们允许您执行任何链上或跨链交换和桥接转账，以及两者的组合。

LI.FI SDK 提供了执行路由和报价的功能。在本指南中，您将学习如何利用 SDK 的功能来处理复杂的跨链转账、管理执行设置以及控制交易流程。

## 执行路由

假设您已经获得了路由。有关更多详细信息，请参阅 [请求路由/报价](/sdk/request-routes)。

请确保您已使用 EVM/Solana 提供者配置了 SDK。有关更多详细信息，请参阅 [配置 SDK 提供者](/sdk/configure-sdk-providers)。

现在，要执行路由，我们可以使用 `executeRoute` 函数。以下是如何使用它的简化示例：

```typescript theme={"system"}
import { createClient } from '@lifi/sdk';
import { executeRoute, getRoutes } from '@lifi/sdk';

const client = createClient({
  integrator: 'Your dApp/company name',
});

const result = await getRoutes(client, {
  fromChainId: 42161, // Arbitrum
  toChainId: 10, // Optimism
  fromTokenAddress: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', // USDC on Arbitrum
  toTokenAddress: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', // DAI on Optimism
  fromAmount: '10000000', // 10 USDC
  // The address from which the tokens are being transferred.
  fromAddress: '0x552008c0f6870c2f77e5cC1d2eb9bdff03e30Ea0', 
});

const route = result.routes[0];

const executedRoute = await executeRoute(client, route, {
  // Gets called once the route object gets new updates
  updateRouteHook(route) {
    console.log(route);
  },
});
```

`executeRoute` 函数在内部管理授权额度和余额检查、链切换、交易数据检索、交易提交以及交易状态跟踪。

* **参数：**
  * `client` (`SDKClient`): SDK 客户端实例。
  * `route` (`Route`): 要执行的路由。
  * `executionOptions` (`ExecutionOptions`, 可选): 包含执行设置和回调的对象。
* **返回值：**
  * `Promise<RouteExtended>`: 在执行完成或暂停时解析，在执行失败时拒绝。

### 执行选项

所有执行选项都是可选的，但我们建议查看它们的描述，以确定哪些选项可能对您的用例有益。

某些选项，例如 [acceptExchangeRateUpdateHook](/sdk/execute-routes#acceptexchangerateupdatehook)，对于在过程中汇率发生变化时成功完成转账至关重要。

#### `updateRouteHook`

当路由对象在执行期间发生变化时，会调用该函数。此函数允许您处理路由更新、跟踪执行状态、交易哈希等。有关更多详细信息，请参阅 [监控路由执行](/sdk/execute-routes#monitor-route-execution) 部分。

* **参数**：
  * `updatedRoute` (`RouteExtended`): 更新后的路由对象。

#### `updateTransactionRequestHook`

该函数适用于高级用法，它允许您在发送之前修改交换/桥接交易请求或代币授权请求，例如更新 gas 信息。

* **参数**：
  * `updatedTxRequest` (`TransactionRequestParameters`): 需要更新的交易请求参数。
* **返回值**：`Promise<TransactionParameters>`: 修改后的交易参数。

#### `acceptExchangeRateUpdateHook`

每当在交换或桥接操作期间汇率发生变化时，都会调用此函数。它会向您提供旧的和新的金额值。要继续执行，您应返回 `true`。如果未提供此钩子或您返回 `false`，SDK 将抛出错误。此钩子是提示用户接受新汇率的理想位置。

* **参数**：一个 `ExchangeRateUpdateParams` 对象，具有以下属性：
  * `toToken` (`Token`): 目标代币。
  * `oldToAmount` (`string`): 目标代币的先前金额。
  * `newToAmount` (`string`): 目标代币的新金额。
* **返回值**：`Promise<boolean | undefined>`: 是否接受更新。
* **抛出：** `TransactionError: Exchange rate has changed!`

#### `getContractCalls`

一个用于在执行期间动态提供合约调用的钩子。这主要用于 [Composer](/composer/overview) 集成，其中合约调用数据需要在执行时根据实际桥接金额生成。

* **参数**：一个 `ContractCallParams` 对象，具有以下属性：
  * `fromChainId` (`number`): 源链 ID。
  * `toChainId` (`number`): 目标链 ID。
  * `fromTokenAddress` (`string`): 源代币地址。
  * `toTokenAddress` (`string`): 目标代币地址。
  * `fromAddress` (`string`): 发送方地址。
  * `toAddress` (`string`, 可选): 接收方地址。
  * `fromAmount` (`bigint`): 源金额。
  * `toAmount` (`bigint`): 目标金额。
  * `slippage` (`number`, 可选): 滑点容差。
* **返回值**：`Promise<GetContractCallsResult>`: 一个包含 `contractCalls` 数组和可选 `patcher` 标志的对象。

#### `adjustZeroOutputFromPreviousStep`

一个布尔标志，当设置为 `true` 时，会调整上一步骤的零输出金额。这在多步骤路由中很有用，因为中间步骤可能会报告零输出。

* **类型**：`boolean`
* **默认值**：`undefined`

#### `executeInBackground`

一个布尔标志，指示路由执行是否应在后台继续，而无需用户交互。有关如何利用此选项的详细信息，请参阅 [更新路由执行](/sdk/execute-routes#update-route-execution) 和 [恢复路由执行](/sdk/execute-routes#resume-route-execution) 部分。

* **类型**：`boolean`
* **默认值**：`false`

<Note>
  在以前的 SDK 版本中，`switchChainHook` 和 `disableMessageSigning` 是 `ExecutionOptions` 的一部分。在 v4 中，这些选项已移至 `EthereumProviderOptions`，应在设置 [EVM 提供者](/sdk/configure-sdk-providers#setup-evm-provider) 时进行配置。请注意，`switchChainHook` 在提供者上已重命名为 `switchChain`。
</Note>

<Note>
  EIP-7702 委托智能钱包当前需要源链原生 gas，因为此类钱包不提供无 gas 或中继器路由。请参阅 [EIP-7702 委托钱包故障排除](/faqs/troubleshooting#eip-7702-delegated-smart-wallets)。
</Note>

## 管理路由执行

在开始路由执行后，可能会有一些用例需要您调整执行设置、停止执行并稍后返回，或将执行移至后台。我们提供了多个函数来实现这一点。

### 更新路由执行

`updateRouteExecution` 函数用于更新正在进行的路由执行的设置。

一个常见的用例是将执行推送到后台，例如，当用户离开您 dApp 中的执行页面时。调用此函数时，执行将继续，直到需要用户交互（例如，签署交易或切换链）。此时，执行将暂停，并且 `executeRoute` promise 将被解析。

要将执行移回前台并使其再次处于活动状态，您可以使用相同的路由对象调用 `resumeRoute`。执行随后将从暂停处恢复。

```typescript theme={"system"}
import { updateRouteExecution } from '@lifi/sdk';

updateRouteExecution(route, { executeInBackground: true });
```

* **参数：**
  * `route` (`Route`): 要更新的活动路由。
  * `executionOptions` (`ExecutionOptions`, **必需**): 包含执行设置和回调的对象。

### 恢复路由执行

`resumeRoute` 函数用于从停止处恢复已暂停、已中止或已失败的路由执行。使用从 `executeRoute` 函数返回的最新活动路由对象，或来自 `updateRouteHook` 的更新后路由对象的最新版本来调用 `resumeRoute` 至关重要。

#### 常见用例

* **将执行移至前台**：当用户导航回您 dApp 中的执行页面时，您可以调用此函数将执行移回前台。执行将从暂停处恢复。
* **页面刷新**：如果用户在执行过程中刷新页面，调用此函数将尝试恢复执行。
* **用户交互错误**：如果用户拒绝链切换、拒绝签署交易或遇到任何其他错误，您可以调用此函数尝试恢复执行。

```typescript theme={"system"}
import { resumeRoute } from '@lifi/sdk';

const route = await resumeRoute(client, route, { executeInBackground: false });
```

* **参数：**
  * `client` (`SDKClient`): SDK 客户端实例。
  * `route` (`Route`): 要恢复执行的路由。
  * `executionOptions` (`ExecutionOptions`, 可选): 包含执行设置和回调的对象。
* **返回值：**
  * `Promise<RouteExtended>`: 在执行完成或暂停时解析，在执行失败时拒绝。

### 停止路由执行

`stopRouteExecution` 函数用于停止活动路由正在进行的执行。它会停止正在进行的执行中任何剩余的用户交互，并从执行队列中移除该路由。但是，如果用户已经签署并发送了交易，它将在链上执行。

```typescript theme={"system"}
import { stopRouteExecution } from '@lifi/sdk';

const stoppedRoute = stopRouteExecution(route);
```

* **参数：**
  * `route` (`Route`): 当前正在执行且需要停止的路由。
* **返回值：**
  * `Route`: 已停止的路由对象。

## 监控路由执行

监控路由执行很重要，我们提供了用于跟踪进度、接收数据更新、访问交易哈希和浏览器链接的工具。

### 步骤的简要说明

一个 `route` 对象包含多个 `step` 对象，每个对象代表一组应按指定顺序完成的交易。每个步骤可以包含多个需要签名的交易，例如授权额度交易，然后是主要的交换或桥接交易。

### 理解 `execution` 对象

`route` 中的每个 `step` 都有一个 `execution` 对象。此对象包含跟踪该步骤执行进度所需的所有信息。`execution` 对象有一个 `actions` 数组，其中每个条目代表执行中的一个顺序阶段。最新的 action 条目包含有关执行阶段的最新信息。

### Actions 数组

`execution` 对象中的 `actions` 数组详细说明了每个步骤的进展。每个 `ExecutionAction` 对象都有一个 `type` 和 `status`，并且在用户签署交易后，还可能包含交易哈希和指向区块链浏览器的链接。

可能的 action 类型有：

* `CHECK_ALLOWANCE` - 检查代币授权额度
* `RESET_ALLOWANCE` - 重置代币授权额度（当必须先重置当前授权额度才能设置新的授权额度时）
* `SET_ALLOWANCE` - 设置代币授权额度
* `PERMIT` - ERC-2612 permit 消息签名
* `NATIVE_PERMIT` - 原生 permit 消息签名
* `SWAP` - 交换交易
* `CROSS_CHAIN` - 桥接交易
* `RECEIVING_CHAIN` - 等待目标链确认

您可以使用 `@lifi/sdk` 中的 `getActionMessage()` 和 `getSubstatusMessage()` 来获取每个 action 类型和状态的人类可读消息。

### 跟踪进度

要监控执行进度，您可以利用 `updateRouteHook` 回调并遍历路由步骤，检查它们的 `execution` 对象。查看 `actions` 数组以获取有关执行阶段的最新信息。`actions` 数组中的最新条目将包含最新的交易哈希、状态和其他相关详细信息。

### 访问交易哈希的示例

```typescript theme={"system"}
const getTransactionLinks = (route: RouteExtended) => {
  route.steps.forEach((step, index) => {
    step.execution?.actions.forEach((action) => {
      if (action.txHash) {
        console.log(
          `Transaction Hash for Step ${index + 1}, Action ${action.type}:`,
          action.txHash
        );
      }
    });
  });
};

const executedRoute = await executeRoute(client, route, {
  updateRouteHook(route) {
    getTransactionLinks(route);
  },
});
```

### 获取活动路由

要获取当前正在执行（活动）的路由，您可以使用 `getActiveRoutes` 和 `getActiveRoute` 函数。

```typescript theme={"system"}
import { getActiveRoute, getActiveRoutes, RouteExtended } from '@lifi/sdk';

const activeRoutes: RouteExtended[] = getActiveRoutes();

const routeId = activeRoutes[0].id;

const activeRoute = getActiveRoute(routeId);
```

## 执行报价

要使用 `executeRoute` 执行报价，您需要先将其转换为路由对象。我们提供了 `convertQuoteToRoute` 辅助函数来将报价对象转换为路由对象。这适用于标准报价和合约调用报价。

```typescript theme={"system"}
import { createClient } from '@lifi/sdk';
import { convertQuoteToRoute, executeRoute, getQuote } from '@lifi/sdk';

const client = createClient({
  integrator: 'Your dApp/company name',
});

const quoteRequest = {
  fromChain: 42161, // Arbitrum
  toChain: 10, // Optimism
  fromToken: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', // USDC on Arbitrum
  toToken: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', // DAI on Optimism
  fromAmount: '10000000', // 10 USDC
  // The address from which the tokens are being transferred.
  fromAddress: '0x552008c0f6870c2f77e5cC1d2eb9bdff03e30Ea0', 
};

const quote = await getQuote(client, quoteRequest);

const route = convertQuoteToRoute(quote);

const executedRoute = await executeRoute(client, route, {
  // Gets called once the route object gets new updates
  updateRouteHook(route) {
    console.log(route);
  },
});
```

## 手动路由执行

除了使用 `executeRoute` 函数外，您还可以手动执行路由和报价。此方法要求开发者独立处理获取交易数据、切换链、发送交易和跟踪交易状态的逻辑。

最初，当请求路由对象时，它们不包含交易数据。这是因为提供了多个路由选项，为所有选项生成交易数据会大大延迟响应。每个路由由多个步骤组成，一旦用户选择了路由，就应使用 `getStepTransaction` 函数单独请求每个步骤的交易数据（见下面的示例）。每个步骤应按顺序执行，因为每个步骤都取决于上一个步骤的结果。

另一方面，报价对象在返回时已包含交易数据，因此不需要调用 `getStepTransaction`，可以立即执行它们。

在使用获取的交易数据发送交易后，您可以使用 `getStatus` 函数跟踪交易的状态。此函数可帮助您监控每笔交易的进度和完成情况。阅读更多 [交易状态](/api-reference/check-the-status-of-a-cross-chain-transfer)。

以下是一个简化的示例。为简单起见，此示例省略了余额检查、交易替换、错误处理、链切换等。但是，在实际实现中，您应包含这些额外功能，以拥有一个健壮的解决方案并确保可靠性。

```typescript theme={"system"}
import { createClient } from '@lifi/sdk';
import { getStepTransaction, getStatus } from '@lifi/sdk';

const client = createClient({
  integrator: 'Your dApp/company name',
});

// Simplified example function to execute each step of the route sequentially
async function executeRouteSteps(route) {
  for (const step of route.steps) {
    // Request transaction data for the current step
    const stepWithTransaction = await getStepTransaction(client, step);
    
    // Send the transaction (e.g. using Viem)
    const transactionHash = await sendTransaction(stepWithTransaction.transactionRequest);
    
    // Monitor the status of the transaction
    let status;
    do {
      const result = await getStatus(client, {
        txHash: transactionHash,
        fromChain: step.action.fromChainId,
        toChain: step.action.toChainId,
        bridge: step.tool,
      });
      status = result.status;
      
      console.log(`Transaction status for ${transactionHash}:`, status);
      
      // Wait for a short period before checking the status again
      await new Promise(resolve => setTimeout(resolve, 5000));
      
    } while (status !== 'DONE' && status !== 'FAILED');
    
    if (status === 'FAILED') {
      console.error(`Transaction ${transactionHash} failed`);
      return;
    }
  }
  
  console.log('All steps executed successfully');
}
```

#### `getStepTransaction`

* **参数：**
  * `client` (`SDKClient`): SDK 客户端实例。
  * `step` (`LiFiStep`): 我们需要为其获取交易数据的步骤对象。
  * `options` (`RequestOptions`, 可选): 一个包含请求选项的对象，例如 `AbortSignal`，可用于在必要时取消请求。
* **返回值：**
  * `Promise<LiFiStep>`: 一个解析为包含交易数据的步骤对象的 promise。

#### `getStatus`

* **参数：**
  * `client` (`SDKClient`): SDK 客户端实例。
  * `params` (`GetStatusRequest`): 用于检查状态的参数，包括交易哈希、源链和目标链 ID 以及 DEX 或桥接名称。
  * `options` (`RequestOptions`, 可选): 一个包含请求选项的对象，例如 `AbortSignal`，可用于在必要时取消请求。
* **返回值：**
  * `Promise<StatusResponse>`: 一个解析为状态响应的 promise，其中包含有关转账的所有相关信息。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.