核心特点
无需锁单
买方直接转账,无需预操作,没有 DoS 攻击面
买方零 Axon Gas
全程只需 BSC/Arb 上的 BNB/ETH,约 $0.01-0.10
专属付款地址
HD 钱包为每笔订单派生唯一收款地址
全自动成交
Keeper 检测 USDT 到账 → 放 AXON → 转 USDT 给卖方
并发安全
多人同时付款先到先得,后到自动退款
管理员兜底
adminForceCancel 可从任何非终态退币
支持的链与代币
| chain | chain_id | role | tokens |
|---|---|---|---|
| Axon | 8210 | AXON 托管链 | AXON (native, 18 decimals) |
| BSC | 56 | 买方付款链 | USDT (18 dec), USDC (18 dec) |
| Arbitrum | 42161 | 买方付款链 | USDT (6 dec), USDC (6 dec) |
私钥同时控制 Axon / BSC / Arbitrum 上的同一地址。卖方需 AXON + gas;买方只需 USDT/USDC + BNB/ETH gas。
交易流程
seller.create_sell_order() // Axon 链, AXON 存入合约托管
│
▼
order.status == Active
│
├── seller.request_cancel_order() → CancelPending → 15min → finalize → Cancelled
│
└── buyer.buy_full(order_id)
├─ ① get_payment_info() // 获取 HD 专属付款地址
└─ ② send_payment() // 转 USDT 到该地址
│
▼
Keeper 自动检测:
├─ sweep() // USDT → Keeper 主钱包
├─ keeperFulfill() // AXON → 买方
└─ forward() // USDT → 卖方
│
▼
order.status == Completed ✓
// 并发处理:
// 多人同时付款 → 先到先得,后到退款
// 付款时订单已被买走 / 已取消 → 自动退款
订单状态
| status | value | 含义 | 后续操作 |
|---|---|---|---|
| Active | 0 | 卖单挂出,等待买方 | buy_full() / request_cancel_order() |
| Completed | 1 | 交易完成 | AXON → 买方, USDT → 卖方 |
| Cancelled | 2 | 已取消 | AXON 已退回卖方 |
| Disputed | 3 | 争议中 | 等待管理员 resolveDispute() |
| CancelPending | 4 | 取消冷却中 | 15min 后 finalize,买方仍可购买 |
快速开始
1
安装依赖
bashpip install web3 eth-account
2
初始化客户端
pythonimport os from src.otc_client import OTCClient client = OTCClient( private_key=os.environ["AXON_PRIVATE_KEY"], contract_address=os.environ["OTC_CONTRACT_ADDRESS"], )
| param | type | 说明 | default |
|---|---|---|---|
private_key | str | 钱包私钥 | 必填 |
contract_address | str | OTC 合约地址 | 必填 |
axon_rpc | str | Axon RPC 地址 | config.AXON["rpc"] |
keeper_url | str | Keeper API 地址 | https://axonotc.com |
keeper_http_timeout | int | 请求 Keeper 超时(秒) | env KEEPER_HTTP_TIMEOUT or 60 |
Keeper HTTP API
Base URL: https://axonotc.com · 仅 GET · 链上转账需自行完成
| endpoint | description | response |
|---|---|---|
GET /health | 健康检查 | {"status":"ok","version":"v7"} |
GET /orders | 活跃卖单列表 | 每项含 payment_address |
GET /order/{id} | 单笔详情 | payment.{address, amount, token, chain_id} |
GET /order/{id}/buy | 同上(别名) | 响应体一致 |
bash# 健康检查 curl -s "https://axonotc.com/health" # 获取所有活跃卖单 curl -s "https://axonotc.com/orders" # 获取订单 #5 详情(含专属付款地址) curl -s "https://axonotc.com/order/5"
拿到
payment.address 后在订单指定链上转 USDT/USDC。不要向 seller_payment_addr 转账 — 那是卖方收款地址。买方操作
list_active_orders()
pythonorders, total = client.list_active_orders(offset=0, limit=50) for o in orders: print(o) # Order#12 100.0000 AXON @ $0.0200/USDT on BSC total=2.00 USDT [Active]
buy_full()
pythonresult = client.buy_full(order_id=12) print(f"付款地址: {result['payment_address']}") print(f"付款 tx: {result['payment_tx']}") # Keeper 自动: 检测付款 → 放 AXON → 转 USDT
buy_full() 内部调用: ① get_payment_info() 获取专属地址 → ② send_payment() 转 USDT → ③ 返回 {payment_address, payment_tx, order}
确认收到 AXON
pythonimport time time.sleep(30) # 等 Keeper 处理 (通常 30-60s) order = client.get_order(12) print(order.status_label) # "Completed" print(client.axon_balance()) # AXON 余额
FAQ
多人同时购买?
先到先得,后到自动退款 USDT,无资金损失。
付款后多久收到?
通常 30-60s。Keeper 每 10s 扫描 + 链上确认。
转错金额?
少付 >0.5%: Keeper 不处理,联系管理员。多付: 按实际金额处理。建议 buy_full() 自动计算。
必须使用
buy_full() — 自动获取正确地址和金额。禁止向 seller_payment_addr 转账。完整示例
buy_axon.pyfrom src.otc_client import OTCClient import os client = OTCClient( private_key=os.environ["AXON_PRIVATE_KEY"], contract_address=os.environ["OTC_CONTRACT_ADDRESS"], ) orders, _ = client.list_active_orders(limit=50) if not orders: exit("当前没有卖单") best = min(orders, key=lambda o: o.price_usd) print(f"最优: #{best.id} {best.amount_axon} AXON @ ${best.price_usd}") bal = client.stablecoin_balance(best.payment_chain_id, best.payment_token) if bal < best.total_payment: exit(f"余额不足: 需 {best.total_payment:.2f}, 有 {bal:.2f}") result = client.buy_full(best.id) print(f"付款 tx: {result['payment_tx']}") print("Keeper 将自动放 AXON 到你的地址")
卖方操作
create_sell_order()
pythonorder_id, tx = client.create_sell_order( amount_axon=100, # 出售数量 price_usd=0.02, # 单价 $0.02 payment_chain_id=56, # BSC (42161 = Arbitrum) payment_token="USDT", # "USDT" | "USDC" ) print(f"卖单 #{order_id} 已创建, 总价 {100 * 0.02:.2f} USDT")
可选参数 seller_payment_addr: 指定不同的 BSC/Arb 收款地址(默认同 Axon 地址)。
pythonorder_id, tx = client.create_sell_order( amount_axon=100, price_usd=0.02, payment_chain_id=56, payment_token="USDT", seller_payment_addr="0x你的BSC收款地址", )
cancel flow
python# step 1: 请求取消 → CancelPending (15min 冷却) client.request_cancel_order(order_id) # step 2: 冷却结束后执行取消 → AXON 退回 import time time.sleep(900) client.finalize_cancel_order(order_id) # 如果改变主意: client.abort_cancel(order_id) # → 恢复 Active
冷却期: 防止卖方看到买方正在付款时恶意取消。冷却期内买方仍可正常购买。
get_order()
pythonorder = client.get_order(order_id) print(order.status_label) # Active | CancelPending | Completed | Cancelled
完整示例
sell_axon.pyfrom src.otc_client import OTCClient import os client = OTCClient( private_key=os.environ["AXON_PRIVATE_KEY"], contract_address=os.environ["OTC_CONTRACT_ADDRESS"], ) print(f"AXON 余额: {client.axon_balance():.4f}") order_id, _ = client.create_sell_order( amount_axon=50, price_usd=0.02, payment_chain_id=56, payment_token="USDT", ) print(f"卖单 #{order_id} 已创建") print("Keeper 自动处理后续,无需任何操作")
查询 API
Order 对象属性
pythonorder = client.get_order(0) # 核心字段 order.id # int 订单 ID order.seller # str 卖方地址 order.buyer # str 买方地址 (成交后) order.amount_wei # int AXON 数量 (wei) order.amount_axon # float AXON 数量 (property) order.price_per_token # int 单价 (6-decimal, $7.50 = 7_500_000) order.price_usd # float 单价 USD (property) order.total_payment # float 总价 (property) order.payment_chain_id # int 56 | 42161 order.payment_chain_name # str "BSC" | "Arbitrum" (property) order.payment_token # str "USDT" | "USDC" order.seller_payment_addr # str 卖方收款地址 order.status # int 0-4 order.status_label # str "Active" | "Completed" | ... order.created_at # int 创建时间戳 order.cancel_requested_at # int 取消请求时间戳
其他查询
python# 我的订单 my = client.get_my_orders() my["as_seller"] # [0, 2, 5] my["as_buyer"] # [1, 3] # 总量 client.get_order_count() # 余额 client.axon_balance() client.stablecoin_balance(56, "USDT") client.stablecoin_balance(42161, "USDC")
方法速查
buyer methods
| method | returns | 说明 | gas |
|---|---|---|---|
buy_full(order_id) | dict | 推荐 获取地址 + 转 USDT | BSC/Arb |
send_payment(order_id, payment_address?) | str tx_hash | 转 USDT 到专属地址 | BSC/Arb |
get_payment_info(order_id) | dict | 查询付款地址和金额 | 无 |
seller methods
| method | returns | 说明 | gas |
|---|---|---|---|
create_sell_order(amount_axon, price_usd, payment_chain_id, payment_token, seller_payment_addr?) | tuple[int, str] | 创建卖单 | Axon |
request_cancel_order(order_id) | str tx_hash | 请求取消 (15min 冷却) | Axon |
finalize_cancel_order(order_id) | str tx_hash | 冷却后执行取消 | Axon |
abort_cancel(order_id) | str tx_hash | 中止取消 → Active | Axon |
seller_release(order_id, buyer) | str tx_hash | 手动放币 (仅 Keeper 异常时) | Axon |
shared methods
| method | returns | 说明 | gas |
|---|---|---|---|
raise_dispute(order_id) | str tx_hash | 发起争议 | Axon |
list_active_orders(offset?, limit?) | tuple[list[Order], int] | 活跃卖单列表 | 无 |
get_order(order_id) | Order | 订单详情 | 无 |
get_my_orders(addr?) | dict | 我的订单 | 无 |
get_order_count() | int | 订单总数 | 无 |
axon_balance(addr?) | float | AXON 余额 | 无 |
stablecoin_balance(chain_id, token, addr?) | float | 稳定币余额 | 无 |
合约信息
| key | value |
|---|---|
| contract | 0x10063340374db851e2628D06F4732d5FF814eB34 |
| chain | Axon (Chain ID: 8210) |
| version | OTCEscrowV7 |
| fee_rate | 0.3% (30 bps, 成交时从 AXON 扣除) |
| cancel_cooldown | 15 min (900s) |
| underpay_tolerance | 0.5% |
安全机制
| threat | defense |
|---|---|
| 伪造付款证明 | submitPaymentProof 已删除,买方无法提交 |
| 自助提币攻击 | buyerSelfClaim 已删除,买方无法绕过 Keeper |
| 锁单 DoS | v7 无锁单机制,攻击面不存在 |
| 卖方恶意取消 | 15min 冷却期,冷却中买方仍可购买 |
| 重复付款 | 先到先得,后到自动退款 |
| 零价格 | 合约强制 pricePerToken > 0 |
| 资金卡死 | adminForceCancel 可退任何非终态 |
争议处理
异常情况(付款 >5min 未收到 AXON、转错金额等):
python# 任一方可发起争议 client.raise_dispute(order_id) # → order.status = Disputed (3) # → 等待管理员 resolveDispute()
管理员可以:发起争议冻结 → adminForceCancel 退 AXON → 协调退 USDT。联系方式见项目公告渠道。
安全须知
// buyer
✓ 使用 buy_full() 自动获取正确地址和金额
✗ 向 seller_payment_addr 转账 (那是卖方收款地址)
✓ 重复付款时 Keeper 自动退款
// seller
✗ 手动调用 seller_release() (除非已确认链上 USDT 到账)
✓ 挂单后无需操作,Keeper 自动放款
// general
✓ 私钥通过环境变量传入
✗ 硬编码私钥 / 提交 .env 到 git
✓ 手续费 0.3% 从 AXON 扣除,卖方收全额 USDT
✓ 同一私钥控制 Axon/BSC/Arb 地址