跳到主要内容

LP 服务接口

状态:规范(LP 协议 v1,2026-09-23 草案)。 这些接口由你实现、Rocky 调用。v1 的字段名与状态值不再变动。

你的服务是一个 HTTPS API,地址为你在接入时登记的 serviceUrl。Rocky 从集成包中列出的固定出口 IP 调用它。请求体均为 JSON;所有小数为字符串;所有时间为 RFC 3339 UTC、毫秒精度。

Rocky 请求的鉴权​

Rocky 发出的每个请求都带 Ed25519 签名,供你证明请求来自 Rocky:

头值
X-ROCKY-KEY-IDRocky 签名密钥标识
X-ROCKY-TIMESTAMP签名时的 Unix 毫秒时间戳
X-ROCKY-SIGNATURE对下述规范字符串的 Ed25519 签名,base64
Idempotency-Key询价用 rfqId,交易相关调用用 swapId

规范字符串(UTF-8,\n 分隔,末尾无换行):

<X-ROCKY-TIMESTAMP>\n<METHOD>\n<含查询串的路径>\n<原始请求体的 SHA-256 小写十六进制,空体则为空串的 SHA-256>

Rocky 的公钥发布在 GET /v1/lp/signing-keys,其指纹在接入时通过第二渠道向你复读,流程与机构接入中登记你自己的密钥相同。时间戳与你本地时钟相差超过 30 s 的请求应拒绝;重复的 Idempotency-Key 视为同一请求,返回相同答复。

要求 TLS 1.2 及以上。你也可以要求客户端证书(mTLS),Rocky 按需支持。

GET /health​

Rocky 每 10 s 轮询一次,并在每次询价广播前调用。非 200 或超时(2 s)会把你移出广播,直到下一次健康答复;连续三次失败会把你的 LP 登记置为 DEGRADED 并通知 Rocky 运营。

{
"status": "ok",
"party": "lp-acme::1220…",
"symbols": ["CBTC-USDCB", "CETH-USDCB"],
"time": "2026-09-23T08:00:00.000Z"
}

symbols 让你在运行时收窄接收询价的交易对;只能是你登记交易对的子集。

POST /rfq/quotes​

Rocky 请求一个可成交价。你有报价超时(默认 800 ms)的时间答复;迟到或非 200 视为无报价。

请求:

{
"rfqId": "7d2f5a4e-1b0e-4f2a-9a5b-1c2d3e4f5a6b",
"symbol": "CBTC-USDCB",
"side": "SELL",
"baseQty": "0.0125",
"baseInstrument": { "admin": "…", "id": "CBTC" },
"quoteInstrument": { "admin": "…", "id": "USDC.B" },
"requestedAt": "2026-09-23T08:00:00.120Z",
"quoteDeadline": "2026-09-23T08:00:00.920Z"
}
字段含义
side以交易者对基础资产的视角:SELL 表示交易者付出基础资产、收到计价资产;BUY 表示交易者付出计价资产、收到基础资产。
baseQty基础资产数量,已按交易对 stepSize 取整。v1 始终按基础数量询价。
baseInstrument / quoteInstrumentToken Standard 资产标识,与 allocation 中出现的一致。
quoteDeadlineRocky 停止等待的时刻。

响应 200:

{
"rfqId": "7d2f5a4e-1b0e-4f2a-9a5b-1c2d3e4f5a6b",
"quoteId": "acme-q-000123",
"price": "86206.60",
"baseQty": "0.0125",
"quoteQty": "1077.5825",
"validUntil": "2026-09-23T08:00:04.000Z",
"party": "lp-acme::1220…"
}

price 为每单位基础资产的计价资产数量,按交易对 tickSize 取整;quoteQty = baseQty × price,按计价资产精度取整。validUntil 最多为 requestedAt 之后 5 s。交易者收到的是扣除 Rocky 费用后的 quoteQty,费用在这一步与你无关。返回 204 或 {"quoteId": null} 表示你放弃报价。

Rocky 在有效答复中选最优价(SELL 取最高 quoteQty,BUY 取最低);同价取最早到达者。只有胜出的 LP 会收到交易调用。报价不是成交承诺,你的承诺是 accept-and-allocate。

POST /rfq/trades/{swapId}/accept-and-allocate​

交易者已接受你的报价并在链上锁定了输入。Rocky 已对照冻结的 swap 核验了交易者的 allocation。你有接受超时(5 s)的时间锁定输出。

请求:

{
"swapId": "01a0d0f2-6c3a-7b1e-8f2a-3b4c5d6e7f80",
"quoteId": "acme-q-000123",
"symbol": "CBTC-USDCB",
"side": "SELL",
"price": "86206.60",
"baseQty": "0.0125",
"quoteQty": "1077.5825",
"trader": { "party": "rockywallet-user::1220…" },
"traderAllocation": {
"contractId": "00a1…",
"updateId": "1220…",
"instrument": { "admin": "…", "id": "CBTC" },
"amount": "0.0125"
},
"legs": {
"lpSends": { "instrument": { "admin": "…", "id": "USDC.B" }, "amount": "1077.5825", "receiver": "rockywallet-user::1220…" },
"lpFee": null
},
"settlement": {
"executor": "Rocky::1220…",
"settlementRef": { "id": "01a0d0f2-6c3a-7b1e-8f2a-3b4c5d6e7f80", "cid": null },
"requestedAt": "2026-09-23T08:00:05.000Z",
"allocateBefore": "2026-09-23T08:01:05.000Z",
"settleBefore": "2026-09-23T08:02:05.000Z"
},
"disclosedContracts": [ { "templateId": "…", "contractId": "00a1…", "createdEventBlob": "…", "synchronizerId": "…" } ]
}

legs.lpSends 就是你必须创建的 allocation:该资产、该数量、该收款方,并把 settlement 原样填入 allocation 的 SettlementInfo。maker 费为 0 时 legs.lpFee 为 null;非空时是第二个 allocation,收款方为 Rocky 手续费 party。disclosedContracts 让你的 participant 能读到交易者的 allocation,便于你自行核验。

接受时响应 200:

{
"swapId": "01a0d0f2-6c3a-7b1e-8f2a-3b4c5d6e7f80",
"status": "ALLOCATED",
"allocations": [
{ "contractId": "00b2…", "instrument": { "admin": "…", "id": "USDC.B" }, "amount": "1077.5825", "receiver": "rockywallet-user::1220…" }
],
"updateId": "1220…",
"disclosedContracts": [ { "templateId": "…", "contractId": "00b2…", "createdEventBlob": "…", "synchronizerId": "…" } ]
}

拒绝时响应 409:

{ "swapId": "01a0d0f2-…", "status": "REJECTED", "reason": "PRICE_MOVED" }
reason含义
QUOTE_EXPIRED调用到达前 validUntil 已过
PRICE_MOVED你的 last-look 检查未通过
INSUFFICIENT_INVENTORY你已不持有该输出数量
RATE_LIMITED你自己的限流
OTHER其他原因;可在可选的 message 中说明

规则:

  • 按 swapId 幂等。 同一调用的重试必须返回相同答复,且不得创建第二个 allocation。传输错误时 Rocky 重试一次。
  • 金额精确。 Rocky 会从账本读回你的 allocation,把资产、数量、收款方、executor 与 settlementRef 和冻结的 swap 逐项比对。任何差异都按拒绝处理(LP_ACCEPT_FAILED),你的 allocation 由 executor 取消。
  • 期限。 若 Rocky 在 allocateBefore 前看不到你的 allocation 上链,即使你已答复 ALLOCATED,swap 也为 LP_ACCEPT_FAILED。
  • 答复 REJECTED 或超时只会耗费交易者的时间;Rocky 会取消交易者的 allocation。频繁拒绝会降低你在广播中的份额(见接入)。

POST /rfq/trades/{swapId}/result​

swap 到达终态后的尽力通知。返回 200、空体即可。权威记录在 GET /v1/lp/trades/{swapId}。

{
"swapId": "01a0d0f2-…",
"status": "SUCCEEDED",
"cantonUpdateId": "1220…",
"settledAt": "2026-09-23T08:00:07.410Z"
}

对于 LP_ACCEPT_FAILED、SETTLEMENT_FAILED 与 CANCELLED,请求体带 reason;若你的 allocation 存在,还带 lpAllocationCancelled: true|false。为 false 时请在 settleBefore 之后自行用 Allocation_Withdraw 撤回。

POST /rfq/trades/{swapId}/cancel​

当 Rocky 在你这边的 accept-and-allocate 完成之前放弃一笔 swap 时发送(例如你的调用在途时,交易者的 allocation 核验失败)。返回 200。若你已 allocate,请在 settleBefore 之后撤回。

错误与超时汇总​

调用超时Rocky 对非 200 或超时的处理
GET /health2 s移出广播直到恢复健康
POST /rfq/quotes800 ms本次询价视你为无报价
POST …/accept-and-allocate5 sLP_ACCEPT_FAILED;取消交易者 allocation
POST …/result、…/cancel5 s仅记录;不影响 swap

过载时返回 429 并带 Retry-After;Rocky 会在该秒数内暂停向你广播。