nautilus_dydx/websocket/enums.rs
1// -------------------------------------------------------------------------------------------------
2// Copyright (C) 2015-2025 Nautech Systems Pty Ltd. All rights reserved.
3// https://nautechsystems.io
4//
5// Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6// You may not use this file except in compliance with the License.
7// You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Enums for dYdX WebSocket operations, channels, and message types.
17
18use std::collections::HashMap;
19
20use nautilus_model::{
21 data::{Data, OrderBookDeltas},
22 events::AccountState,
23 reports::{FillReport, OrderStatusReport, PositionStatusReport},
24};
25use serde::{Deserialize, Serialize};
26use serde_json::Value;
27use strum::{AsRefStr, Display, EnumString, FromRepr};
28
29use super::{
30 error::DydxWebSocketError,
31 messages::{
32 DydxOraclePriceMarket, DydxWsChannelBatchDataMsg, DydxWsChannelDataMsg, DydxWsConnectedMsg,
33 DydxWsSubaccountsChannelData, DydxWsSubaccountsSubscribed, DydxWsSubscriptionMsg,
34 },
35};
36
37/// WebSocket operation types for dYdX.
38#[derive(
39 Clone,
40 Copy,
41 Debug,
42 PartialEq,
43 Eq,
44 Hash,
45 Display,
46 AsRefStr,
47 EnumString,
48 FromRepr,
49 Serialize,
50 Deserialize,
51)]
52#[serde(rename_all = "snake_case")]
53#[strum(serialize_all = "snake_case")]
54pub enum DydxWsOperation {
55 /// Subscribe to a channel.
56 Subscribe,
57 /// Unsubscribe from a channel.
58 Unsubscribe,
59 /// Ping keepalive message.
60 Ping,
61 /// Pong response to ping.
62 Pong,
63}
64
65/// dYdX WebSocket channel identifiers.
66///
67/// # References
68///
69/// <https://docs.dydx.trade/developers/indexer/websockets>
70#[derive(
71 Clone,
72 Copy,
73 Debug,
74 PartialEq,
75 Eq,
76 Hash,
77 Display,
78 AsRefStr,
79 EnumString,
80 FromRepr,
81 Serialize,
82 Deserialize,
83)]
84#[serde(rename_all = "snake_case")]
85#[strum(serialize_all = "snake_case")]
86pub enum DydxWsChannel {
87 /// Market data for all markets.
88 #[serde(rename = "v4_markets")]
89 #[strum(serialize = "v4_markets")]
90 Markets,
91 /// Trade stream for specific market.
92 #[serde(rename = "v4_trades")]
93 #[strum(serialize = "v4_trades")]
94 Trades,
95 /// Order book snapshots and updates.
96 #[serde(rename = "v4_orderbook")]
97 #[strum(serialize = "v4_orderbook")]
98 Orderbook,
99 /// Candlestick/kline data.
100 #[serde(rename = "v4_candles")]
101 #[strum(serialize = "v4_candles")]
102 Candles,
103 /// Subaccount updates (orders, fills, positions).
104 #[serde(rename = "v4_subaccounts")]
105 #[strum(serialize = "v4_subaccounts")]
106 Subaccounts,
107 /// Parent subaccount updates (for isolated positions).
108 #[serde(rename = "v4_parent_subaccounts")]
109 #[strum(serialize = "v4_parent_subaccounts")]
110 ParentSubaccounts,
111 /// Block height updates from chain.
112 #[serde(rename = "v4_block_height")]
113 #[strum(serialize = "v4_block_height")]
114 BlockHeight,
115 /// Unknown/unrecognized channel type.
116 #[serde(other)]
117 #[strum(to_string = "unknown")]
118 Unknown,
119}
120
121impl DydxWsChannel {
122 /// Returns `true` if this is a private channel requiring authentication.
123 #[must_use]
124 pub const fn is_private(&self) -> bool {
125 matches!(self, Self::Subaccounts | Self::ParentSubaccounts)
126 }
127
128 /// Returns `true` if this is a public channel.
129 #[must_use]
130 pub const fn is_public(&self) -> bool {
131 !self.is_private()
132 }
133
134 /// Returns `true` if this is an unknown/unrecognized channel type.
135 #[must_use]
136 pub const fn is_unknown(&self) -> bool {
137 matches!(self, Self::Unknown)
138 }
139}
140
141/// WebSocket message types for dYdX.
142#[derive(
143 Clone,
144 Copy,
145 Debug,
146 PartialEq,
147 Eq,
148 Hash,
149 Display,
150 AsRefStr,
151 EnumString,
152 FromRepr,
153 Serialize,
154 Deserialize,
155)]
156#[serde(rename_all = "snake_case")]
157#[strum(serialize_all = "snake_case")]
158pub enum DydxWsMessageType {
159 /// Connection established.
160 Connected,
161 /// Subscription confirmed.
162 Subscribed,
163 /// Unsubscription confirmed.
164 Unsubscribed,
165 /// Channel data update.
166 ChannelData,
167 /// Batch channel data update.
168 ChannelBatchData,
169 /// Error message.
170 Error,
171 /// Unknown/unrecognized message type.
172 #[serde(other)]
173 #[strum(to_string = "unknown")]
174 Unknown,
175}
176
177/// High level message emitted by the dYdX WebSocket client.
178#[derive(Debug, Clone)]
179pub enum DydxWsMessage {
180 /// Subscription acknowledgement.
181 Subscribed(DydxWsSubscriptionMsg),
182 /// Unsubscription acknowledgement.
183 Unsubscribed(DydxWsSubscriptionMsg),
184 /// Subaccounts subscription with initial account state.
185 SubaccountsSubscribed(DydxWsSubaccountsSubscribed),
186 /// Connected acknowledgement with connection_id.
187 Connected(DydxWsConnectedMsg),
188 /// Channel data update.
189 ChannelData(DydxWsChannelDataMsg),
190 /// Batch of channel data updates.
191 ChannelBatchData(DydxWsChannelBatchDataMsg),
192 /// Error received from the venue or client lifecycle.
193 Error(DydxWebSocketError),
194 /// Raw message payload that does not yet have a typed representation.
195 Raw(Value),
196 /// Notification that the underlying connection reconnected.
197 Reconnected,
198 /// Explicit pong event (text-based heartbeat acknowledgement).
199 Pong,
200}
201
202/// Nautilus domain message emitted after parsing dYdX WebSocket events.
203///
204/// This enum contains fully-parsed Nautilus domain objects ready for consumption
205/// by the Python layer without additional processing.
206#[derive(Debug, Clone)]
207pub enum NautilusWsMessage {
208 /// Market data (trades, quotes, bars).
209 Data(Vec<Data>),
210 /// Order book deltas.
211 Deltas(Box<OrderBookDeltas>),
212 /// Order status reports from subaccount stream.
213 Order(Box<OrderStatusReport>),
214 /// Fill reports from subaccount stream.
215 Fill(Box<FillReport>),
216 /// Position status reports from subaccount stream.
217 Position(Box<PositionStatusReport>),
218 /// Account state updates from subaccount stream.
219 AccountState(Box<AccountState>),
220 /// Raw subaccount subscription with full state (for execution client parsing).
221 SubaccountSubscribed(Box<DydxWsSubaccountsSubscribed>),
222 /// Raw subaccounts channel data (orders/fills) for execution client parsing.
223 SubaccountsChannelData(Box<DydxWsSubaccountsChannelData>),
224 /// Oracle price updates from markets channel (for execution client).
225 OraclePrices(HashMap<String, DydxOraclePriceMarket>),
226 /// Error message.
227 Error(DydxWebSocketError),
228 /// Reconnection notification.
229 Reconnected,
230}