WebSocket changelog
Customer-visible WebSocket protocol changes
2026-09-09 — Address-scoped unsubscribe on user-entity channels
unsubscribewithaddresses(usersforuserOrderUpdates) now subtracts those addresses from the subscription the connection holds, leaving the rest streaming. Previously subscribing addresses merged them into one subscription but unsubscribing required the request to name the entire merged set — any smaller request was acknowledged and removed nothing, so those addresses kept delivering and their subscription units were never released. A connection that added and dropped addresses over time therefore climbed toward its tier's total-subscription limit and eventually gotTotal subscription limit reached for tier ... (N/M subscriptions)while holding far fewer addresses than N.Applies to
userFills,userOrderUpdates,userNonFundingLedgerEvents,userTwapStatusUpdates,userLeverageUpdates,userIsolatedMarginUpdatesanduserCompletedTrades.Unsubscribing every address held drops the subscription and sets
unsubscribed: ["<channel>"], as before. Addresses you do not hold are ignored.The subscription's other parameters pick the merge group:
aggregateByTimeforuserFills,dexandaddStakingEventsforuserNonFundingLedgerEvents,dexforuserCompletedTrades. An unsubscribe subtracts only from the group whose parameters match, so twouserFillssubscriptions that differ onaggregateByTimestay independent.No wire-format change: no field was added, removed, or renamed.
2026-09-08 — hip4MarketEvents subscription
New
hip4MarketEventssubscription: every HIP-4 outcome and question lifecycle transition — registration, child association, description change and settlement — pushed as the chain produces it, replacing pollingregisteredOutcomes/settledOutcomeson a timer. Short-duration recurring markets can register and settle between polls; this channel does not miss them.Optional
venue,category,subCategoryandclassfilters, matched case-insensitively and combined with AND. Omit all of them to receive every HIP-4 market event. An event that does not carry a filtered field never matches that filter — validator-registered markets carry novenue, price markets carry nocategory, canonical markets carry noclass.Each event carries
entity(outcomeorquestion),action, andtime/blockNumber/txIndex, so every step is timestamped. Only executed actions are delivered.Question events carry
namedOutcomes(the child outcomes of a question) and, on settlement,settleWinningOutcomeIdandchildSettles.Reconnect replay: subscribe with your last
cursorto replay missed events; the same filters apply to replay as to live.Venue lifecycle (a venue activating or deactivating) is not on this channel — use the REST
outcomeVenuesOverview.Additive: no existing channel or field changes.
2026-09-02 — perpPrices subscription
New
perpPricessubscription: the accepted oracle/mark/external perp prices of the subscribedcoinson every dex including HIP-3 — the streaming counterpart ofperpPriceHistoryByTime, with row-for-row identical fields.A message is sent for every block,
prices: []when the block carried no round for your coins, so the chain height and time can be tracked continuously and the per-connectionseqis gap-free.Coins always merge: a repeat subscribe unions into the connection's single
perpPricessubscription,unsubscribewithcoinssubtracts, withoutcoinsit removes the subscription.Reconnect replay: subscribe with your last
cursorto replay up to 30 seconds of missed rounds (tick messages are not replayed);hasGapflags a cursor older than the cache.Additive: no existing channel or field changes.
2026-08-28 — Subscription ack ordering
A subscription change is now acknowledged after every frame that was already in flight when it committed. Previously an
l4BookUpdatesmerge: truesubscribe could be acked with the merged coin list while the next frame — a block already being fanned out — still covered only the previous set, which read as a coin intermittently going missing right after it was added.Applies to
l4BookUpdates,userFills/builderFills/allFills/liquidationFills/trades,userOrderUpdates/builderOrderUpdates/tpslUpdates,userNonFundingLedgerEvents/allUserNonFundingLedgerEvents/fundingRates, the TWAP status channels, and the leverage / isolated-margin channels.l2Book,l2BookDiff,bbo, the candle, asset-context, mids, and dashboard channels are unchanged for now — their acks may still precede an in-flight frame.The rule to code against: each frame carries the coin set its block was fanned out with, and the ack marks the boundary. Frames before the ack may predate the change; every frame after it reflects it. Apply a coin-set change on the ack, not on the request. The hold is bounded — if fan-out stalls past it the ack is released early, and every block still being fanned out at that moment can deliver a pre-change frame after it (blocks fan out concurrently, so this is not limited to one frame). It resolves once those blocks drain.
Same rule for
unsubscribe: a trailing frame containing dropped coins now arrives before the ack, not after it (this replaces the note in the 2026-08-20 entry below).No wire-format change: no field was added, removed, or renamed.
2026-08-20 — Opt-in merge for l4BookUpdates
Coin-list
l4BookUpdatesstays one stream per subscribe by default.{"type":"l4BookUpdates","coins":["ETH"]}then{"type":"l4BookUpdates","coins":["BTC"]}is still two frames per block.Set
"merge": trueon a coin-list subscribe to union those coins into the connection's existing coin-list slots. The next block is one frame covering the merged set, so adding an instrument does not need an unsubscribe/resubscribe cycle. The subscribe confirmation echoes the merged coin list.mergeis subscribe-only: it is rejected on anunsubscribe, on the all-markets firehose, and on other subscription types.unsubscribewithcoinssubtracts when the connection holds a single coin-list slot (one batched subscribe, or the result ofmerge: true). Several coin-list slots keep exact-match unsubscribe. Coins you do not hold are ignored.unsubscribewithoutcoinsstill removes the all-markets firehose only. A coin-scoped unsubscribe against only the firehose is rejected.The tier coin cap now applies to the effective (post-merge) coin set rather than to each raw request, so repeated
merge: true(and the existingtrades/allFillsunions) cannot walk past it. A single request is still capped at 200 names.When a subscribe carries a
cursor, replay covers the coins named in that request. After a merge the ack still echoes the full merged list.After a coin-scoped
unsubscribeis acknowledged, one already-in-flight block may still deliver a frame containing the dropped coins. Steady state resumes from the next block.Draining the coin-list while the all-markets firehose is still held does not set
unsubscribed: ["l4BookUpdates"]— that field means the channel is gone, and the firehose is still on it.Upcoming:
mergewill become the default for coin-listl4BookUpdatesin a future release. Set it explicitly now —"merge": trueto adopt early,"merge": falseto pin today's one-stream-per-subscribe behaviour through the change. The flag stays accepted afterwards; only clients that send neither will see a behaviour change.
2026-08-07 — Trigger TWAP fields and userTwapStatusUpdates
New
userTwapStatusUpdatessubscription: TWAP status events filtered to the subscribedaddresses(multi-address, merge-on-resubscribe, cursor replay supported) — the user-scoped counterpart ofallTwapStatusUpdates.TWAP status updates (both channels) now carry the trigger-TWAP fields the node added on 2026-07-25:
triggerPx,triggerAbove, andstopPx. The fields are omitted for plain TWAPs.New TWAP
statusvalues from the same node update:waitingForTriggerandstopped.
2026-08-04 — requestId bounds and outcome market activity
Optional
requestIdis capped at 128 characters and must not contain control characters. Violations reject withcode: "invalid_request_id"(oversized values are not echoed).Inbound WebSocket frames are capped (default 256 KiB,
WS_MAX_INBOUND_MESSAGE_BYTES) so control-plane messages cannot use Axum’s 64 MiB default.Active-market metadata refresh now includes HIP-4 outcome markets via
outcomeMeta, so outcome wire coins (#{outcome_id * 10 + side_index}) receive the same active/inactive advisories as perps and spot. IfoutcomeMetafails, the server still commits the perp+spot snapshot (partial_success) and treats outcome activity as unavailable until the next full refresh.
2026-07-22 — Attributable subscription feedback
Subscribe and unsubscribe requests may include an optional string
requestId; confirmations and rejects echo it.subscriptionUpdateretainssubscribedandfailedand addsoperation,subscription, and, for unsubscribe confirmations,unsubscribed.Subscription errors retain
typeandmessageand add request context. Orderbook-family invalid-coin and coin-count rejects also include stablecodeanddetailsfields.l2Book,l2BookDiff,l4BookUpdates, andbboconfirmations may include advisorywarningsfor inactive coins or unavailable activity metadata. These warnings do not fail the subscription.Orderbook invalid-name errors now name every distinct invalid value. Requests containing more than 200 coin entries now report a coin-count error instead of an address-format error.
These changes are additive except for the corrected error text. Clients should continue reading the existing fields they need and ignore unknown fields and message types.
Last updated