Skip to main content
订单服务器从用户那里接收意图(订单)并将其广播给求解器。它负责:
  1. 从各种来源收集用户意图。
  2. 实时向已连接的求解器广播这些意图。
  3. 跟踪所有交易的链上状态。
我们推荐使用订单服务器,因为它内置了安全检查,但_对于链上订单_,它完全是可选的。不过,并非所有意图都会上链——例如 lintent.org 就不会在链上发出意图。而任何你自己从链上读取的意图,都必须经过补全并进行非常彻底的验证。

订单订阅

有两种方式可以收集订单:一种是会向你推送订单的 WebSocket 订阅,另一种是你自行轮询的 GET 端点。我们推荐使用 WebSocket 订阅。这两种方式都可以在 lintent.org 演示实现中找到。 如果您过于频繁地使用 GET 端点,您可能会被限流或暂时超时。您可以在 https://order-dev.li.fi/docs 上找到关于 api 接口的 swagger 文档。
您可能会通过 WebSocket 接口多次收到同一个订单。每当从一个真实来源摄取意图时,都可能发生这种情况,而后续的副本可能携带额外的上下文。请使用 orderId 来识别一个意图,并在后续副本携带额外上下文时保留它。

订单服务器事件

WebSocket 主机地址为 wss://order.li.fi(生产环境)或 wss://order-dev.li.fi(开发环境)。消息是形如 { "event": string, "data": ... } 的 JSON 帧:
  • user:vm-order-submit —— 有新订单可用。返回的数据格式与提交时类似:完整订单加上元数据(订单 id、状态、时间戳、报价 id)。
  • intent:transaction-observed —— 当订单变为 Delivered、Finalised 或 Refunded 时的生命周期更新。
  • 心跳 —— 服务器每 5 秒发送一次 {"event": "ping"};请在 10 秒内回复 {"event": "pong"},否则连接会被关闭。这用于断开行为异常的客户端,并用于调试目的。您可以在此处找到示例实现。

订单验证

LI.FI Intents 允许高度可定制的订单,因此您必须添加自己的验证,以确认您支持转发给您的每一笔订单。 下文中,“白名单”是指由您信任并验证过的。当某个代币_必须_被列入白名单时,意味着您已经审核过该代币。如果某个验证层被列入白名单,意味着您已经审核过该验证层,以此类推。白名单并不意味着由某个中心化实体授权。 以下清单旨在涵盖求解器必须实现的每一项验证。它可能看起来很长,但您很可能已经实现了其中的大部分检查。

通用验证

  1. fillDeadline:确保您有足够的时间填充订单:
    • 在目标链上填充的时间,包括潜在的源链最终性。
  2. expires:确保您有足够的时间填充、转发和领取订单:
    • 在目标链上填充的时间,包括潜在的源链最终性。
    • 将消息验证证明发送到输入链的时间。
    • 验证送达后领取订单的时间。
  3. 验证层:确保您支持向验证层提交证明(如果不是自动的,还需转发)。此外,inputOracle 和 output.oracle 必须属于同一个验证层。
  4. 确保您已将每个 input 代币列入白名单。如果某个输入代币是恶意的,订单可能无法领取。此外,对于像 USDC 这样可被列入黑名单的代币,请确保您不在黑名单上。
    • 如果订单的输入或输出中包含 0 数量的某个您未列入白名单的代币,该订单可能无法填充。在填充包含不熟悉代币的订单时请务必小心。
  5. 对于每个输出:
    1. output.chainId 已列入白名单。
    2. output.oracle 和 inputOracle 就 originChainId 和 output.chainId 而言配置正确。链上配置是不可变的,因此这对每个链对只需做一次。
    3. output.settler 已列入白名单。
    4. output.context 可解码,且订单类型受支持并与 output.settler 兼容。
    5. output.token 已列入白名单。此外,对于像 USDC 这样可被列入黑名单的代币,请确保您和接收方都不在黑名单上。
      • 如果订单的输入或输出中包含 0 数量的某个您未列入白名单的代币,该订单可能无法填充。在填充包含不熟悉代币的订单时请务必小心。
    6. 您有足够的代币用于 output.amount。
    7. 如果输出包含 calldata,请确保您能够原子性地执行它以及其他输出。对于不同链上的输出,如果存在 calldata,您可能必须将接收方列入白名单。
      • 在 OP 链上,CrossL2Inbox 需要在整个调用树中被列入黑名单。如果其他链上存在类似的合约,它们也需要被列入黑名单。
    8. call.length 和 context.length 都不超过 65,535 字节长。
    9. 根据订单类型验证上下文。具体针对 Bitcoin,请确保编码的乘数是相对于 Bitcoin 值的。
  6. 如果订单有多个输出,请确保您能够填充所有输出,且第一个输出设置为您的求解器标识符。如果所有输出都在同一条链上,作为一种保护措施,单次 fillOrderOutputs 调用即可全部填充。
  7. 如果 InputSettler 有任何费用,请检查是否有即将发生的费用变更。
在 EVM 和 Tron 上,输入代币以 uint256 编码;前 12 字节可能存放一个 lock tag,地址是最后 20 字节。而 Solana 订单携带的是单个 MandateInput { token: Pubkey, amount: u64 }。在 Solana 的信息流消息中,顶层地址以 base58 渲染,而输出的 oracle、settler、token 和 recipient 值仍然是 32 字节字段。

Escrow 验证

  1. 确保没有任何输入代币是转账时收费(fee on transfer)的。
  2. 确保每个 inputs 代币的高 12 字节中没有设置任何位。
  3. 确保订单已经被打开,可以通过 event Open 或 function orderStatus,或者您在填充订单之前通过 function openFor 打开订单。

Solana 验证

Solana 订单仅支持 Escrow,因此下方的 Compact 检查不适用。除了通用验证之外,还需检查:
  1. 身份字段。 从已发布的程序 id 和种子重新推导订单中的每一个 32 字节身份字段——outputs[].settler、outputs[].oracle、inputOracle(或者将已发布的地址钉住作为标准值),并与身份矩阵进行核对。只要有任何不匹配,就拒绝该订单。
  2. u64 边界。 超过 u64::MAX 的 MandateOutput.amount 和荷兰式拍卖 slope 值会使某个输出在 Solana 上无法被填充(见拍卖)。
  3. 回调。 默认的 Solana 输出结算器要求 callback_data 为空,否则会拒绝填充。
  4. 接收方账户。 对于 SPL 输出,recipient_token_account.owner 必须等于 recipient;如果接收方还没有代币账户,你可能需要支付 ATA 的租金。
  5. 订单大小。 一个没有 calldata、使用标准 context 的单输出订单,始终可以安全地完结。超出这个范围的任何情况,都需要针对完结交易的限制进行彻底验证——精确的界限见订单大小。

Compact 验证

  1. 确保每个 input 代币使用相同的 allocatorId。如果 lockId 不同,则应检查每个 lockId 的锁过期时间;如果它们都相等,则只需检查一次过期时间。
  2. 确保资源锁的潜在 reset period 延伸到 expiry 之后,并且没有活跃的提款。
  3. 确保 allocatorID 已列入白名单。分配器可以阻止领取的处理(通过撤回签名或重用 nonce)。
    • allocatorID 是 inputs 的 lock tag(前 12 字节)的一部分。
    • 可选地,确保用户有足够的代币。不过这应该已经由分配器验证过了。
  4. 确保用户提供了 ECDSA 签名或者他们注册了列入白名单的 emissary或者您在填充领取之前在链上注册了该领取。
    • 注意:如果采取了这些操作中的任何一个,则可以假定签名是可信的。
    • emissary 签名无法在链上注册。必须信任 emissary 不会撤回签名。
  5. 验证 allocatorData。您可能需要进行链上调用。
  6. 验证分配器 nonce 之前未被任何用户使用过。订单 nonce 不是用户 nonce。

签名验证

StandardOrder 是您用来对接输入链上所有函数的对象。此外,一旦填充了签名,它也让您可以核实一笔订单是否有效。 StandardOrder 结构体将被签名并作为见证存储在相应的锁/领取结构中。对于 TheCompact,这是:
要验证订单,请确保 sponsor 和 allocator 的签名对于这个 EIP-712 签名结构是有效的。

链上订单广播

当意图在链上注册时,可以通过输入结算合约上的 IntentRegistered 事件进行广播:
在收集无需许可的订单时,请确保它们经过正确验证和共同签名。订单服务器有助于验证,但在链上,任何人都可能发出欺诈性消息。