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