LP 服务接口
状态:规范(LP 协议 v1,2026-09-23 草案)。 这些接口由你实现、Rocky 调用。v1 的字段名与状态值不再变动。
你的服务是一个 HTTPS API,地址为你在接入时登记的 serviceUrl。Rocky 从集成包中列出的固定出口 IP 调用它。请求体均为 JSON;所有小数为字符串;所有时间为 RFC 3339 UTC、毫秒精度。
Rocky 请求的鉴权
Rocky 发出的每个请求都带 Ed25519 签名,供你证明请求来自 Rocky:
| 头 | 值 |
|---|---|
X-ROCKY-KEY-ID | Rocky 签名密钥标识 |
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 / quoteInstrument | Token Standard 资产标识,与 allocation 中出现的一致。 |
quoteDeadline | Rocky 停止等待的时刻。 |
响应 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。频繁拒绝会降低你在广播中的份额(见接入)。