金额与资金

微单位、字符串字段,以及为什么 USDT 的小数位数不止一种。

全部使用微单位

本 API 中的每个金额都是以微单位表示的整数:精确到小数点后 6 位。

25000000  ==  25.000000 USDT
     100  ==   0.000100 USDT

之所以用整数,是因为用浮点数表示金钱,就是一个迟早会发作的错误。之所以是 6 位,是因为在 USDT 小数位数最少的那条链上,它自身的精度就是 6 位。

字符串字段不是摆设

每个金额字段都会出现两次:

{ "amount": 25000000, "amount_decimal": "25.000000" }

amount_decimal 之所以存在,是因为 JavaScript 在 JSON 中没有整数JSON.parse 给你的是双精度浮点数,而 25000000 / 1e6 不一定等于 25。超过 2^53 微单位——约 90 亿 USDT——整数本身就不再精确。

能帮你避坑的规则:

在请求中传入金额也是一样。传入 amount amount_decimal,不要两者都传:

{ "amount_decimal": "25.00" }
{ "amount": 25000000 }

USDT 的小数位数因链而异

Tron 上是 6 位。BSC 上是 18 位。这是代币合约的属性,而不是链的属性,也是转账金额相差一万亿倍这类错误最常见的根源。

你完全不必操心:API 的每个字段都使用微单位。链上原始值会以 amount_raw 按付款路由公布,并附带 token_contract,供需要关心这一点的钱包使用。

amount_raw字符串,原因正如上文所述——25 × 10^18 无法放进双精度浮点数,而在 BSC 上每个金额都是这个数量级。

精确金额就是标识

在默认的共享地址策略下,同一个地址上可能同时有多笔付款在等待到账。区分它们的是精确金额:系统会把金额调整几个微单位,确保同一地址上不会有两笔未完成的付款要求相同的数额。

这带来两个结果:

  1. 向客户展示付款路由中的金额,而不是你请求的金额。两者可能相差几个微单位,而付款路由中的值才是能匹配上的那个。
  2. 金额错误的转账不会被静默入账。它会变为 underpaidoverpaid,这两种状态都会触发事件,也都由你决定如何处理。

取整

不需要做任何取整。按你实际收取的精确数额创建付款即可;网关不会取整,低于配置最低金额的金额会以 amount_too_small 被拒绝,而不会被向上取整成客户没有同意的数额。