Skip to main content
WSS
This user-scoped stream uses (feedEpoch, globalUserSeq). Without seq, it sends a complete finalized order snapshot, replays retained updates after that snapshot, and then joins live delivery. It also sends a complete snapshot every five seconds by default. Incremental updates use the requested coalescing duration, which defaults to 300 milliseconds.

Subscribe

Empty snapshots and nullable sequences

An authoritative snapshot with orders: [] means the user has no open orders in the selected view. Apply it by clearing the local open-order list, even if globalSeq or globalUserSeq is null. Order count and cursor availability are independent:
  • An empty snapshot can have non-null sequences after orders are cancelled or fully filled. Keep a valid globalUserSeq; do not discard it because the list is empty.
  • Null sequences indicate an unavailable or zero baseline cursor, not proof that the user has never traded. They can occur for an untouched user, before a snapshot baseline exists, or after checkpoint restoration into a new feed epoch, including for users with restored open orders.
  • The binary format encodes missing sequences as zero; the SDK maps zero to null. globalSeq and globalUserSeq need not both be null.
Use (feedEpoch, globalUserSeq) for user-stream replay, never globalSeq. If globalUserSeq is null, do not substitute globalSeq or infer a cursor from the order list. Continue the current subscription’s bootstrap/live flow; on a fresh connection, omit seq to request a new authoritative snapshot. Follow the documented predecessor checks once sequenced updates arrive.

Decoded event

The shape below is the inner message returned by decodeExchangeWsEnvelope or decodeExchangeWsMessage. Every binary socket message also carries an outer id: bigint, matching your subscription ID. Use it to route snapshots, replay, and live updates. See binary subscription envelopes.
The binary decoder maps event codes 1 through 5 to created, trade, cancelled, rab-reduced, and operation-sentinel. Every delta event carries its exact transaction source tuple:
Replace all local open-order state when snapshot=true. For a delta, validate previousGlobalUserSeq, then apply events in array order: For an explicit replay cut R, the first publication is a valid sparse bridge when globalUserSeq > R and previousGlobalUserSeq is null or at most R. After accepting it, require every subsequent previousGlobalUserSeq to equal the last accepted globalUserSeq exactly.
  • created carries the complete new open order.
  • trade carries the complete user trade payload. For activeFifo, update the resting maker’s order using liquidity.orderId and liquidity.slotIndex, setting its remaining size to liquidity.remainingBaseAfter; remove it when zero. Only mutate the local order when users[1] matches the subscribed user. A taker’s trade notification does not identify a taker resting order. Passive fills have no active order identity and must not mutate the open-order list.
  • cancelled removes the order.
  • rab-reduced sets the remaining size to updatedSize; remove it when that value is zero.
  • operation-sentinel reports an operation outcome without adding or removing an open order.
Real order events reach the affected maker. Tagged outcomes also reach the action account, with overlapping recipients delivered once. For created and cancelled, only mutate the subscribed user’s open orders when makerId matches that user. Tagged passive fills reach the taker, and sentinels reach the action account. Snapshots still contain only real open orders. Key each live slot by (marketAddress, slotIdx). Before updating or removing a slot, verify that its current orderId matches the event. This prevents a late event from mutating a newer order that reused the physical slot. Use the frame’s globalUserSeq for stream continuity; the event’s source tuple identifies the causal onchain or generated record.

Action and operation outcomes

action identifies the action account, executor address, and optional client order ID. It is present on created, trade, cancelled, and operation-sentinel, but not rab-reduced. The action account is not necessarily the affected maker. operation is nullable on created, trade, and cancelled events. When present, it supplies operationIndex and an outcome code; trades additionally include replacementSlot. This metadata describes the operation outcome, not another fill or open order. Sentinels always have operation metadata, restricted to outcomes 3, 5, 6, and 9. Use them to resolve pending actions, not to create synthetic orders. Wire version remains 1; use the matching updated SDK decoder for these event layouts. Snapshot order rows are unchanged. Prices remain in market price precision and sizes in market size precision.

Canonical event timestamp

Each decoded trade row or order delta event includes blockTimestamp: bigint in Unix seconds. It is the source block’s canonical header timestamp and is identical in live delivery and retained replay. It is not the publication time. Snapshot orders expose createdAt: bigint in Unix seconds: their original creation-block time, retained through updates and checkpoint restore. Each snapshot row is now 104 bytes, with createdAt appended at offset 96. On created deltas, initialize createdAt from blockTimestamp; later events do not change it. See the event timestamp changelog.
userOrders@f subscription
type:object