跳到主要内容

充值流程

概述

DF 充值由后端监听器追踪 BSC 金库合约(ZtdxSpotVault)的 SpotDeposit 事件,并将余额记入现货钱包。无充值发起 API — 用户直接在链上与金库合约交互,后端异步完成对账。

当监听器确认 SPOT_BSC_CONFIRMATION_DEPTH 个区块(当前为 20)后,即认为充值最终完成,随即为用户增加 spot_balances.available,并向 spot_deposits 插入一条记录。幂等性由 (chain_id, tx_hash, log_index) 唯一键保证——重放同一事件为无操作。

生命周期

用户钱包

│ 1. DF.approve(vault, amount)

DF ERC-20 合约 ─────────────────────────────────────────────▶

│ 2. ZtdxSpotVault.deposit(token, amount) │
▼ │
ZtdxSpotVault (0x4Fe0b354c5865ee9deb979a99030d757ae47664a) │
│ │
│ 触发 SpotDeposit(account, token, amount) │
▼ │
BSC 区块 N │
│ │
│ ≥ 20 个确认(约 40 秒) │
▼ │
后端监听器(每 2 秒轮询一次) │
│ │
├─ INSERT spot_deposits (status = "confirmed") │
└─ spot_balances.available += amount ◀────────────────────

第一步 — 授权

用户授权金库合约从其钱包中提取 amount 数量的 DF:

DF.approve(vaultAddress, amount);
// vaultAddress = 0x4Fe0b354c5865ee9deb979a99030d757ae47664a
// amount = wei(DF 有 18 位小数,1 DF = 10**18 wei)

第二步 — 充值

用户调用金库的 deposit 函数:

ZtdxSpotVault.deposit(address token, uint256 amount);
// token = 0x8063a43ed88397c1B10DA23dcC60ba1E7A0Bf555(BSC 测试网上的 DF)
// amount = wei

金库接受转账并触发事件:

event SpotDeposit(address indexed account, address indexed token, uint256 amount);

第三步 — 后端入账

监听器每隔 SPOT_BSC_POLL_INTERVAL_MS(2 000 毫秒)轮询一次 BSC。当某个 SpotDeposit 事件累积 SPOT_BSC_CONFIRMATION_DEPTH(20)个区块确认后:

  • spot_deposits 插入一条 status = "confirmed" 的记录。
  • 将充值用户的 spot_balances.available 增加对应的入账金额。

链上组件

项目网络
BSC 链 idBSC 测试网97
金库合约(ZtdxSpotVaultBSC 测试网0x4Fe0b354c5865ee9deb979a99030d757ae47664a
DF 代币(ERC-20)BSC 测试网0x8063a43ed88397c1B10DA23dcC60ba1E7A0Bf555
DF 精度18

确认深度与延迟

参数
SPOT_BSC_CONFIRMATION_DEPTH20 个区块
BSC 测试网出块时间约 2 秒
稳态入账延迟充值交易上链后约 40 秒
冷启动追块速率约 30 个区块/秒

在冷启动阶段(例如服务重启后),监听器以约 30 个区块/秒的速率回放历史区块,直至追上链上最新高度。监听器离线期间发生的充值均会在追块过程中完成入账。

代码示例:监控充值状态

轮询 GET /spot/deposits,直到已知 tx_hash 的充值记录出现且 status = "confirmed"

import time
import requests

BASE_URL = "https://api-sepolia.p99.world/api/v1"
JWT = "your_jwt_token"

# 链上充值交易的 tx_hash。
EXPECTED_TX = "0xabc123..."

def get_deposits(limit: int = 50) -> list:
r = requests.get(
f"{BASE_URL}/spot/deposits",
headers={"Authorization": f"Bearer {JWT}"},
params={"limit": limit},
timeout=5,
)
r.raise_for_status()
return r.json()

print(f"等待充值 {EXPECTED_TX[:12]}... 确认中...")

for attempt in range(60): # 最多轮询 5 分钟
deposits = get_deposits()
match = next((d for d in deposits if d["tx_hash"] == EXPECTED_TX), None)
if match:
print(
f"充值已确认!amount={match['amount']} {match['token']} "
f"block={match['block_number']} confirmed_at={match['confirmed_at']}"
)
break
print(f" 第 {attempt + 1}/60 次尝试 — 暂未可见,5 秒后重试...")
time.sleep(5)
else:
print("等待充值确认超时。")

响应中的 confirmed_at 时间戳表示后端完成余额入账的时间;block_number 表示包含 SpotDeposit 事件的 BSC 区块号。

另见:GET /spot/deposits 参考文档通用信息