Skip to content

充值 ​

充值无需调用接口发起:用户向钱包的充值地址转账,平台监听链上交易,达到最终性后自动入账,并通过回调通知你。你方只需要 获取充值地址 和 处理回调。

流程 ​

text
链上转账到充值地址
   │
   ▼
发现交易 ──▶ 交易记录 kind=DEPOSIT, status=CONFIRMING      回调 TRANSACTION_CREATED
   │
   ▼  等待确认 / 最终性(按网络配置)
   │
   ├─ 金额 < 最小充值额 ──────────▶ COMPLETED + subStatus=BELOW_MIN_DEPOSIT   (未入账)
   ├─ 金额 ≤ 充值手续费 ──────────▶ COMPLETED + subStatus=BELOW_MIN_DEPOSIT   (未入账)
   ├─ 资产暂停充值 / 钱包冻结等 ──▶ PENDING_REVIEW(人工处理,未入账)
   ├─ 反洗钱筛查未通过 ──────────▶ PENDING_REVIEW + subStatus=AML(未入账)
   ├─ 交易未进入主链 ────────────▶ FAILED(未入账)
   └─ 正常 ─────────────────────▶ COMPLETED(已入账 netAmountRaw)         回调 TRANSACTION_STATUS_UPDATED
                                       │
                                       ▼ 极少数情况:入账后链重组,原区块被替换
                                    REVERSED + subStatus=REORG(入账被冲正)  回调 DEPOSIT_REVERSED

状态的完整定义见 交易状态。

确认与最终性 ​

若 EVM 充值地址启用了 EIP-7702 长期委托,发送原生币时请通过 eth_estimateGas 估算 Gas,不要固定使用 21,000;委托代码执行需要额外 Gas。链上执行失败不会形成有效充值。此限制不影响普通 ERC-20 转入的 Gas 估算方式。

每个网络有自己的入账条件,可从 GET /v1/wallets/{id}/addresses 的 confirmations 字段读取:

mode含义
confirmations交易所在区块之上有 n 个确认后入账
finalized交易所在区块被链最终确定后入账(如 Solana)
solidified交易所在区块被固化后入账(如 TRON)

等待期间状态一直是 CONFIRMING,平台不推送确认数变化。

充值手续费 ​

充值手续费用于覆盖平台把充值归集到热钱包的链上成本,在入账时从充值金额中扣除:

text
到账金额(amountRaw) = 链上实际转入金额
手续费  (feeRaw)    = 入账时生效的充值手续费
入账金额(netAmountRaw)= amountRaw - feeRaw
  • 手续费在入账那一刻确定(取当时的 depositFeeRaw,见 手续费如何计算),可能与用户转账时看到的值略有差异。
  • 交易对象在入账后才有 feeRaw 和 netAmountRaw;入账前 feeRaw 为 null,且不包含 netAmountRaw 字段。
  • 请按 netAmountRaw 给用户记账,而不是 amountRaw。

不会自动入账的充值 ​

情况状态处理
金额低于资产的最小充值额(minDeposit / minDepositRaw)COMPLETED + subStatus = BELOW_MIN_DEPOSIT不入账、不扣费。请在前端提示最小充值额
金额不高于充值手续费(amountRaw ≤ depositFeeRaw)COMPLETED + subStatus = BELOW_MIN_DEPOSIT(与上一行相同;BELOW_DEPOSIT_FEE 为预留值,当前不会出现)不入账、不扣费
资产暂停充值(DEPOSIT_PAUSED)PENDING_REVIEW + subStatus = ASSET_DEPOSIT_PAUSED平台/租户后台人工处理
钱包已冻结或关闭、网络关闭了自动入账PENDING_REVIEW + subStatus = WALLET_OR_NETWORK_HOLD人工处理
反洗钱(AML)筛查未通过或需复核PENDING_REVIEW + subStatus = AML人工处理
交易失败或未进入主链(被丢弃、2 小时内未确认)FAILED + subStatus = "not on canonical chain"无需处理

注意 COMPLETED 不一定等于已入账

status = COMPLETED 且 subStatus 不为 null(BELOW_MIN_DEPOSIT,以及预留的 BELOW_DEPOSIT_FEE)时,资金没有进入用户余额。判断是否入账请同时检查 subStatus 为 null(或检查存在 netAmountRaw 字段)。

用户冻结(PATCH /v1/users/{customerRefId} 设为 FROZEN)不影响充值入账;只有钱包被冻结时才转人工。

人工补入账 ​

不支持的代币、用户申诉找回等情况由平台人工处理。人工补入账成功后推送 MANUAL_DEPOSIT_CREDITED 回调:

json
{
  "eventId": "0192a4d0-1111-7aaa-8bbb-0c0d0e0f1011",
  "type": "MANUAL_DEPOSIT_CREDITED",
  "tenantId": "0191f0aa-1b2c-7d3e-8f40-5a6b7c8d9e0f",
  "createdAt": "2026-10-03T09:12:00.000000Z",
  "data": {
    "caseId": "0192a4cf-9a00-7b00-8c00-0d0e0f101112",
    "walletId": "0192a4c1-8b10-7e22-b3a1-6f1e2d3c4b5a",
    "assetId": "USDT_ERC20",
    "amountRaw": "50000000"
  }
}

该事件不对应交易记录(GET /v1/transactions 查不到),data 中只有 walletId。请在你方保存 walletId → customerRefId 的映射(deposit_address 响应里同时有这两个字段),以 caseId 为唯一键给用户加 amountRaw。

链重组冲正 ​

入账后若平台证实原区块被替换(链重组),该笔入账会被冲正:交易状态变为 REVERSED、subStatus = REORG,并推送 DEPOSIT_REVERSED 回调:

json
{
  "eventId": "0192a4d2-0000-7000-8000-000000000abc",
  "type": "DEPOSIT_REVERSED",
  "tenantId": "0191f0aa-1b2c-7d3e-8f40-5a6b7c8d9e0f",
  "createdAt": "2026-10-03T09:30:00.000000Z",
  "data": { "depositId": "0192a4c9-2222-7333-8444-555566667777" }
}

depositId 是平台内部充值 ID,不是交易 id。收到该事件时,请用 GET /v1/transactions?kind=DEPOSIT&status=REVERSED&createdFrom=… 找出对应交易,并从用户余额中扣回 netAmountRaw。若用户已把资金转走、余额不足,平台会冻结该钱包并人工处理。

回调示例 ​

1)发现充值(TRANSACTION_CREATED):

json
{
  "eventId": "0192a4c9-3000-7000-8000-000000000001",
  "type": "TRANSACTION_CREATED",
  "tenantId": "0191f0aa-1b2c-7d3e-8f40-5a6b7c8d9e0f",
  "createdAt": "2026-10-03T06:00:01.120000Z",
  "data": {
    "id": "0192a4c9-2f00-7aaa-8bbb-ccccdddd0001",
    "kind": "DEPOSIT",
    "settlement": "ON_CHAIN",
    "status": "CONFIRMING",
    "subStatus": null,
    "assetId": "USDT_ERC20",
    "networkKey": "ethereum",
    "decimals": 6,
    "amountRaw": "77000000",
    "feeRaw": null,
    "networkFeeRaw": null,
    "networkFeeAssetId": "ETH",
    "source": { "walletId": null, "address": "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc", "customerRefId": null, "uid": null },
    "destination": { "walletId": "0192a4c1-8b10-7e22-b3a1-6f1e2d3c4b5a", "address": "0x8ba1f109551bd432803012645ac136ddd64dba72", "customerRefId": "u-10001", "uid": "48213907" },
    "txHash": "0x5f1c2a0e9b7d4c3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8d7c6b5a4f3e2d1c0b9a",
    "externalTxId": null,
    "note": null,
    "createdAt": "2026-10-03T06:00:01.050000Z",
    "updatedAt": "2026-10-03T06:00:01.050000Z"
  }
}

2)入账完成(TRANSACTION_STATUS_UPDATED):

json
{
  "eventId": "0192a4ca-1000-7000-8000-000000000002",
  "type": "TRANSACTION_STATUS_UPDATED",
  "tenantId": "0191f0aa-1b2c-7d3e-8f40-5a6b7c8d9e0f",
  "createdAt": "2026-10-03T06:03:15.400000Z",
  "data": {
    "id": "0192a4c9-2f00-7aaa-8bbb-ccccdddd0001",
    "kind": "DEPOSIT",
    "settlement": "ON_CHAIN",
    "status": "COMPLETED",
    "subStatus": null,
    "assetId": "USDT_ERC20",
    "networkKey": "ethereum",
    "decimals": 6,
    "amountRaw": "77000000",
    "feeRaw": "500000",
    "netAmountRaw": "76500000",
    "networkFeeRaw": null,
    "networkFeeAssetId": "ETH",
    "source": { "walletId": null, "address": "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc", "customerRefId": null, "uid": null },
    "destination": { "walletId": "0192a4c1-8b10-7e22-b3a1-6f1e2d3c4b5a", "address": "0x8ba1f109551bd432803012645ac136ddd64dba72", "customerRefId": "u-10001", "uid": "48213907" },
    "txHash": "0x5f1c2a0e9b7d4c3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8d7c6b5a4f3e2d1c0b9a",
    "externalTxId": null,
    "note": null,
    "createdAt": "2026-10-03T06:00:01.050000Z",
    "updatedAt": "2026-10-03T06:03:15.390000Z"
  }
}

回调中的 data 是“当前快照”

TRANSACTION_* 事件的 data 是投递时刻的交易对象,而不是事件发生时刻的。如果投递发生了延迟或重试,TRANSACTION_CREATED 里看到的可能已经是 COMPLETED。请始终以 data.status 为准做幂等的状态推进,而不要依赖事件类型。

入账处理建议 ​

js
function onTransactionEvent(tx) {
  if (tx.kind !== "DEPOSIT") return;
  if (tx.status === "COMPLETED" && tx.subStatus === null && tx.netAmountRaw !== undefined) {
    // 以 tx.id 为唯一键(数据库唯一约束),仅首次给 tx.destination.customerRefId 增加 tx.netAmountRaw
  } else if (tx.status === "REVERSED") {
    // 若之前已入账,则扣回 netAmountRaw
  } else {
    // CONFIRMING / PENDING_REVIEW / FAILED / COMPLETED+BELOW_*:仅更新展示状态,不加钱
  }
}
  • 唯一键用交易 id,不要用 txHash:一笔链上交易可能包含多笔转入(例如 BTC 的多个输出、同一交易多次代币转账),会生成多条充值记录。
  • 定期用 GET /v1/transactions?kind=DEPOSIT&createdFrom=…&createdTo=… 对账,补齐可能漏处理的回调。