nautilus_common/messages/defi/
mod.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//! DeFi (Decentralized Finance) specific messages.
17
18use std::any::Any;
19
20use nautilus_core::{UUID4, UnixNanos};
21use nautilus_model::{
22    defi::Blockchain,
23    identifiers::{ClientId, Venue},
24};
25
26pub mod request;
27pub mod subscribe;
28pub mod unsubscribe;
29
30// Re-exports
31pub use request::RequestPoolSnapshot;
32pub use subscribe::{
33    SubscribeBlocks, SubscribePool, SubscribePoolFeeCollects, SubscribePoolFlashEvents,
34    SubscribePoolLiquidityUpdates, SubscribePoolSwaps,
35};
36pub use unsubscribe::{
37    UnsubscribeBlocks, UnsubscribePool, UnsubscribePoolFeeCollects, UnsubscribePoolFlashEvents,
38    UnsubscribePoolLiquidityUpdates, UnsubscribePoolSwaps,
39};
40
41#[derive(Clone, Debug)]
42pub enum DefiDataCommand {
43    Request(DefiRequestCommand),
44    Subscribe(DefiSubscribeCommand),
45    Unsubscribe(DefiUnsubscribeCommand),
46}
47
48impl PartialEq for DefiDataCommand {
49    fn eq(&self, other: &Self) -> bool {
50        self.command_id() == other.command_id()
51    }
52}
53
54impl DefiDataCommand {
55    /// Converts the command to a dyn Any trait object for messaging.
56    pub fn as_any(&self) -> &dyn Any {
57        self
58    }
59
60    pub fn command_id(&self) -> UUID4 {
61        match self {
62            Self::Request(cmd) => *cmd.request_id(),
63            Self::Subscribe(cmd) => cmd.command_id(),
64            Self::Unsubscribe(cmd) => cmd.command_id(),
65        }
66    }
67
68    pub fn client_id(&self) -> Option<&ClientId> {
69        match self {
70            Self::Request(cmd) => cmd.client_id(),
71            Self::Subscribe(cmd) => cmd.client_id(),
72            Self::Unsubscribe(cmd) => cmd.client_id(),
73        }
74    }
75
76    pub fn venue(&self) -> Option<&Venue> {
77        match self {
78            Self::Request(cmd) => cmd.venue(),
79            Self::Subscribe(cmd) => cmd.venue(),
80            Self::Unsubscribe(cmd) => cmd.venue(),
81        }
82    }
83
84    pub fn ts_init(&self) -> UnixNanos {
85        match self {
86            Self::Request(cmd) => cmd.ts_init(),
87            Self::Subscribe(cmd) => cmd.ts_init(),
88            Self::Unsubscribe(cmd) => cmd.ts_init(),
89        }
90    }
91}
92
93#[derive(Clone, Debug)]
94pub enum DefiSubscribeCommand {
95    Blocks(SubscribeBlocks),
96    Pool(SubscribePool),
97    PoolSwaps(SubscribePoolSwaps),
98    PoolLiquidityUpdates(SubscribePoolLiquidityUpdates),
99    PoolFeeCollects(SubscribePoolFeeCollects),
100    PoolFlashEvents(SubscribePoolFlashEvents),
101}
102
103impl PartialEq for DefiSubscribeCommand {
104    fn eq(&self, other: &Self) -> bool {
105        self.command_id() == other.command_id()
106    }
107}
108
109impl DefiSubscribeCommand {
110    /// Converts the command to a dyn Any trait object for messaging.
111    pub fn as_any(&self) -> &dyn Any {
112        self
113    }
114
115    /// Returns the blockchain associated with this command.
116    ///
117    /// # Panics
118    ///
119    /// Panics if the instrument ID's venue cannot be parsed as a valid blockchain venue
120    /// for Pool, PoolSwaps, PoolLiquidityUpdates, PoolFeeCollects, or PoolFlashEvents commands.
121    pub fn blockchain(&self) -> Blockchain {
122        match self {
123            Self::Blocks(cmd) => cmd.chain,
124            Self::Pool(cmd) => cmd.instrument_id.blockchain().expect("Invalid venue"),
125            Self::PoolSwaps(cmd) => cmd.instrument_id.blockchain().expect("Invalid venue"),
126            Self::PoolLiquidityUpdates(cmd) => {
127                cmd.instrument_id.blockchain().expect("Invalid venue")
128            }
129            Self::PoolFeeCollects(cmd) => cmd.instrument_id.blockchain().expect("Invalid venue"),
130            Self::PoolFlashEvents(cmd) => cmd.instrument_id.blockchain().expect("Invalid venue"),
131        }
132    }
133
134    pub fn command_id(&self) -> UUID4 {
135        match self {
136            Self::Blocks(cmd) => cmd.command_id,
137            Self::Pool(cmd) => cmd.command_id,
138            Self::PoolSwaps(cmd) => cmd.command_id,
139            Self::PoolLiquidityUpdates(cmd) => cmd.command_id,
140            Self::PoolFeeCollects(cmd) => cmd.command_id,
141            Self::PoolFlashEvents(cmd) => cmd.command_id,
142        }
143    }
144
145    pub fn client_id(&self) -> Option<&ClientId> {
146        match self {
147            Self::Blocks(cmd) => cmd.client_id.as_ref(),
148            Self::Pool(cmd) => cmd.client_id.as_ref(),
149            Self::PoolSwaps(cmd) => cmd.client_id.as_ref(),
150            Self::PoolLiquidityUpdates(cmd) => cmd.client_id.as_ref(),
151            Self::PoolFeeCollects(cmd) => cmd.client_id.as_ref(),
152            Self::PoolFlashEvents(cmd) => cmd.client_id.as_ref(),
153        }
154    }
155
156    // TODO: TBD
157    pub fn venue(&self) -> Option<&Venue> {
158        match self {
159            Self::Blocks(_) => None,
160            Self::Pool(_) => None,
161            Self::PoolSwaps(_) => None,
162            Self::PoolLiquidityUpdates(_) => None,
163            Self::PoolFeeCollects(_) => None,
164            Self::PoolFlashEvents(_) => None,
165        }
166    }
167
168    pub fn ts_init(&self) -> UnixNanos {
169        match self {
170            Self::Blocks(cmd) => cmd.ts_init,
171            Self::PoolSwaps(cmd) => cmd.ts_init,
172            Self::PoolLiquidityUpdates(cmd) => cmd.ts_init,
173            Self::Pool(cmd) => cmd.ts_init,
174            Self::PoolFeeCollects(cmd) => cmd.ts_init,
175            Self::PoolFlashEvents(cmd) => cmd.ts_init,
176        }
177    }
178}
179
180#[derive(Clone, Debug)]
181pub enum DefiUnsubscribeCommand {
182    Blocks(UnsubscribeBlocks),
183    Pool(UnsubscribePool),
184    PoolSwaps(UnsubscribePoolSwaps),
185    PoolLiquidityUpdates(UnsubscribePoolLiquidityUpdates),
186    PoolFeeCollects(UnsubscribePoolFeeCollects),
187    PoolFlashEvents(UnsubscribePoolFlashEvents),
188}
189
190impl PartialEq for DefiUnsubscribeCommand {
191    fn eq(&self, other: &Self) -> bool {
192        self.command_id() == other.command_id()
193    }
194}
195
196impl DefiUnsubscribeCommand {
197    /// Converts the command to a dyn Any trait object for messaging.
198    pub fn as_any(&self) -> &dyn Any {
199        self
200    }
201
202    /// Returns the blockchain associated with this command.
203    ///
204    /// # Panics
205    ///
206    /// Panics if the instrument ID's venue cannot be parsed as a valid blockchain venue
207    /// for Pool, PoolSwaps, PoolLiquidityUpdates, PoolFeeCollects, or PoolFlashEvents commands.
208    pub fn blockchain(&self) -> Blockchain {
209        match self {
210            Self::Blocks(cmd) => cmd.chain,
211            Self::Pool(cmd) => cmd.instrument_id.blockchain().expect("Invalid venue"),
212            Self::PoolSwaps(cmd) => cmd.instrument_id.blockchain().expect("Invalid venue"),
213            Self::PoolLiquidityUpdates(cmd) => {
214                cmd.instrument_id.blockchain().expect("Invalid venue")
215            }
216            Self::PoolFeeCollects(cmd) => cmd.instrument_id.blockchain().expect("Invalid venue"),
217            Self::PoolFlashEvents(cmd) => cmd.instrument_id.blockchain().expect("Invalid venue"),
218        }
219    }
220
221    pub fn command_id(&self) -> UUID4 {
222        match self {
223            Self::Blocks(cmd) => cmd.command_id,
224            Self::Pool(cmd) => cmd.command_id,
225            Self::PoolSwaps(cmd) => cmd.command_id,
226            Self::PoolLiquidityUpdates(cmd) => cmd.command_id,
227            Self::PoolFeeCollects(cmd) => cmd.command_id,
228            Self::PoolFlashEvents(cmd) => cmd.command_id,
229        }
230    }
231
232    pub fn client_id(&self) -> Option<&ClientId> {
233        match self {
234            Self::Blocks(cmd) => cmd.client_id.as_ref(),
235            Self::Pool(cmd) => cmd.client_id.as_ref(),
236            Self::PoolSwaps(cmd) => cmd.client_id.as_ref(),
237            Self::PoolLiquidityUpdates(cmd) => cmd.client_id.as_ref(),
238            Self::PoolFeeCollects(cmd) => cmd.client_id.as_ref(),
239            Self::PoolFlashEvents(cmd) => cmd.client_id.as_ref(),
240        }
241    }
242
243    // TODO: TBD
244    pub fn venue(&self) -> Option<&Venue> {
245        match self {
246            Self::Blocks(_) => None,
247            Self::Pool(_) => None,
248            Self::PoolSwaps(_) => None,
249            Self::PoolLiquidityUpdates(_) => None,
250            Self::PoolFeeCollects(_) => None,
251            Self::PoolFlashEvents(_) => None,
252        }
253    }
254
255    pub fn ts_init(&self) -> UnixNanos {
256        match self {
257            Self::Blocks(cmd) => cmd.ts_init,
258            Self::Pool(cmd) => cmd.ts_init,
259            Self::PoolSwaps(cmd) => cmd.ts_init,
260            Self::PoolLiquidityUpdates(cmd) => cmd.ts_init,
261            Self::PoolFeeCollects(cmd) => cmd.ts_init,
262            Self::PoolFlashEvents(cmd) => cmd.ts_init,
263        }
264    }
265}
266
267#[derive(Clone, Debug)]
268pub enum DefiRequestCommand {
269    PoolSnapshot(RequestPoolSnapshot),
270}
271
272impl PartialEq for DefiRequestCommand {
273    fn eq(&self, other: &Self) -> bool {
274        self.request_id() == other.request_id()
275    }
276}
277
278impl DefiRequestCommand {
279    /// Converts the command to a dyn Any trait object for messaging.
280    pub fn as_any(&self) -> &dyn Any {
281        self
282    }
283
284    pub fn request_id(&self) -> &UUID4 {
285        match self {
286            Self::PoolSnapshot(cmd) => &cmd.request_id,
287        }
288    }
289
290    pub fn client_id(&self) -> Option<&ClientId> {
291        match self {
292            Self::PoolSnapshot(cmd) => cmd.client_id.as_ref(),
293        }
294    }
295
296    pub fn venue(&self) -> Option<&Venue> {
297        match self {
298            Self::PoolSnapshot(cmd) => Some(&cmd.instrument_id.venue),
299        }
300    }
301
302    pub fn ts_init(&self) -> UnixNanos {
303        match self {
304            Self::PoolSnapshot(cmd) => cmd.ts_init,
305        }
306    }
307}