Skip to main content
你提交一笔订单,链就给它分配一个订单 ID。那个 ID 是权威的,可你要等订单被接受之后才知道它——假如你正要撤的,恰恰是一笔你压根没看到有没有被接受的订单,麻烦就来了。 客户端订单 ID 解决的就是这个。标识符由你自己生成,在提交时附上,从你发出请求的那一刻起就可以用它来操作这笔订单。

为什么这件事比听上去重要

设想一次提交超时。它到链上了吗?你不知道。没有客户端订单 ID,你要么去查最近的订单,靠市场、方向、价格和数量去猜;要么什么都不做,听天由命。 有了它,这种含糊就消失了。你用自己生成的标识符撤单。如果订单存在,它被撤掉;如果它从未到达,撤单请求什么都找不到。无论哪种情况,你都停在一个确定的状态上——没人盯着的系统,要的正是这个。 对账也因此才做得下来。你自己的记录以你分配的标识符为键,所以把你这边的视图和链上的对上,是一次查表,不是一次启发式猜测。

格式

标识符是一个 16 字节的值,提交时写成 0x 前缀、小写、共 32 个字符的十六进制字符串。
协议强制执行三条规则:
  • 只接受小写。 大写十六进制会被拒绝,而不是被规范化。
  • 长度必须精确。 更短或更长的值都会被拒绝。
  • 全零值被保留。 0x00000000...0000 是表示不存在的哨兵值,不能用作标识符。
这个字段是可选的。不带它的订单在各方面都表现正常——只是不能通过客户端订单 ID 撤单,只能用链上分配的订单 ID。

唯一性

唯一性的作用范围是子账户:签名地址与其下子账户的组合。 由此有两个推论。同一地址下的不同子账户可以使用相同的标识符而不冲突——在运行各自生成 ID 的独立策略时很有用。而在同一个子账户内,把一个还挂在活动订单上的标识符再用一次,是错误,不是替换。
标识符要随机生成,不要用递增序号。计数器很诱人,因为它让顺序一目了然;可是重启一次把计数器丢了,就会和还活着的订单撞上,而 16 个随机字节在实践中永远不会碰撞。

你能用它做什么

生命周期

标识符属于订单,不属于你的会话。订单成交或撤销之后照样查得到,事后对账好用就好用在这里。 它标识的那笔订单一旦不再活动,这个标识符就能复用。但实践中几乎没有复用的理由——重新生成一个随机值成本为零,还免去了“某条历史记录到底指哪笔订单”的疑问。

后续阅读

修改订单

改动一笔活动订单,以及它的标识符会怎样。

订单类型

你可以给哪些东西附上标识符。

开发者

在代码中提交订单并处理含糊的响应。

交易排序

为什么同一区块内提交的撤单会先于主动吃单执行。