## 资金 API 文档

资金接口用于从组织账户提现、查询提现状态与手续费，以及查询 USDT 和 USDC 可用余额。

所有资金接口前缀：

`/v2/funds`

### 认证与权限

所有接口使用 **HMAC-SHA256** 认证：携带 **`Date`**、有请求体时携带 **`Digest`**，以及带 **`keyId`** 的 **`Authorization`** 请求头。GET 请求带查询参数时，签名路径必须包含完整 query string。计算方式见 [章节 4：授权与安全机制](/zh/docs/en/4-authorization)。

| 权限 | 适用接口 |
|  --- | --- |
| `fund.withdraw` | `POST /v2/funds/withdraw`、`GET /v2/funds/withdraw/status`、`GET /v2/funds/withdraw/fees`、`GET /v2/funds/balances` |


> **IP 白名单：** 包含 `fund.withdraw` 权限的 API Key，必须在商户后台创建或更新时配置非空的 IP 白名单。


### 提现幂等

创建提现时，`request_id` 为可选字段：

- 不传时，由 Infini 生成提现请求 ID，并保持原有提现逻辑。调用方重试时如果没有复用同一个 ID，则不具备幂等保障。
- 传入时必须为 UUID，并作为本次提现的幂等键。
- 同一商户使用相同 `request_id` 重试时，接口会返回之前创建的提现订单信息，并设置 `is_duplicate: true`。
- 一个 `request_id` 只能用于一笔逻辑提现。请勿将其复用于不同金额、链、代币或目标地址。


### 响应信封

通过网关鉴权后，应用层响应统一使用 `code` / `message` / `data` 信封。`code === 0` 表示业务成功，非零 `code` 表示错误，详情见 `message`。部分下游业务错误可能以 HTTP 200 返回，此时 `code` 非零且 `data` 为 `null`。

HMAC 或网关校验失败时，请求可能在到达应用前被拒绝，并返回类似 `{"message":"client request can't be validated"}` 的网关响应，而不是应用层信封。客户端应先检查 HTTP 状态，再在存在信封时检查 `code`。

### 提取组织资金

**POST** /v2/funds/withdraw

从当前认证组织账户向外部钱包发起提现。

- **所需权限：** `fund.withdraw`


#### Request Body

| 字段 | 类型 | 必填 | 说明 |
|  --- | --- | --- | --- |
| request_id | string (UUID) | 否 | 幂等键。不传时由 Infini 生成 |
| chain | string | 是 | 公网链名称，例如 `ETHEREUM` 或 `ARBITRUM` |
| token_type | string | 是 | 代币类型，例如 `USDT` 或 `USDC` |
| amount | string | 是 | 正数金额；第六位小数后的数字会直接截断而非四舍五入，截断后金额必须至少为 `1` 且大于提现手续费 |
| wallet_address | string | 是 | 与所选链匹配的目标钱包地址 |
| note | string | 否 | 可选的提现备注 |


请以 **`GET /v2/funds/withdraw/fees`** 返回的当前可用链/代币组合和手续费为准。示例中的链和代币名称均使用大写。

#### 请求示例

```json
{
  "request_id": "e94b4e88-36c2-4550-907e-839742cf5fae",
  "chain": "ETHEREUM",
  "token_type": "USDT",
  "amount": "10.00",
  "wallet_address": "0x5f716e5775b18409917e2a2f0762d29d6c385cb0",
  "note": "Treasury withdrawal"
}
```

#### 响应示例

```json
{
  "code": 0,
  "message": "",
  "data": {
    "request_id": "e94b4e88-36c2-4550-907e-839742cf5fae",
    "status": "pending",
    "is_duplicate": false
  }
}
```

幂等重试时，`data.is_duplicate` 为 `true`，`data.status` 为已有提现单的当前状态。

### 查询提现状态

**GET** /v2/funds/withdraw/status?request_id={request_id}

查询当前认证组织名下提现单的状态和金额信息。

- **所需权限：** `fund.withdraw`
- HMAC 签名路径必须包含 `?request_id={request_id}`。


#### 请求参数

| 字段 | 类型 | 必填 | 说明 |
|  --- | --- | --- | --- |
| request_id | string (UUID) | 是 | 提现请求 ID |


#### 响应示例

```json
{
  "code": 0,
  "message": "",
  "data": {
    "request_id": "e94b4e88-36c2-4550-907e-839742cf5fae",
    "status": "completed",
    "amount": "11",
    "fee": "0.1",
    "actual_amount": "10.9",
    "transaction_hash": "0xabc123",
    "chain": "ETHEREUM",
    "token_type": "USDT"
  }
}
```

#### 响应字段

| 字段 | 类型 | 说明 |
|  --- | --- | --- |
| request_id | string | 提现请求 ID |
| status | string | 当前提现状态 |
| amount | string | 原始提现金额 |
| fee | string | 以 `token_type` 计价的提现手续费 |
| actual_amount | string | 扣除手续费后的链上到账金额 |
| transaction_hash | string | 链上交易哈希；尚未提交时为空字符串 |
| chain | string | 公网链名称 |
| token_type | string | 代币类型 |


#### 状态说明

| 状态 | 说明 |
|  --- | --- |
| `pending` | 提现已创建，等待提交或审核 |
| `processing` | 交易已提交，等待确认 |
| `completed` | 提现已完成 |
| `failed` | 提现失败 |


### 查询提现手续费

**GET** /v2/funds/withdraw/fees

返回当前已启用的公网链/代币组合及其手续费。手续费是动态配置，客户端应调用本接口，不要硬编码手续费表。

- **所需权限：** `fund.withdraw`


#### 响应示例

```json
{
  "code": 0,
  "message": "",
  "data": {
    "fees": [
      {
        "chain": "ARBITRUM",
        "token_type": "USDC",
        "withdraw_fee": "0.5"
      },
      {
        "chain": "ETHEREUM",
        "token_type": "USDT",
        "withdraw_fee": "2"
      }
    ]
  }
}
```

每个 `withdraw_fee` 都使用对应的 `token_type` 计价。

### 查询可用余额

**GET** /v2/funds/balances

仅返回当前认证组织的 USDT 和 USDC `AVAILABLE_BALANCE`。

- **所需权限：** `fund.withdraw`


#### 响应示例

```json
{
  "code": 0,
  "message": "",
  "data": {
    "available_balance_usdt": "120.50",
    "available_balance_usdc": "75.25"
  }
}
```

如果组织没有某个代币的余额记录，对应值返回 `"0"`。