“待处理”“已发送”“已确认”和“已成交”常常出现在同一个界面上,很容易被读成同一架梯子上的不同台阶。它们通常描述的是两件不同的事。订单在交易场所有自己的生命周期:它被接受或拒绝,可能挂在订单簿中,可能部分成交,也可能被撤销。区块链交易也有自己的生命周期:它被签名、提交、处理、确认、最终确定,或者失败、从未上链。把两者混在一起的记录,可能显示一笔从未发生的交易,也可能漏掉一笔确实发生的交易。
两套状态机,两类证据
订单状态回答的是一个交易问题:交易场所是否把我的指令与另一笔订单撮合了,成交的数量和价格是多少?交易状态回答的是一个账本问题:网络是否打包了我签名的交易,它是否无错误地执行,这条记录现在的确定程度如何?
有时两者相互依赖。链上兑换只有在对应交易成功执行时才能完成。有时两者几乎无关:一笔充值交易把抵押资产转到交易场所,之后下的订单有自己的标识符和状态。无论哪种情况,来自一套状态机的状态都不是另一套状态机的证据。一笔已最终确定的充值不能证明订单已成交,一笔标记为已成交的订单也不能证明提现已结算。
交易场所上的订单生命周期
各家交易场所对状态的命名不同,所以要阅读具体的文档。Hyperliquid 的 exchange 端点文档是一个有用的例子。下单会在一个状态列表中返回逐笔订单的结果。其示例显示:挂单结果带有订单 ID(oid),成交结果带有总数量、平均价格和 oid,错误结果带有消息。有一个错误响应示例的顶层状态仍然是“ok”,所以请求被接受并不等于订单成功。要读逐笔订单的那一条。
同一份文档允许订单携带一个可选的客户端订单 ID(cloid),这是你在提交前自行选择的 128 位十六进制字符串。Hyperliquid 的订单状态查询接受 oid 或 cloid,并返回该订单及其状态和状态时间戳。列出的取值包括 open、filled、canceled、triggered 和 rejected,还有许多具体原因:因保证金不足被撤销、因自成交防范被撤销、因强平被撤销,或因无效的 tick 价格、市价单缺乏流动性而被拒绝。找不到的订单会返回未知订单响应。
部分成交需要格外小心。一个状态标签可以描述订单,而它的数量却讲述另一个故事:可能有一部分已经执行,其余部分仍在挂单,或后来被撤销。已执行数量、价格和手续费应当从交易场所的成交记录中核对,而不是从一个状态词推断。订单类型指南解释了为什么限价、市价或触发指令可能导致不同的结果。
链上的交易生命周期
在 Solana 上,钱包构建一笔交易,用户签名,然后它被发送到网络。手续费以 SOL 支付。如果交易被打包,RPC 节点可以在不断提高的承诺级别上报告它:processed、confirmed 和 finalized,其中 finalized 最强。交易也可能执行时出错,这仍可能产生手续费,或者根本没有被打包而最终过期。Solana 交易如何运作讲解了签名、手续费和确认,而关于待处理、已确认和已最终确定状态的指南比较了 Bitcoin、Ethereum 和 Solana 如何用相似的词表达不同的事情。
这里的标识符在 Solana 上是交易签名,在其他链上是交易哈希。它标识一条记录;其本身并不能证明付款或交易。关于交易哈希标识什么的讲解涵盖了这一区别。要查询一笔交易,请在正确的集群上查看 Solana 签名,并阅读它的状态和任何错误。
为什么“已发送”或“待处理”不是成交
钱包显示“已发送”,通常意味着一笔已签名的交易离开了钱包。它还没有告诉你网络是否打包了这笔交易、交易是否执行,或者买到了什么。兑换界面显示“待处理”时也是同样的情况:在交易成功执行之前,这笔交易并未发生,而收到的数量就是已执行交易在其限制范围内实际交付的数量。如果一笔兑换看起来卡住了,关于 Jupiter 兑换待处理或失败的指南解释了重试前应检查什么,以免第二次尝试造成重复交易。
反向的混淆也会发生。在交易场所上,提交的指令可以在请求层面被接受,却在订单层面被拒绝,或者挂单数小时未成交。“已提交”描述的是你的动作,而不是市场的回应。
一个虚构的对账示例
设想一位虚构的交易者,他向交易场所存入稳定币抵押资产,然后下一笔限价买单。以下所有标识符和时间均为虚构。
| 时间(UTC) | 事件 | 状态机 | 观察到的状态 | 它证明了什么 |
|---|---|---|---|---|
| 09:00:05 | 充值已签名 | 链 | 返回签名 | 一笔交易已创建并发送 |
| 09:00:20 | 充值已查询 | 链 | 已最终确定,无错误 | 该转账已记录在网络上 |
| 09:02:10 | 交易场所余额 | 交易场所 | 抵押资产已入账 | 交易场所执行了自己的入账步骤 |
| 09:05:00 | 限价买单,cloid 0xA1… | 交易场所 | 挂单中,oid 4411 | 订单有效,尚未执行任何数量 |
| 09:40:00 | 同一订单 | 交易场所 | 1.0 中已执行 0.6 | 部分成交,而非完整仓位 |
| 10:00:00 | 剩余部分已撤销 | 交易场所 | 已撤销 | 最终数量为 0.6,以记录的成交为准 |
只有交易场所的成交记录显示买到了什么。只有链上记录显示充值已到账。中间的入账步骤属于交易场所,它可以在网络已最终确定一笔转账之后适用自己的规则。
交易日志中应记录什么
对每笔订单:交易场所、交易标的、方向、原始数量、限价或触发价格、你设置的 cloid(如有)、交易场所的 oid、提交时间、每个状态及其时间戳,以及每笔成交的数量、价格和手续费。对每笔交易:链和集群、签名或哈希、你观察到的承诺级别及观察时间、任何错误、支付的手续费以及由此产生的余额变化。在区块浏览器中读取交易的指南说明了哪些字段承载这些证据,以及它们不能证明什么。
在提交前设置客户端订单 ID 很有用,因为即使响应丢失,它也能把你自己的记录与交易场所记录关联起来。交易日志模板可以把两栏并排放在一起。模拟记录也应放在自己的一栏:SuperQuant 附带的示例使用合成的每小时数据和模拟成交,它不下真实订单,也不验证真实执行。模拟交易与实盘交易的比较解释了为什么模拟成交和交易场所成交是不同的证据。
继续学习
使用 Solana 学院课程从签名到区块浏览器检查,一步步搭建交易这一侧的知识。在交易方面,可搭配阅读限价单与市价单有何不同,并在每条日志记录中保留两个标识符。本文为教育性研究内容,不构成投资建议。