跳到主要内容

与流动性提供方的 RFQ Swap

状态:规范(LP 协议 v1,2026-09-23 草案)。 本节是 Rocky 正在按其实现的接口契约。除非在 变更日志 中公告,v1 的路径、字段名与状态值不再变动;标注 v2 的内容不属于首个版本。

外部机构在 Rocky 提供流动性有两种方式:

订单簿做市RFQ Swap(本节)
提供流动性的方式用自己的 party 在现货订单簿挂限价单应答询价;每笔交易是一次私下的、按报价成交的 swap
谁发起交易任何吃掉你挂单的 taker使用 Swap 页或钱包内 swap 功能的交易者
你的接入面作为客户端使用现货 REST/WS(做市商指南)一个由你托管、由 Rocky 调用的 HTTPS 服务(LP 服务接口),以及你调用的 Rocky 接口(面向 LP 的接口)
Last look无:挂单即承诺有:在 accept-and-allocate 逐笔接受或拒绝
结算在你的 MemberAuth 下两腿 DvP,按对手方对净额双方各自以 Token Standard allocation 锁定,Rocky 在双方 MemberAuth 下一笔交易执行
交易所手续费钱包托管段为零交易者付 taker 费;v1 中 maker 费为 0
你在链上签什么MemberAuth 一次接入时签一次 MemberAuth,之后每接受一笔交易签一次 AllocationFactory_Allocate

两种模式并存,同一家机构可以用同一个 party 同时运行两者。

参与方​

参与方Canton party在一笔 swap 中的角色
交易者(钱包提供方)用户自己的 party,私钥在钱包请求报价,把输入金额锁进 allocation,swap 未结算时解锁。从不与 LP 通信。
Rocky(场所与执行方)操作员 party Rocky::…(executor);手续费腿收款用手续费 party向 LP 广播询价、选最优报价、对照冻结报价核验双方 allocation、一笔原子执行所有转账腿、记录成交。
流动性提供方(LP)你的 party,托管在你运营的 validator 或钱包对询价定价;接受交易时把输出金额(以及非零时的 maker 费)锁进 allocation。

Rocky 从不持有 LP 的库存或密钥;结算前 LP 也从不持有交易者资金:在 Allocation_ExecuteTransfer 执行之前,双方的 allocation 仍归各自所有,过了结算期限即可撤回。

时序​

交易者钱包 Rocky LP 服务 Canton
│ GET 报价 │ │ │
│─────────────────────►│ POST /rfq/quotes(所有 LP) │ │
│ │───────────────────────────────────►│ │
│ 最优报价, rfqId │◄───────────────────────────────────│ │
│◄─────────────────────│ │ │
│ POST /v1/swaps/rfq │ │ │
│─────────────────────►│ swapId, 需签名的 allocation │ │
│ prepare → 签名 → execute(AllocationFactory_Allocate:输入 + taker 费) │
│──────────────────────────────────────────────────────────────────────────────────►│
│ │ POST /rfq/trades/{swapId}/accept-and-allocate │
│ │───────────────────────────────────►│ Allocate(输出) │
│ │ │──────────────────────►│
│ │ ALLOCATED + allocation cid │ │
│ │◄───────────────────────────────────│ │
│ │ 对所有腿 Allocation_ExecuteTransfer,一笔交易 │
│ │───────────────────────────────────────────────────────────►│
│ SUCCEEDED, updateId │ POST /rfq/trades/{swapId}/result │ │
│◄─────────────────────│───────────────────────────────────►│ │
  1. 报价。 交易者向 Rocky 询价(symbol、side、baseQty)。Rocky 向该交易对上所有活跃 LP 各发一次 POST /rfq/quotes,最多等待报价超时时间,然后以 rfqId 返回最优可成交价,有效期数秒。交易者看到的是含费用的到手金额。
  2. 创建。 交易者接受报价:POST /v1/swaps/rfq 把价格、金额、费用与结算窗口冻结到一个 swapId 上,并精确返回钱包需要 allocate 的内容。
  3. 交易者 allocate。 钱包执行 AllocationFactory_Allocate:输入金额(receiver 为 LP party)与 taker 费(receiver 为 Rocky 手续费 party),executor 为 Rocky 操作员 party,settlementRef.id = swapId。Rocky 可以为外部签名准备好这笔交易,钱包也可以自己构造。
  4. LP 接受并 allocate。 Rocky 在账本上核验交易者的 allocation 与冻结行一致,然后调用你的 accept-and-allocate。你有 last look:要么把输出金额 allocate 给交易者(同一 executor、同一 settlementRef)并回复 ALLOCATED,要么回复 REJECTED。
  5. 结算。 Rocky 在你的 MemberAuth 上执行 Auth_OpenAllocations(peer 为交易者的 MemberAuth),在一笔 Canton 交易里对每一腿执行 Allocation_ExecuteTransfer。要么全部转移,要么全不转移。
  6. 回报。 交易者轮询得到 SUCCEEDED 与 cantonUpdateId;Rocky 把结果推送到你的服务,并可在 GET /v1/lp/trades/{swapId} 查询。

资金流向​

交易者 ──[baseQty 或 quoteQty,即输入]──► LP
交易者 ──[taker 费]────────────────────► Rocky 手续费 party
LP ──[输出金额]─────────────────────► 交易者
LP ──[maker 费,v1 为 0]────────────► Rocky 手续费 party

金额在创建 swap 时固定,之后不再重算:交易者的 execute 与你的 accept-and-allocate 对照同一冻结行核验,Allocation_ExecuteTransfer 精确转移每个 allocation 中的数量。任一方 allocate 的金额、资产或收款方不同,Rocky 就不结算。

费用​

腿付费方v1 取值说明
taker 费交易者现货 taker 费率(5 bps)按输入计,加上 Swap 页固定的网络执行成本(按报价折算成输入资产;计价资产不是美元代币的市场为 0)两者都以输入资产计,合并为一条手续费腿 allocate 给手续费 party,LP 始终把全部输出付给交易者
maker 费LP0 bps每条消息中都保留该字段,未来引入非零或负值(返佣)不需要改协议
Canton 流量各参与方为自己提交与确认的部分付费—你为自己的 Allocate 与结算确认付费;Rocky 为执行交易付费。见 Canton 流量。

时间窗口​

窗口默认含义
报价超时800 msRocky 等待 POST /rfq/quotes 的时长;迟到或非 200 视为无报价
报价有效期(validUntil)由你决定,≤ 5 s过期报价不会被用来创建 swap
接受超时5 sRocky 等待 accept-and-allocate 的时长
allocateBefore创建 + 60 s双方 allocation 必须在此之前上链,否则 swap 为 EXPIRED
settleBefore创建 + 120 s此后 allocation 可由发送方撤回;Rocky 的 executor 会在此之前尽量取消

状态机​

QUOTED ──► TRADER_ALLOCATING ──► TRADER_ALLOCATED ──► LP_ACCEPTING ──► LP_ALLOCATED ──► SETTLING ──► SUCCEEDED
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
EXPIRED EXPIRED EXPIRED LP_ACCEPT_FAILED CANCELLED SETTLEMENT_FAILED
状态终态交易者输入LP 输出接下来
QUOTED否未锁—钱包尚未 allocate
TRADER_ALLOCATING否提交中—Rocky 等待 allocation 在账本可见
TRADER_ALLOCATED否已锁—Rocky 正在核验
LP_ACCEPTING否已锁—正在调用你的服务
LP_ALLOCATED否已锁已锁Rocky 正在提交结算
SETTLING否已锁已锁结算已提交,等待确认;瞬时错误会重试
SUCCEEDED是已转移已转移cantonUpdateId 已写入
EXPIRED是未锁或可撤回—allocateBefore 前没有 allocation
LP_ACCEPT_FAILED是可撤回—你拒绝、超时或 allocation 不匹配;Rocky 取消交易者 allocation,钱包也可 Allocation_Withdraw
SETTLEMENT_FAILED是可撤回可撤回执行终态失败;Rocky 取消双方 allocation;settleBefore 后任一发送方可撤回
CANCELLED是可撤回可撤回Rocky 在结算前放弃(运营操作或核验不匹配)

SETTLING 的重试策略与现货结算器一致:传输与竞争类瞬时错误在 settleBefore 窗口内按退避重试;Daml 授权失败或 allocation 缺失为终态。

记录方式​

SUCCEEDED 的 swap 是一笔场所成交:与结算行同一事务写入成交日志,纳入下一次 epoch 承诺,在交易者的 GET /api/v3/myTrades 中以 source: "RFQ" 及其 cantonUpdateId 呈现,并在你的 GET /v1/lp/trades 中可查。它不是订单簿成交:不会出现在 @trade 流、K 线或 24 小时行情中。

本节页面​