WebSocket
连接入口:
GET /api/v1/ws· 10 个推送主题 非 JSON-RPC over WS · 订阅/推送协议 生产 Base URL:wss://rpc.auroran.io/api/v1/ws
1. 连接
Upgrade GET /api/v1/ws。连接后发送订阅消息,每块收到增量推送。可随时重发订阅变更主题。
服务端参数:
| 参数 | 值 |
|---|---|
| 最大消息/帧大小 | 65536 字节 |
| 心跳间隔 | 15 秒 |
| 空闲超时 | 30 秒(无消息即断开) |
| 最大并发连接 | 1024 |
| 单次 send 超时 | 5 秒(慢消费者断开) |
2. 订阅协议
2.1 订阅请求
{
"op": "subscribe",
"topics": ["block", "book.BTC-USDT", "trades.ETH-USDT", "account.0x1111...0000"]
}
| 字段 | 类型 | 说明 |
|---|---|---|
op | String | 固定 "subscribe" |
topics | String[] | 主题列表 |
2.2 订阅确认
全部接受:
{ "op": "subscribed", "topics": ["block", "book.BTC-USDT"] }
部分拒绝(未知/非法主题不产生 error 帧,而是返回到 rejected 数组):
{ "op": "subscribed", "topics": ["block"], "rejected": ["unknown topic `foo.bar`"] }
rejected 为空时省略该字段。
2.3 协议错误
无效 JSON / 非 subscribe op:
{ "op": "error", "message": "invalid json: ..." }
3. 推送主题(10 个)
| 主题 | 推送时机 | 初始推送 |
|---|---|---|
block | 每块 | 订阅后首块 |
book.{symbol}[.{depth}] | 盘口变化 | 订阅即推全量快照 |
trades.{symbol} | 有成交 | — |
account.{hex} | 账户被触及,或每 3 秒兜底 | 订阅即推全量快照 |
external_quote.{symbol} | 仅 ExternalPeg | — |
bbo.{symbol} | 最优价变化 | 订阅即推初始快照 |
userFills.{hex} | 用户有成交 | — |
orderUpdates.{hex} | 订单变更 | — |
triggerUpdates.{hex} | 触发单 / OCO 变更 | — |
marks | mark 变化 | 订阅即推全量快照 |
3.1 block
每块推送块元数据。digest/state_root 无 0x 前缀(与 HTTP Hex32 不同)。
{
"topic": "block",
"height": 12346,
"timestamp_ms": 1717200001000,
"digest": "abc123...",
"state_root": "def456...",
"envelope_count": 15,
"event_count": 42
}
3.2 book.{symbol}[.{depth}]
盘口快照。depth 可选,默认 50;0 = 全深度。订阅即推初始快照;之后仅在可见盘口变化时全量推送。
{
"topic": "book.BTC-USDT",
"symbol": "BTC-USDT",
"height": 12346,
"timestamp_ms": 1717200001000,
"state_hash": "0x...",
"bids": [
{ "price": "97200.00", "qty": "1.50000", "cumulative_qty": "1.50000" },
{ "price": "97150.00", "qty": "3.20000", "cumulative_qty": "4.70000" }
],
"asks": [
{ "price": "97250.00", "qty": "2.10000", "cumulative_qty": "2.10000" }
]
}
| 字段 | 类型 | 说明 |
|---|---|---|
topic | String | 主题名 |
symbol | String | 交易对名 |
height | u64 | 快照高度 |
timestamp_ms | u64 | 块时间戳 |
state_hash | Hex32 | 盘口状态哈希 |
bids | Level[] | 买单档位:price(px)/qty(sz)/cumulative_qty(sz) |
asks | Level[] | 卖单档位 |
3.3 trades.{symbol}
成交推送(taker 侧单行,每笔撮合一条)。
{
"topic": "trades.BTC-USDT",
"symbol": "BTC-USDT",
"height": 12346,
"timestamp_ms": 1717200001000,
"trades": [{
"block_height": 12346,
"event_seq": 3,
"timestamp_ms": 1717200001000,
"market_id": 1,
"price": "97234.50",
"qty": "0.50000",
"notional": "48617.250000",
"side": "Bid"
}]
}
| 字段 | 类型 | 说明 |
|---|---|---|
topic | String | 主题名 |
symbol | String | 交易对名 |
height | u64 | 所在块高 |
timestamp_ms | u64 | 块时间戳 |
trades[].block_height | u64 | 成交块高 |
trades[].event_seq | u64 | 块内事件序号 |
trades[].timestamp_ms | u64 | 成交时刻(块时间,毫秒;本帧内同块同值,与 HTTP getRecentTrades 逐笔对齐) |
trades[].market_id | u32 | 市场 ID |
trades[].price | String | 成交价(px 精度) |
trades[].qty | String | 成交量(sz 精度) |
trades[].notional | String | 名义价值(SCALE_6) |
trades[].side | Side | taker 进攻方向("Bid"/"Ask");前端据此红绿染色 |
3.4 account.{hex}
账户余额 / 持仓 / 衍生指标推送。两条路径格式完全一致,前端无需区分来源:
- 事件驱动:账户在本块被 touch(余额 / 持仓 / 挂单 IM 等变化)时立即推送。
- 定时兜底:连接存续且已订阅时,每 3 秒对全部已订阅地址全量推送一次(mark 变动导致 uPnL / 强平价变化但账户未 touch 时仍能更新)。
订阅 / 重订阅时立即推一份当前快照(与上述格式相同)。
{
"topic": "account.0x1111222233334444555566667777888899990000",
"address": "0x1111222233334444555566667777888899990000",
"height": 12346,
"timestamp_ms": 1717200001000,
"balance": "100000.000000",
"nonce": 42,
"role_mask": 1,
"account_value": "101117.250000",
"total_margin_used": "4861.725000",
"total_notional": "48617.250000",
"withdrawable": "96255.525000",
"positions": {
"1": {
"symbol": "BTC-USDT",
"mark_price": "97225.00",
"size": "0.50000",
"entry_vwap": "95000.00",
"margin_mode": "Cross",
"leverage": 10,
"isolated_margin": "0",
"margin_used": "4861.725000",
"unrealized_pnl": "1117.250000",
"notional": "48617.250000",
"liquidation_price": "87450.00",
"roe": "0.2298"
}
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
topic | String | 主题名 |
address | Address20 | 账户地址 |
height | u64 | 所在块高 |
timestamp_ms | u64 | 块时间戳 |
balance | String | 余额(SCALE_6) |
nonce | u64 | 当前 nonce |
role_mask | u64 | 角色位掩码 |
account_value | String | 总价值 = balance + Σ(uPnL)(SCALE_6) |
total_margin_used | String | 已用保证金(SCALE_6) |
total_notional | String | 总名义价值(SCALE_6) |
withdrawable | String | 可提现 = max(0, account_value − total_margin_used)(SCALE_6) |
positions | Map<MarketId, PositionResponse> | 持仓映射(字段同 getAccount 的 PositionResponse)。仅含已开仓(size != 0)的市场,与 HTTP getAccount 同口径 |
聚合字段
account_value/total_margin_used/total_notional/withdrawable与 HTTPgetAccount同源(服务端复用同一account_margin_summary原语),前端可直接展示「可用余额 / 账户概况」,无需本地复刻链上公式。agents/dms_deadline_ms仍仅在 HTTPgetAccount提供(极少变动,不进逐块/3 秒推送)。
3.5 external_quote.{symbol}
ExternalPeg 市场 oracle 报价逐块推送。唯一携带 last_price/volume 的通道(HTTP getMarket.latest_quote 中这两个字段恒为 null)。
{
"topic": "external_quote.BTC-USDT",
"symbol": "BTC-USDT",
"height": 12346,
"timestamp_ms": 1717200001000,
"quote": {
"bid_price": "97100.00",
"ask_price": "97300.00",
"mark_price": "97200.00",
"source_ts_ms": 1717200000000,
"sequence_id": 5,
"quoter": "0x...",
"last_price": "97234.50",
"volume": "1.50000"
},
"market_stats": {
"long_size": "10.50000",
"short_size": "8.20000",
"net_size": "2.30000",
"oracle_counter_pnl": "150.000000",
"open_interest": "10.50000",
"open_interest_notional": "1021862.500000",
"fills_in_block": 5,
"block_height": 12346
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
topic | String | 主题名 |
symbol | String | 交易对名 |
height | u64 | 所在块高 |
timestamp_ms | u64 | 块时间戳 |
quote | OracleQuoteResponse | 报价详情(bid_price/ask_price/mark_price 为 px 精度;last_price 为 px 精度;volume 为 sz 精度) |
market_stats | MarketStatsResponse? | 市场统计快照(字段见 read-methods §6.2 的 MarketStatsResponse) |
3.6 bbo.{symbol}
最优买卖价轻量推送。订阅即推初始快照;之后仅在最优价变化时推送。
{
"topic": "bbo.BTC-USDT",
"symbol": "BTC-USDT",
"height": 12346,
"timestamp_ms": 1717200001000,
"best_bid": "97200.00",
"best_ask": "97250.00"
}
| 字段 | 类型 | 说明 |
|---|---|---|
topic | String | 主题名 |
symbol | String | 交易对名 |
height | u64 | 所在块高 |
timestamp_ms | u64 | 块时间戳 |
best_bid | String? | 买一价(px 精度);空盘时省略或 null |
best_ask | String? | 卖一价(px 精度);空盘时省略或 null |
3.7 userFills.{hex}
用户成交实时推送。
{
"topic": "userFills.0x1111222233334444555566667777888899990000",
"address": "0x1111222233334444555566667777888899990000",
"height": 12346,
"timestamp_ms": 1717200001000,
"fills": [{
"block_height": 12346,
"event_seq": 3,
"market_id": 1,
"price": "97234.50",
"qty": "0.50000",
"notional": "48617.250000",
"fee": "24.308625",
"is_taker": true,
"aggressor_side": "Bid"
}]
}
| 字段 | 类型 | 说明 |
|---|---|---|
fills[].block_height | u64 | 成交块高 |
fills[].event_seq | u64 | 块内事件序号 |
fills[].market_id | u32 | 市场 ID |
fills[].price | String | 成交价(px 精度) |
fills[].qty | String | 成交量(sz 精度) |
fills[].notional | String | 名义价值(SCALE_6) |
fills[].fee | String | 手续费(SCALE_6;负值=maker rebate) |
fills[].is_taker | bool | 该用户是否为吃单方 |
fills[].aggressor_side | Side | 吃单方向 |
3.8 orderUpdates.{hex}
订单状态变更实时推送。accepted/resting 帧携带订单明细字段(symbol/side/price/
qty/tif/reduce_only/client_order_id),前端可仅凭本通道增量自洽维护「当前委托」
列表——无需回查 getAccountOrders:
resting(含 amend 后重挂)→ 按order_idupsert 一行(明细字段齐全 +remaining)。done/expired→ 按order_id摘除该行(不携带明细字段)。accepted→ 下单意图先行确认(带side/price/qty/tif,不带reduce_only/client_order_id,这两个随同块resting补齐);完全成交 / IOC 不挂簿的单不会再有resting,前端无需将其计入挂单列表。
{
"topic": "orderUpdates.0x1111222233334444555566667777888899990000",
"address": "0x1111222233334444555566667777888899990000",
"height": 12346,
"timestamp_ms": 1717200001000,
"updates": [{
"block_height": 12346,
"event_seq": 3,
"order_id": 1001,
"market_id": 1,
"symbol": "BTC-USDT",
"kind": "resting",
"remaining": "1.00000",
"side": "Bid",
"price": "97100.00",
"qty": "1.00000",
"tif": "Gtc",
"reduce_only": false,
"client_order_id": "my-cloid-1"
}]
}
| 字段 | 类型 | 说明 |
|---|---|---|
updates[].block_height | u64 | 事件块高 |
updates[].event_seq | u64 | 块内事件序号 |
updates[].order_id | u64 | 订单 ID |
updates[].market_id | u32 | 市场 ID |
updates[].symbol | String | 交易对名 |
updates[].kind | OrderUpdateKind | "accepted" · "resting" · "done" · "expired" |
updates[].remaining | String | 剩余量(sz 精度) |
updates[].reason | String? | 仅 done/expired 时出现,DoneReason 标签(如 "Filled"、"Cancelled") |
updates[].side | Side? | 仅 accepted/resting:"Bid" · "Ask" |
updates[].price | String? | 仅 accepted/resting:限价(px 精度) |
updates[].qty | String? | 仅 accepted/resting:原始下单数量(sz 精度) |
updates[].tif | TimeInForce? | 仅 accepted/resting:"Gtc" · "Ioc" · "Fok" · "PostOnly" |
updates[].reduce_only | bool? | 仅 resting:是否仅减仓 |
updates[].client_order_id | String? | 仅 resting 且下单时携带:客户端订单 ID |
3.9 triggerUpdates.{hex}
触发单 / OCO(条件委托)生命周期实时推送。placed 帧携带完整明细,前端可仅凭本通道
增量自洽维护「条件委托」列表——无需轮询 getTriggerOrders / getOcoPairs:
placed→ 按trigger_idupsert 一行(明细字段齐全)。activated/cancelled/expired/fire_failed→ 按trigger_id摘除该行;activated表示已促升下单,结果挂单/成交分别走orderUpdates/userFills。oco_placed/oco_resolved→ 仅带pair_id(+ placed 的client_pair_id);OCO 两腿的 详情由各腿自身的triggerUpdates(Stop 腿)/orderUpdates(限价腿)描述。
{
"topic": "triggerUpdates.0x1111222233334444555566667777888899990000",
"address": "0x1111222233334444555566667777888899990000",
"height": 12346,
"timestamp_ms": 1717200001000,
"updates": [{
"block_height": 12346,
"event_seq": 3,
"kind": "placed",
"market_id": 1,
"symbol": "BTC-USDT",
"trigger_id": 7001,
"side": "Ask",
"order_type": "limit",
"qty": "0.50000",
"trigger_price": "95000.00",
"trigger_direction": "Below",
"limit_price": "94900.00",
"tif": "Gtc",
"reduce_only": true,
"client_order_id": "sl-1",
"expires_at_ms": null
}]
}
| 字段 | 类型 | 说明 |
|---|---|---|
updates[].block_height | u64 | 事件块高 |
updates[].event_seq | u64 | 块内事件序号 |
updates[].kind | TriggerUpdateKind | "placed" · "activated" · "cancelled" · "expired" · "fire_failed" · "oco_placed" · "oco_resolved" |
updates[].market_id | u32 | 市场 ID |
updates[].symbol | String | 交易对名 |
updates[].trigger_id | u64? | 触发单 ID(OCO place/resolve 缺省) |
updates[].pair_id | u64? | OCO 对 ID(仅 oco_placed/oco_resolved) |
updates[].reason | String? | 终态原因(cancelled 的 TriggerCancelReason / oco_resolved 的 OcoResolveReason / fire_failed 的 RejectReason) |
updates[].side | Side? | 仅 placed:"Bid" · "Ask" |
updates[].order_type | String? | 仅 placed:"market"(IOC 吃穿)· "limit" |
updates[].qty | String? | 仅 placed:下单数量(sz 精度) |
updates[].trigger_price | String? | 仅 placed:触发线(px 精度) |
updates[].trigger_direction | TriggerDirection? | 仅 placed:"Above" · "Below" |
updates[].limit_price | String? | 仅 placed 且 limit:限价(px 精度) |
updates[].tif | TimeInForce? | 仅 placed |
updates[].reduce_only | bool? | 仅 placed |
updates[].client_order_id | String? | 仅 placed 且下单时携带 |
updates[].expires_at_ms | u64? | 仅 placed:GTD 过期时刻(毫秒);null = 永不过期 |
updates[].client_pair_id | u64? | 仅 oco_placed:客户端 OCO pair ID |
3.10 marks
全市场标记价推送。订阅即推全量快照;之后仅推 mark 变化的市场。
{
"topic": "marks",
"height": 12346,
"timestamp_ms": 1717200001000,
"marks": {
"BTC-USDT": "97225.00",
"ETH-USDT": "3450.00"
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
topic | String | 固定 "marks" |
height | u64 | 所在块高 |
timestamp_ms | u64 | 块时间戳 |
marks | Map<String, String> | symbol → mark_price(各自 px 精度)。注意是 mark(清算/uPnL 公允价),不是盘口中点 mid |
4. 主题解析规则
| 主题模式 | 解析规则 |
|---|---|
block | 匹配 "block" |
book.{symbol}[.{depth}] | 匹配 "book." 前缀,可选 .depth 后缀(默认 50) |
trades.{symbol} | 匹配 "trades." 前缀 |
account.{hex} | 匹配 "account." 前缀,地址为 20 字节 hex(0x 前缀可选) |
external_quote.{symbol} | 匹配 "external_quote." 前缀 |
bbo.{symbol} | 匹配 "bbo." 前缀 |
userFills.{hex} | 匹配 "userFills." 前缀,地址为 20 字节 hex |
orderUpdates.{hex} | 匹配 "orderUpdates." 前缀,地址为 20 字节 hex |
triggerUpdates.{hex} | 匹配 "triggerUpdates." 前缀,地址为 20 字节 hex |
marks | 匹配 "marks" |