Classifies WebSocket subscribe acknowledgements and rejections.
Venues deliver subscribe outcomes in two ways:
- Correlated (deribit JSON-RPC) —
ZenWebsocket.Client.send_message/2returns{:ok, envelope}because the outbound frame carries anid. - Asynchronous (alpaca, bybit, okx, hyperliquid, derive, binance,
lighter) — send
returns
:okand the venue reply arrives as{:websocket_message, frame}or{:websocket_unmatched_response, frame}(derive replies with a JSON-RPC envelope even when the request had no id).
Bourse.WS.subscribe/3 uses this module so both paths resolve to the same
caller contract: :ok on accept, {:error, {:subscription_rejected, frame}}
on reject.
Summary
Functions
Classifies a subscribe outcome frame for exchange_id.
Turns a classification into the public subscribe/3 return value.
Types
@type classification() :: :success | {:success, :data} | :not_ack | {:rejected, map()}
Functions
@spec classify(String.t(), map() | [map()]) :: classification()
Classifies a subscribe outcome frame for exchange_id.
Returns:
:success— venue accepted the subscription{:success, :data}— venue accepted, and the frame is also the first snapshot (re-queue after treating it as the acknowledgement){:rejected, frame}— venue rejected it (frame is the raw envelope):not_ack— not a subscribe outcome (data/heartbeat/other); leave in mailbox
@spec to_result(classification()) :: :ok | {:error, :unexpected_subscription_response | {:subscription_rejected, map()}}
Turns a classification into the public subscribe/3 return value.
A non-ack correlated reply is an unexpected protocol response, not evidence that the venue accepted the subscription.