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 subscribe;
27pub mod unsubscribe;
28
29// Re-exports
30pub use subscribe::{
31    SubscribeBlocks, SubscribePool, SubscribePoolLiquidityUpdates, SubscribePoolSwaps,
32};
33pub use unsubscribe::{
34    UnsubscribeBlocks, UnsubscribePool, UnsubscribePoolLiquidityUpdates, UnsubscribePoolSwaps,
35};
36
37#[derive(Clone, Debug)]
38pub enum DefiDataCommand {
39    Subscribe(DefiSubscribeCommand),
40    Unsubscribe(DefiUnsubscribeCommand),
41}
42
43impl PartialEq for DefiDataCommand {
44    fn eq(&self, other: &Self) -> bool {
45        self.command_id() == other.command_id()
46    }
47}
48
49impl DefiDataCommand {
50    /// Converts the command to a dyn Any trait object for messaging.
51    pub fn as_any(&self) -> &dyn Any {
52        self
53    }
54
55    pub fn command_id(&self) -> UUID4 {
56        match self {
57            Self::Subscribe(cmd) => cmd.command_id(),
58            Self::Unsubscribe(cmd) => cmd.command_id(),
59        }
60    }
61
62    pub fn client_id(&self) -> Option<&ClientId> {
63        match self {
64            Self::Subscribe(cmd) => cmd.client_id(),
65            Self::Unsubscribe(cmd) => cmd.client_id(),
66        }
67    }
68
69    pub fn venue(&self) -> Option<&Venue> {
70        match self {
71            Self::Subscribe(cmd) => cmd.venue(),
72            Self::Unsubscribe(cmd) => cmd.venue(),
73        }
74    }
75
76    pub fn ts_init(&self) -> UnixNanos {
77        match self {
78            Self::Subscribe(cmd) => cmd.ts_init(),
79            Self::Unsubscribe(cmd) => cmd.ts_init(),
80        }
81    }
82}
83
84#[derive(Clone, Debug)]
85pub enum DefiSubscribeCommand {
86    Blocks(SubscribeBlocks),
87    Pool(SubscribePool),
88    PoolSwaps(SubscribePoolSwaps),
89    PoolLiquidityUpdates(SubscribePoolLiquidityUpdates),
90}
91
92impl PartialEq for DefiSubscribeCommand {
93    fn eq(&self, other: &Self) -> bool {
94        self.command_id() == other.command_id()
95    }
96}
97
98impl DefiSubscribeCommand {
99    /// Converts the command to a dyn Any trait object for messaging.
100    pub fn as_any(&self) -> &dyn Any {
101        self
102    }
103
104    /// Returns the blockchain associated with this command.
105    ///
106    /// # Panics
107    ///
108    /// Panics if the instrument ID's venue cannot be parsed as a valid blockchain venue
109    /// for Pool, PoolSwaps, or PoolLiquidityUpdates commands.
110    pub fn blockchain(&self) -> Blockchain {
111        match self {
112            Self::Blocks(cmd) => cmd.chain,
113            Self::Pool(cmd) => cmd.instrument_id.blockchain().expect("Invalid venue"),
114            Self::PoolSwaps(cmd) => cmd.instrument_id.blockchain().expect("Invalid venue"),
115            Self::PoolLiquidityUpdates(cmd) => {
116                cmd.instrument_id.blockchain().expect("Invalid venue")
117            }
118        }
119    }
120
121    pub fn command_id(&self) -> UUID4 {
122        match self {
123            Self::Blocks(cmd) => cmd.command_id,
124            Self::Pool(cmd) => cmd.command_id,
125            Self::PoolSwaps(cmd) => cmd.command_id,
126            Self::PoolLiquidityUpdates(cmd) => cmd.command_id,
127        }
128    }
129
130    pub fn client_id(&self) -> Option<&ClientId> {
131        match self {
132            Self::Blocks(cmd) => cmd.client_id.as_ref(),
133            Self::Pool(cmd) => cmd.client_id.as_ref(),
134            Self::PoolSwaps(cmd) => cmd.client_id.as_ref(),
135            Self::PoolLiquidityUpdates(cmd) => cmd.client_id.as_ref(),
136        }
137    }
138
139    // TODO: TBD
140    pub fn venue(&self) -> Option<&Venue> {
141        match self {
142            Self::Blocks(_) => None,
143            Self::Pool(_) => None,
144            Self::PoolSwaps(_) => None,
145            Self::PoolLiquidityUpdates(_) => None,
146        }
147    }
148
149    pub fn ts_init(&self) -> UnixNanos {
150        match self {
151            Self::Blocks(cmd) => cmd.ts_init,
152            Self::PoolSwaps(cmd) => cmd.ts_init,
153            Self::PoolLiquidityUpdates(cmd) => cmd.ts_init,
154            Self::Pool(cmd) => cmd.ts_init,
155        }
156    }
157}
158
159#[derive(Clone, Debug)]
160pub enum DefiUnsubscribeCommand {
161    Blocks(UnsubscribeBlocks),
162    Pool(UnsubscribePool),
163    PoolSwaps(UnsubscribePoolSwaps),
164    PoolLiquidityUpdates(UnsubscribePoolLiquidityUpdates),
165}
166
167impl PartialEq for DefiUnsubscribeCommand {
168    fn eq(&self, other: &Self) -> bool {
169        self.command_id() == other.command_id()
170    }
171}
172
173impl DefiUnsubscribeCommand {
174    /// Converts the command to a dyn Any trait object for messaging.
175    pub fn as_any(&self) -> &dyn Any {
176        self
177    }
178
179    /// Returns the blockchain associated with this command.
180    ///
181    /// # Panics
182    ///
183    /// Panics if the instrument ID's venue cannot be parsed as a valid blockchain venue
184    /// for Pool, PoolSwaps, or PoolLiquidityUpdates commands.
185    pub fn blockchain(&self) -> Blockchain {
186        match self {
187            Self::Blocks(cmd) => cmd.chain,
188            Self::Pool(cmd) => cmd.instrument_id.blockchain().expect("Invalid venue"),
189            Self::PoolSwaps(cmd) => cmd.instrument_id.blockchain().expect("Invalid venue"),
190            Self::PoolLiquidityUpdates(cmd) => {
191                cmd.instrument_id.blockchain().expect("Invalid venue")
192            }
193        }
194    }
195
196    pub fn command_id(&self) -> UUID4 {
197        match self {
198            Self::Blocks(cmd) => cmd.command_id,
199            Self::Pool(cmd) => cmd.command_id,
200            Self::PoolSwaps(cmd) => cmd.command_id,
201            Self::PoolLiquidityUpdates(cmd) => cmd.command_id,
202        }
203    }
204
205    pub fn client_id(&self) -> Option<&ClientId> {
206        match self {
207            Self::Blocks(cmd) => cmd.client_id.as_ref(),
208            Self::Pool(cmd) => cmd.client_id.as_ref(),
209            Self::PoolSwaps(cmd) => cmd.client_id.as_ref(),
210            Self::PoolLiquidityUpdates(cmd) => cmd.client_id.as_ref(),
211        }
212    }
213
214    // TODO: TBD
215    pub fn venue(&self) -> Option<&Venue> {
216        match self {
217            Self::Blocks(_) => None,
218            Self::Pool(_) => None,
219            Self::PoolSwaps(_) => None,
220            Self::PoolLiquidityUpdates(_) => None,
221        }
222    }
223
224    pub fn ts_init(&self) -> UnixNanos {
225        match self {
226            Self::Blocks(cmd) => cmd.ts_init,
227            Self::Pool(cmd) => cmd.ts_init,
228            Self::PoolSwaps(cmd) => cmd.ts_init,
229            Self::PoolLiquidityUpdates(cmd) => cmd.ts_init,
230        }
231    }
232}