1use std::{any::Any, sync::Arc};
19
20use nautilus_core::{UUID4, UnixNanos};
21use nautilus_model::{
22 data::BarType,
23 identifiers::{ClientId, Venue},
24};
25
26pub mod request;
27pub mod response;
28pub mod subscribe;
29pub mod unsubscribe;
30
31pub use request::{
33 RequestBars, RequestBookDepth, RequestBookSnapshot, RequestCustomData, RequestInstrument,
34 RequestInstruments, RequestQuotes, RequestTrades,
35};
36pub use response::{
37 BarsResponse, BookResponse, CustomDataResponse, InstrumentResponse, InstrumentsResponse,
38 QuotesResponse, TradesResponse,
39};
40pub use subscribe::{
41 SubscribeBars, SubscribeBookDeltas, SubscribeBookDepth10, SubscribeBookSnapshots,
42 SubscribeCustomData, SubscribeFundingRates, SubscribeIndexPrices, SubscribeInstrument,
43 SubscribeInstrumentClose, SubscribeInstrumentStatus, SubscribeInstruments, SubscribeMarkPrices,
44 SubscribeQuotes, SubscribeTrades,
45};
46pub use unsubscribe::{
47 UnsubscribeBars, UnsubscribeBookDeltas, UnsubscribeBookDepth10, UnsubscribeBookSnapshots,
48 UnsubscribeCustomData, UnsubscribeFundingRates, UnsubscribeIndexPrices, UnsubscribeInstrument,
49 UnsubscribeInstrumentClose, UnsubscribeInstrumentStatus, UnsubscribeInstruments,
50 UnsubscribeMarkPrices, UnsubscribeQuotes, UnsubscribeTrades,
51};
52
53#[cfg(feature = "defi")]
54use crate::messages::defi::{DefiRequestCommand, DefiSubscribeCommand, DefiUnsubscribeCommand};
55
56#[non_exhaustive]
57#[derive(Clone, Debug, PartialEq)]
58pub enum DataCommand {
59 Request(RequestCommand),
60 Subscribe(SubscribeCommand),
61 Unsubscribe(UnsubscribeCommand),
62 #[cfg(feature = "defi")]
63 DefiRequest(DefiRequestCommand),
64 #[cfg(feature = "defi")]
65 DefiSubscribe(DefiSubscribeCommand),
66 #[cfg(feature = "defi")]
67 DefiUnsubscribe(DefiUnsubscribeCommand),
68}
69
70impl DataCommand {
71 pub fn as_any(&self) -> &dyn Any {
73 self
74 }
75}
76
77#[derive(Clone, Debug)]
78pub enum SubscribeCommand {
79 Data(SubscribeCustomData),
80 Instrument(SubscribeInstrument),
81 Instruments(SubscribeInstruments),
82 BookDeltas(SubscribeBookDeltas),
83 BookDepth10(SubscribeBookDepth10),
84 BookSnapshots(SubscribeBookSnapshots),
85 Quotes(SubscribeQuotes),
86 Trades(SubscribeTrades),
87 Bars(SubscribeBars),
88 MarkPrices(SubscribeMarkPrices),
89 IndexPrices(SubscribeIndexPrices),
90 FundingRates(SubscribeFundingRates),
91 InstrumentStatus(SubscribeInstrumentStatus),
92 InstrumentClose(SubscribeInstrumentClose),
93}
94
95impl PartialEq for SubscribeCommand {
96 fn eq(&self, other: &Self) -> bool {
97 self.command_id() == other.command_id()
98 }
99}
100
101impl SubscribeCommand {
102 pub fn as_any(&self) -> &dyn Any {
104 self
105 }
106
107 pub fn command_id(&self) -> UUID4 {
108 match self {
109 Self::Data(cmd) => cmd.command_id,
110 Self::Instrument(cmd) => cmd.command_id,
111 Self::Instruments(cmd) => cmd.command_id,
112 Self::BookDeltas(cmd) => cmd.command_id,
113 Self::BookDepth10(cmd) => cmd.command_id,
114 Self::BookSnapshots(cmd) => cmd.command_id,
115 Self::Quotes(cmd) => cmd.command_id,
116 Self::Trades(cmd) => cmd.command_id,
117 Self::Bars(cmd) => cmd.command_id,
118 Self::MarkPrices(cmd) => cmd.command_id,
119 Self::IndexPrices(cmd) => cmd.command_id,
120 Self::FundingRates(cmd) => cmd.command_id,
121 Self::InstrumentStatus(cmd) => cmd.command_id,
122 Self::InstrumentClose(cmd) => cmd.command_id,
123 }
124 }
125
126 pub fn client_id(&self) -> Option<&ClientId> {
127 match self {
128 Self::Data(cmd) => cmd.client_id.as_ref(),
129 Self::Instrument(cmd) => cmd.client_id.as_ref(),
130 Self::Instruments(cmd) => cmd.client_id.as_ref(),
131 Self::BookDeltas(cmd) => cmd.client_id.as_ref(),
132 Self::BookDepth10(cmd) => cmd.client_id.as_ref(),
133 Self::BookSnapshots(cmd) => cmd.client_id.as_ref(),
134 Self::Quotes(cmd) => cmd.client_id.as_ref(),
135 Self::Trades(cmd) => cmd.client_id.as_ref(),
136 Self::MarkPrices(cmd) => cmd.client_id.as_ref(),
137 Self::IndexPrices(cmd) => cmd.client_id.as_ref(),
138 Self::FundingRates(cmd) => cmd.client_id.as_ref(),
139 Self::Bars(cmd) => cmd.client_id.as_ref(),
140 Self::InstrumentStatus(cmd) => cmd.client_id.as_ref(),
141 Self::InstrumentClose(cmd) => cmd.client_id.as_ref(),
142 }
143 }
144
145 pub fn venue(&self) -> Option<&Venue> {
146 match self {
147 Self::Data(cmd) => cmd.venue.as_ref(),
148 Self::Instrument(cmd) => cmd.venue.as_ref(),
149 Self::Instruments(cmd) => Some(&cmd.venue),
150 Self::BookDeltas(cmd) => cmd.venue.as_ref(),
151 Self::BookDepth10(cmd) => cmd.venue.as_ref(),
152 Self::BookSnapshots(cmd) => cmd.venue.as_ref(),
153 Self::Quotes(cmd) => cmd.venue.as_ref(),
154 Self::Trades(cmd) => cmd.venue.as_ref(),
155 Self::MarkPrices(cmd) => cmd.venue.as_ref(),
156 Self::IndexPrices(cmd) => cmd.venue.as_ref(),
157 Self::FundingRates(cmd) => cmd.venue.as_ref(),
158 Self::Bars(cmd) => cmd.venue.as_ref(),
159 Self::InstrumentStatus(cmd) => cmd.venue.as_ref(),
160 Self::InstrumentClose(cmd) => cmd.venue.as_ref(),
161 }
162 }
163
164 pub fn ts_init(&self) -> UnixNanos {
165 match self {
166 Self::Data(cmd) => cmd.ts_init,
167 Self::Instrument(cmd) => cmd.ts_init,
168 Self::Instruments(cmd) => cmd.ts_init,
169 Self::BookDeltas(cmd) => cmd.ts_init,
170 Self::BookDepth10(cmd) => cmd.ts_init,
171 Self::BookSnapshots(cmd) => cmd.ts_init,
172 Self::Quotes(cmd) => cmd.ts_init,
173 Self::Trades(cmd) => cmd.ts_init,
174 Self::MarkPrices(cmd) => cmd.ts_init,
175 Self::IndexPrices(cmd) => cmd.ts_init,
176 Self::FundingRates(cmd) => cmd.ts_init,
177 Self::Bars(cmd) => cmd.ts_init,
178 Self::InstrumentStatus(cmd) => cmd.ts_init,
179 Self::InstrumentClose(cmd) => cmd.ts_init,
180 }
181 }
182}
183
184#[derive(Clone, Debug)]
185pub enum UnsubscribeCommand {
186 Data(UnsubscribeCustomData),
187 Instrument(UnsubscribeInstrument),
188 Instruments(UnsubscribeInstruments),
189 BookDeltas(UnsubscribeBookDeltas),
190 BookDepth10(UnsubscribeBookDepth10),
191 BookSnapshots(UnsubscribeBookSnapshots),
192 Quotes(UnsubscribeQuotes),
193 Trades(UnsubscribeTrades),
194 Bars(UnsubscribeBars),
195 MarkPrices(UnsubscribeMarkPrices),
196 IndexPrices(UnsubscribeIndexPrices),
197 FundingRates(UnsubscribeFundingRates),
198 InstrumentStatus(UnsubscribeInstrumentStatus),
199 InstrumentClose(UnsubscribeInstrumentClose),
200}
201
202impl PartialEq for UnsubscribeCommand {
203 fn eq(&self, other: &Self) -> bool {
204 self.command_id() == other.command_id()
205 }
206}
207
208impl UnsubscribeCommand {
209 pub fn as_any(&self) -> &dyn Any {
211 self
212 }
213
214 pub fn command_id(&self) -> UUID4 {
215 match self {
216 Self::Data(cmd) => cmd.command_id,
217 Self::Instrument(cmd) => cmd.command_id,
218 Self::Instruments(cmd) => cmd.command_id,
219 Self::BookDeltas(cmd) => cmd.command_id,
220 Self::BookDepth10(cmd) => cmd.command_id,
221 Self::BookSnapshots(cmd) => cmd.command_id,
222 Self::Quotes(cmd) => cmd.command_id,
223 Self::Trades(cmd) => cmd.command_id,
224 Self::Bars(cmd) => cmd.command_id,
225 Self::MarkPrices(cmd) => cmd.command_id,
226 Self::IndexPrices(cmd) => cmd.command_id,
227 Self::FundingRates(cmd) => cmd.command_id,
228 Self::InstrumentStatus(cmd) => cmd.command_id,
229 Self::InstrumentClose(cmd) => cmd.command_id,
230 }
231 }
232
233 pub fn client_id(&self) -> Option<&ClientId> {
234 match self {
235 Self::Data(cmd) => cmd.client_id.as_ref(),
236 Self::Instrument(cmd) => cmd.client_id.as_ref(),
237 Self::Instruments(cmd) => cmd.client_id.as_ref(),
238 Self::BookDeltas(cmd) => cmd.client_id.as_ref(),
239 Self::BookDepth10(cmd) => cmd.client_id.as_ref(),
240 Self::BookSnapshots(cmd) => cmd.client_id.as_ref(),
241 Self::Quotes(cmd) => cmd.client_id.as_ref(),
242 Self::Trades(cmd) => cmd.client_id.as_ref(),
243 Self::Bars(cmd) => cmd.client_id.as_ref(),
244 Self::MarkPrices(cmd) => cmd.client_id.as_ref(),
245 Self::IndexPrices(cmd) => cmd.client_id.as_ref(),
246 Self::FundingRates(cmd) => cmd.client_id.as_ref(),
247 Self::InstrumentStatus(cmd) => cmd.client_id.as_ref(),
248 Self::InstrumentClose(cmd) => cmd.client_id.as_ref(),
249 }
250 }
251
252 pub fn venue(&self) -> Option<&Venue> {
253 match self {
254 Self::Data(cmd) => cmd.venue.as_ref(),
255 Self::Instrument(cmd) => cmd.venue.as_ref(),
256 Self::Instruments(cmd) => Some(&cmd.venue),
257 Self::BookDeltas(cmd) => cmd.venue.as_ref(),
258 Self::BookDepth10(cmd) => cmd.venue.as_ref(),
259 Self::BookSnapshots(cmd) => cmd.venue.as_ref(),
260 Self::Quotes(cmd) => cmd.venue.as_ref(),
261 Self::Trades(cmd) => cmd.venue.as_ref(),
262 Self::Bars(cmd) => cmd.venue.as_ref(),
263 Self::MarkPrices(cmd) => cmd.venue.as_ref(),
264 Self::IndexPrices(cmd) => cmd.venue.as_ref(),
265 Self::FundingRates(cmd) => cmd.venue.as_ref(),
266 Self::InstrumentStatus(cmd) => cmd.venue.as_ref(),
267 Self::InstrumentClose(cmd) => cmd.venue.as_ref(),
268 }
269 }
270
271 pub fn ts_init(&self) -> UnixNanos {
272 match self {
273 Self::Data(cmd) => cmd.ts_init,
274 Self::Instrument(cmd) => cmd.ts_init,
275 Self::Instruments(cmd) => cmd.ts_init,
276 Self::BookDeltas(cmd) => cmd.ts_init,
277 Self::BookDepth10(cmd) => cmd.ts_init,
278 Self::BookSnapshots(cmd) => cmd.ts_init,
279 Self::Quotes(cmd) => cmd.ts_init,
280 Self::Trades(cmd) => cmd.ts_init,
281 Self::MarkPrices(cmd) => cmd.ts_init,
282 Self::IndexPrices(cmd) => cmd.ts_init,
283 Self::FundingRates(cmd) => cmd.ts_init,
284 Self::Bars(cmd) => cmd.ts_init,
285 Self::InstrumentStatus(cmd) => cmd.ts_init,
286 Self::InstrumentClose(cmd) => cmd.ts_init,
287 }
288 }
289}
290
291fn check_client_id_or_venue(client_id: &Option<ClientId>, venue: &Option<Venue>) {
292 assert!(
293 client_id.is_some() || venue.is_some(),
294 "Both `client_id` and `venue` were None"
295 );
296}
297
298#[derive(Clone, Debug)]
299pub enum RequestCommand {
300 Data(RequestCustomData),
301 Instrument(RequestInstrument),
302 Instruments(RequestInstruments),
303 BookSnapshot(RequestBookSnapshot),
304 BookDepth(RequestBookDepth),
305 Quotes(RequestQuotes),
306 Trades(RequestTrades),
307 Bars(RequestBars),
308}
309
310impl PartialEq for RequestCommand {
311 fn eq(&self, other: &Self) -> bool {
312 self.request_id() == other.request_id()
313 }
314}
315
316impl RequestCommand {
317 pub fn as_any(&self) -> &dyn Any {
319 self
320 }
321
322 pub fn request_id(&self) -> &UUID4 {
323 match self {
324 Self::Data(cmd) => &cmd.request_id,
325 Self::Instrument(cmd) => &cmd.request_id,
326 Self::Instruments(cmd) => &cmd.request_id,
327 Self::BookSnapshot(cmd) => &cmd.request_id,
328 Self::BookDepth(cmd) => &cmd.request_id,
329 Self::Quotes(cmd) => &cmd.request_id,
330 Self::Trades(cmd) => &cmd.request_id,
331 Self::Bars(cmd) => &cmd.request_id,
332 }
333 }
334
335 pub fn client_id(&self) -> Option<&ClientId> {
336 match self {
337 Self::Data(cmd) => Some(&cmd.client_id),
338 Self::Instrument(cmd) => cmd.client_id.as_ref(),
339 Self::Instruments(cmd) => cmd.client_id.as_ref(),
340 Self::BookSnapshot(cmd) => cmd.client_id.as_ref(),
341 Self::BookDepth(cmd) => cmd.client_id.as_ref(),
342 Self::Quotes(cmd) => cmd.client_id.as_ref(),
343 Self::Trades(cmd) => cmd.client_id.as_ref(),
344 Self::Bars(cmd) => cmd.client_id.as_ref(),
345 }
346 }
347
348 pub fn venue(&self) -> Option<&Venue> {
349 match self {
350 Self::Data(_) => None,
351 Self::Instrument(cmd) => Some(&cmd.instrument_id.venue),
352 Self::Instruments(cmd) => cmd.venue.as_ref(),
353 Self::BookSnapshot(cmd) => Some(&cmd.instrument_id.venue),
354 Self::BookDepth(cmd) => Some(&cmd.instrument_id.venue),
355 Self::Quotes(cmd) => Some(&cmd.instrument_id.venue),
356 Self::Trades(cmd) => Some(&cmd.instrument_id.venue),
357 Self::Bars(cmd) => match &cmd.bar_type {
359 BarType::Standard { instrument_id, .. } => Some(&instrument_id.venue),
360 BarType::Composite { instrument_id, .. } => Some(&instrument_id.venue),
361 },
362 }
363 }
364
365 pub fn ts_init(&self) -> UnixNanos {
366 match self {
367 Self::Data(cmd) => cmd.ts_init,
368 Self::Instrument(cmd) => cmd.ts_init,
369 Self::Instruments(cmd) => cmd.ts_init,
370 Self::BookSnapshot(cmd) => cmd.ts_init,
371 Self::BookDepth(cmd) => cmd.ts_init,
372 Self::Quotes(cmd) => cmd.ts_init,
373 Self::Trades(cmd) => cmd.ts_init,
374 Self::Bars(cmd) => cmd.ts_init,
375 }
376 }
377}
378
379#[derive(Clone, Debug)]
380pub enum DataResponse {
381 Data(CustomDataResponse),
382 Instrument(Box<InstrumentResponse>),
383 Instruments(InstrumentsResponse),
384 Book(BookResponse),
385 Quotes(QuotesResponse),
386 Trades(TradesResponse),
387 Bars(BarsResponse),
388}
389
390impl DataResponse {
391 pub fn as_any(&self) -> &dyn Any {
393 self
394 }
395
396 pub fn correlation_id(&self) -> &UUID4 {
397 match self {
398 Self::Data(resp) => &resp.correlation_id,
399 Self::Instrument(resp) => &resp.correlation_id,
400 Self::Instruments(resp) => &resp.correlation_id,
401 Self::Book(resp) => &resp.correlation_id,
402 Self::Quotes(resp) => &resp.correlation_id,
403 Self::Trades(resp) => &resp.correlation_id,
404 Self::Bars(resp) => &resp.correlation_id,
405 }
406 }
407}
408
409pub type Payload = Arc<dyn Any + Send + Sync>;