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

# 资产恢复

> 恢复发送到正确地址但错误区块链上的资产

<Note>
  简而言之<br />
  Yiksi Pay 资产恢复 API 允许您恢复意外发送到正确地址但错误区块链上的资产。它支持所有受支持网络上的原生货币和自定义资产（ERC-20 及兼容标准）。
</Note>

## 什么是资产恢复？

资产恢复使您能够取回发送到正确钱包地址但错误区块链网络上的资金。这通常发生在：

* 用户在以太坊上发送资产，但本意是在 Polygon 上发送
* 资产被发送到 BNB Smart Chain 而非 Arbitrum
* 任何跨链地址混淆，即同一地址存在于多个 EVM 兼容网络上

<Info>
  由于 EVM 兼容的区块链共享相同的地址格式，同一地址可以在多个网络上接收资产。资产恢复允许您以编程方式访问这些资金。
</Info>

## 前提条件

在使用资产恢复 API 之前，请确保您有：

<Steps>
  <Step title="API 密钥">
    从 [Yiksi Pay 控制台](https://dashboard.yiksipay.com) 获取您的 API 密钥。导航到 **设置 → API 密钥** 生成一个。
  </Step>

  <Step title="已创建钱包">
    通过 [创建钱包 API](/zh/api-reference/wallets/create-wallet) 或控制台创建钱包。您需要 `walletId` 来进行恢复操作。
  </Step>

  <Step title="区块链 ID">
    获取资产被困网络的 `blockchainId`。您可以在控制台或通过 [获取区块链 API](/zh/api-reference/miscellaneous/get-blockchains) 找到它。
  </Step>

  <Step title="原生货币余额">
    确保发送方地址在恢复区块链上有足够的原生货币（ETH、BNB、MATIC 等）来支付 gas 费用。
  </Step>
</Steps>

## 工作原理

资产恢复 API 将资产从发送方地址（资产被困的地方）转移到同一区块链上的接收方地址：

<CardGroup cols={2}>
  <Card title="原生货币恢复" icon="coins">
    恢复发送到错误网络的原生货币，如 ETH、BNB、MATIC 或 AVAX。
  </Card>

  <Card title="自定义资产恢复" icon="file-contract">
    通过指定合约地址恢复 ERC-20 及兼容资产。
  </Card>

  <Card title="费用估算" icon="calculator">
    在执行前计算网络费用，确保余额充足。
  </Card>

  <Card title="自定义 RPC 支持" icon="server">
    通过提供您自己的 RPC 端点，在不支持的区块链上恢复资产。
  </Card>
</CardGroup>

## 支持的区块链

资产恢复可在 Yiksi Pay 支持的**所有区块链**上使用，包括 EVM 兼容网络、Tron 和 Solana。查看[集成](/zh/essentials/integrations)获取完整的支持网络列表和水龙头链接。

<Note>
  对于不直接支持的 EVM 网络，您可以提供自定义 RPC URL，并可选择为基于 rollup 的网络启用 Layer 2 模式。
</Note>

<Tip>
  在开发过程中从测试网开始，以避免花费真实资金。
</Tip>

***

## 恢复资产

发起资产恢复操作，将被困资产转移到接收方地址。

### 请求参数

| 参数                 | 类型            | 必需 | 描述                                                                               |
| ------------------ | ------------- | -- | -------------------------------------------------------------------------------- |
| `senderAddress`    | string        | 是  | 资产当前被困的 Yiksi Pay 地址。                                                            |
| `recipientAddress` | string        | 是  | 恢复的资产将发送到的目标地址。                                                                  |
| `amount`           | string        | 是  | 要恢复的金额。使用全部金额或部分金额。                                                              |
| `blockchainId`     | string (UUID) | 是  | 将进行恢复的区块链 UUID。通过[获取区块链 API](/zh/api-reference/miscellaneous/get-blockchains)获取。 |
| `tokenAddress`     | string        | 否  | 自定义资产恢复的合约地址。原生货币则省略。                                                            |
| `rpcUrl`           | string        | 否  | 不支持的区块链的自定义 RPC 端点。                                                              |
| `isL2`             | boolean       | 否  | 如果 RPC URL 指向 Layer 2 网络，设置为 `true`。                                             |

### 原生货币恢复

从错误网络恢复原生货币（ETH、BNB、MATIC 等）：

<CodeGroup>
  ```bash Curl theme={null}
  curl --request POST \
    --url https://api.yiksipay.com/v1/wallets/{walletId}/salvage \
    --header 'Content-Type: application/json' \
    --header 'x-api-key: 您的_API_密钥' \
    --data '{
      "senderAddress": "0x1234567890abcdef1234567890abcdef12345678",
      "recipientAddress": "0xabcdef1234567890abcdef1234567890abcdef12",
      "amount": "0.5",
      "blockchainId": "b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://api.yiksipay.com/v1/wallets/{walletId}/salvage',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': '您的_API_密钥'
      },
      body: JSON.stringify({
        senderAddress: '0x1234567890abcdef1234567890abcdef12345678',
        recipientAddress: '0xabcdef1234567890abcdef1234567890abcdef12',
        amount: '0.5',
        blockchainId: 'b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa'
      })
    }
  );

  const data = await response.json();
  console.log(data);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.yiksipay.com/v1/wallets/{walletId}/salvage',
      headers={
          'Content-Type': 'application/json',
          'x-api-key': '您的_API_密钥'
      },
      json={
          'senderAddress': '0x1234567890abcdef1234567890abcdef12345678',
          'recipientAddress': '0xabcdef1234567890abcdef1234567890abcdef12',
          'amount': '0.5',
          'blockchainId': 'polygon-mainnet'
      }
  )

  print(response.json())
  ```
</CodeGroup>

### 自定义资产恢复

通过指定合约地址恢复 ERC-20 或兼容资产：

<CodeGroup>
  ```bash Curl theme={null}
  curl --request POST \
    --url https://api.yiksipay.com/v1/wallets/{walletId}/salvage \
    --header 'Content-Type: application/json' \
    --header 'x-api-key: 您的_API_密钥' \
    --data '{
      "senderAddress": "0x1234567890abcdef1234567890abcdef12345678",
      "recipientAddress": "0xabcdef1234567890abcdef1234567890abcdef12",
      "amount": "100",
      "blockchainId": "b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa",
      "tokenAddress": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://api.yiksipay.com/v1/wallets/{walletId}/salvage',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': '您的_API_密钥'
      },
      body: JSON.stringify({
        senderAddress: '0x1234567890abcdef1234567890abcdef12345678',
        recipientAddress: '0xabcdef1234567890abcdef1234567890abcdef12',
        amount: '100',
        blockchainId: 'b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa',
        tokenAddress: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359'
      })
    }
  );

  const data = await response.json();
  console.log(data);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.yiksipay.com/v1/wallets/{walletId}/salvage',
      headers={
          'Content-Type': 'application/json',
          'x-api-key': '您的_API_密钥'
      },
      json={
          'senderAddress': '0x1234567890abcdef1234567890abcdef12345678',
          'recipientAddress': '0xabcdef1234567890abcdef1234567890abcdef12',
          'amount': '100',
          'blockchainId': 'polygon-mainnet',
          'tokenAddress': '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359'
      }
  )

  print(response.json())
  ```
</CodeGroup>

### 自定义 RPC 恢复

通过提供您自己的 RPC 端点在不支持的区块链上恢复资产：

<CodeGroup>
  ```bash Curl theme={null}
  curl --request POST \
    --url https://api.yiksipay.com/v1/wallets/{walletId}/salvage \
    --header 'Content-Type: application/json' \
    --header 'x-api-key: 您的_API_密钥' \
    --data '{
      "senderAddress": "0x1234567890abcdef1234567890abcdef12345678",
      "recipientAddress": "0xabcdef1234567890abcdef1234567890abcdef12",
      "amount": "0.5",
      "blockchainId": "b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa",
      "rpcUrl": "https://rpc.custom-network.io",
      "isL2": true
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://api.yiksipay.com/v1/wallets/{walletId}/salvage',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': '您的_API_密钥'
      },
      body: JSON.stringify({
        senderAddress: '0x1234567890abcdef1234567890abcdef12345678',
        recipientAddress: '0xabcdef1234567890abcdef1234567890abcdef12',
        amount: '0.5',
        blockchainId: 'b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa',
        rpcUrl: 'https://rpc.custom-network.io',
        isL2: true
      })
    }
  );

  const data = await response.json();
  console.log(data);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.yiksipay.com/v1/wallets/{walletId}/salvage',
      headers={
          'Content-Type': 'application/json',
          'x-api-key': '您的_API_密钥'
      },
      json={
          'senderAddress': '0x1234567890abcdef1234567890abcdef12345678',
          'recipientAddress': '0xabcdef1234567890abcdef1234567890abcdef12',
          'amount': '0.5',
          'blockchainId': 'custom',
          'rpcUrl': 'https://rpc.custom-network.io',
          'isL2': True
      }
  )

  print(response.json())
  ```
</CodeGroup>

### 成功响应

```json theme={null}
{
  "message": "Salvage asset initiated successfully",
  "statusCode": 200
}
```

***

## 网络费用估算

在执行恢复之前，估算网络费用以确保余额充足。

### 费用估算请求

<CodeGroup>
  ```bash Curl theme={null}
  curl --request POST \
    --url https://api.yiksipay.com/v1/wallets/{walletId}/salvage/network-fee \
    --header 'Content-Type: application/json' \
    --header 'x-api-key: 您的_API_密钥' \
    --data '{
      "senderAddress": "0x1234567890abcdef1234567890abcdef12345678",
      "recipientAddress": "0xabcdef1234567890abcdef1234567890abcdef12",
      "amount": "0.5",
      "blockchainId": "b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://api.yiksipay.com/v1/wallets/{walletId}/salvage/network-fee',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': '您的_API_密钥'
      },
      body: JSON.stringify({
        senderAddress: '0x1234567890abcdef1234567890abcdef12345678',
        recipientAddress: '0xabcdef1234567890abcdef1234567890abcdef12',
        amount: '0.5',
        blockchainId: 'b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa'
      })
    }
  );

  const data = await response.json();
  console.log(data);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.yiksipay.com/v1/wallets/{walletId}/salvage/network-fee',
      headers={
          'Content-Type': 'application/json',
          'x-api-key': '您的_API_密钥'
      },
      json={
          'senderAddress': '0x1234567890abcdef1234567890abcdef12345678',
          'recipientAddress': '0xabcdef1234567890abcdef1234567890abcdef12',
          'amount': '0.5',
          'blockchainId': 'polygon-mainnet'
      }
  )

  print(response.json())
  ```
</CodeGroup>

### 费用响应参数

| 参数                   | 描述                |
| -------------------- | ----------------- |
| `networkFee`         | 以原生货币单位估算的 gas 费用 |
| `networkFeeInUSD`    | 转换为美元的 gas 费用     |
| `nativeBalance`      | 发送方当前的原生货币余额      |
| `nativeBalanceInUSD` | 转换为美元的原生余额        |

<Warning>
  始终在执行恢复操作之前估算费用。发送方地址必须在恢复区块链上有足够的原生货币来支付 gas 费用。
</Warning>

***

## Webhooks

订阅 webhook 事件以接收有关恢复操作的实时通知。

### 恢复事件

| 事件                  | 描述                         |
| ------------------- | -------------------------- |
| `salvage.success`   | 恢复操作成功完成时触发。               |
| `salvage.failed`    | 恢复操作因资金不足、网络问题或其他错误而失败时触发。 |
| `salvage.cancelled` | 恢复操作在完成前被取消时触发。            |

### Webhook 负载

```json theme={null}
{
  "event": "salvage.success",
  "data": {
    "id": "txn_abc123",
    "type": "SALVAGE",
    "status": "SUCCESS",
    "amount": "0.5",
    "senderAddress": "0x1234567890abcdef1234567890abcdef12345678",
    "recipientAddress": "0xabcdef1234567890abcdef1234567890abcdef12",
    "blockchain": "polygon-mainnet",
    "txHash": "0x9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba",
    "networkFee": "0.001",
    "createdAt": "2025-01-12T10:30:00Z"
  }
}
```

<Note>
  在 [Yiksi Pay 控制台](https://dashboard.yiksipay.com/developers) 的 **Developers → Webhooks** 下配置 webhooks。有关设置说明，请参阅 [Webhooks 文档](/zh/essentials/webhooks)。
</Note>

***

## 常见用例

<AccordionGroup>
  <Accordion title="用户在错误网络发送了 USDC">
    用户想在以太坊上发送 USDC，但意外发送到了 Polygon。由于地址相同，资金到达了 Polygon。使用 Polygon 上的 USDC 合约地址进行资产恢复来取回资金。
  </Accordion>

  <Accordion title="ETH 发送到 Arbitrum 而非以太坊">
    用户将 ETH 桥接到 Arbitrum，但发送到了 Yiksi Pay 地址。由于 EVM 兼容性，同一地址存在于 Arbitrum 上。使用原生货币恢复从 Arbitrum 恢复 ETH。
  </Accordion>

  <Accordion title="Layer 2 上的自定义资产">
    用户在 Optimism 等 L2 网络上发送了自定义 ERC-20 资产。提供资产合约地址并使用恢复 API 来恢复它。
  </Accordion>

  <Accordion title="不支持网络上的资产">
    资产被困在 Yiksi Pay 不直接支持的区块链上。提供您自己的 RPC 端点，如果是 rollup 则设置 `isL2: true` 来恢复资金。
  </Accordion>
</AccordionGroup>

***

## 错误处理

<AccordionGroup>
  <Accordion title="原生余额不足">
    ```json theme={null}
    {
      "error": "Insufficient native balance for gas",
      "code": "INSUFFICIENT_GAS",
      "details": {
        "required": "0.01",
        "available": "0.001",
        "currency": "MATIC"
      }
    }
    ```

    **解决方案：** 在重试之前，向发送方地址充值足够的原生货币以支付 gas 费用。
  </Accordion>

  <Accordion title="无效的发送方地址">
    ```json theme={null}
    {
      "error": "Sender address not found in wallet",
      "code": "INVALID_SENDER"
    }
    ```

    **解决方案：** 确保发送方地址属于您的 Yiksi Pay 钱包，并且是有效的子地址。
  </Accordion>

  <Accordion title="未找到资产">
    ```json theme={null}
    {
      "error": "No balance found for specified asset",
      "code": "ASSET_NOT_FOUND",
      "details": {
        "tokenAddress": "0x...",
        "blockchain": "polygon-mainnet"
      }
    }
    ```

    **解决方案：** 验证合约地址和区块链。使用区块浏览器确认资产存在于发送方地址。
  </Accordion>

  <Accordion title="RPC 连接失败">
    ```json theme={null}
    {
      "error": "Failed to connect to custom RPC",
      "code": "RPC_ERROR"
    }
    ```

    **解决方案：** 验证您的 RPC URL 是否正确且可访问。确保它支持所需的 JSON-RPC 方法。
  </Accordion>
</AccordionGroup>

***

## 最佳实践

<CardGroup cols={2}>
  <Card title="始终先估算费用" icon="calculator">
    在恢复之前使用网络费用端点，确保有足够的 gas 余额并显示准确的成本。
  </Card>

  <Card title="验证地址" icon="magnifying-glass">
    在发起恢复之前，使用区块浏览器仔细检查发送方和接收方地址。
  </Card>

  <Card title="使用 Webhooks" icon="bell">
    配置 webhooks 以接收实时状态更新，而不是轮询 API。
  </Card>

  <Card title="在测试网测试" icon="flask">
    在生产环境使用之前，在测试网上测试您的恢复集成。
  </Card>
</CardGroup>

***

## API 参考

| 端点                                                                          | 描述        |
| --------------------------------------------------------------------------- | --------- |
| [Salvage](/zh/api-reference/asset-recovery/salvage)                         | 发起资产恢复操作  |
| [Salvage Network Fee](/zh/api-reference/asset-recovery/salvage-network-fee) | 估算恢复的网络费用 |

<br /> 祝您恢复顺利！
