Skip to main content

nautilus_model/defi/data/
mod.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 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) data models and types.
17//!
18//! This module provides core data structures for working with decentralized finance protocols,
19//! including blockchain networks, tokens, liquidity pools, swaps, and other DeFi primitives.
20
21use std::fmt::Display;
22
23use nautilus_core::UnixNanos;
24
25use crate::{
26    data::HasTsInit,
27    defi::{Pool, pool_analysis::PoolSnapshot},
28    identifiers::InstrumentId,
29};
30
31pub mod block;
32pub mod collect;
33pub mod fee_protocol_collect;
34pub mod fee_protocol_update;
35pub mod flash;
36pub mod liquidity;
37pub mod swap;
38pub mod swap_trade_info;
39pub mod transaction;
40
41// Re-exports
42pub use block::Block;
43pub use collect::PoolFeeCollect;
44pub use fee_protocol_collect::PoolFeeProtocolCollect;
45pub use fee_protocol_update::PoolFeeProtocolUpdate;
46pub use flash::PoolFlash;
47pub use liquidity::{PoolLiquidityUpdate, PoolLiquidityUpdateType};
48pub use swap::PoolSwap;
49pub use transaction::Transaction;
50
51#[derive(Debug, Clone, PartialEq)]
52pub enum DexPoolData {
53    Swap(PoolSwap),
54    LiquidityUpdate(PoolLiquidityUpdate),
55    FeeCollect(PoolFeeCollect),
56    FeeProtocolUpdate(PoolFeeProtocolUpdate),
57    FeeProtocolCollect(PoolFeeProtocolCollect),
58    Flash(PoolFlash),
59}
60
61impl DexPoolData {
62    /// Returns the block number associated with this pool event.
63    #[must_use]
64    pub fn block_number(&self) -> u64 {
65        match self {
66            Self::Swap(s) => s.block,
67            Self::LiquidityUpdate(u) => u.block,
68            Self::FeeCollect(c) => c.block,
69            Self::FeeProtocolUpdate(u) => u.block,
70            Self::FeeProtocolCollect(c) => c.block,
71            Self::Flash(f) => f.block,
72        }
73    }
74
75    /// Returns the transaction index associated with this pool event.
76    #[must_use]
77    pub fn transaction_index(&self) -> u32 {
78        match self {
79            Self::Swap(s) => s.transaction_index,
80            Self::LiquidityUpdate(u) => u.transaction_index,
81            Self::FeeCollect(c) => c.transaction_index,
82            Self::FeeProtocolUpdate(u) => u.transaction_index,
83            Self::FeeProtocolCollect(c) => c.transaction_index,
84            Self::Flash(f) => f.transaction_index,
85        }
86    }
87
88    /// Returns the log index associated with this pool event.
89    #[must_use]
90    pub fn log_index(&self) -> u32 {
91        match self {
92            Self::Swap(s) => s.log_index,
93            Self::LiquidityUpdate(u) => u.log_index,
94            Self::FeeCollect(c) => c.log_index,
95            Self::FeeProtocolUpdate(u) => u.log_index,
96            Self::FeeProtocolCollect(c) => c.log_index,
97            Self::Flash(f) => f.log_index,
98        }
99    }
100}
101
102/// Represents DeFi-specific data events in a decentralized exchange ecosystem.
103#[cfg_attr(
104    feature = "python",
105    pyo3::pyclass(module = "nautilus_trader.model", from_py_object)
106)]
107#[cfg_attr(
108    feature = "python",
109    pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
110)]
111#[derive(Debug, Clone, PartialEq)]
112pub enum DefiData {
113    /// A block completion in a blockchain network.
114    Block(Block),
115    /// A DEX liquidity pool definition or update.
116    Pool(Pool),
117    /// A complete snapshot of a pool's state at a specific point in time.
118    PoolSnapshot(PoolSnapshot),
119    /// A token swap transaction on a decentralized exchange.
120    PoolSwap(PoolSwap),
121    /// A liquidity update event (mint/burn) in a DEX pool.
122    PoolLiquidityUpdate(PoolLiquidityUpdate),
123    /// A fee collection event from a DEX pool position.
124    PoolFeeCollect(PoolFeeCollect),
125    /// A protocol-fee configuration change in a DEX pool.
126    PoolFeeProtocolUpdate(PoolFeeProtocolUpdate),
127    /// A protocol-fee withdrawal from a DEX pool.
128    PoolFeeProtocolCollect(PoolFeeProtocolCollect),
129    /// A flash event
130    PoolFlash(PoolFlash),
131}
132
133impl DefiData {
134    /// Returns the block position associated with this DeFi data.
135    #[must_use]
136    #[rustfmt::skip]
137    pub fn block_position(&self) -> (u64, u32, u32) {
138        match self {
139            Self::Block(block) => (block.number, 0, 0),
140            Self::Pool(pool) => (pool.creation_block, 0, 0),
141            Self::PoolSnapshot(snapshot) => (
142                snapshot.block_position.number,
143                snapshot.block_position.transaction_index,
144                snapshot.block_position.log_index,
145            ),
146            Self::PoolSwap(swap) => (swap.block, swap.transaction_index, swap.log_index),
147            Self::PoolLiquidityUpdate(update) => (update.block, update.transaction_index, update.log_index),
148            Self::PoolFeeCollect(collect) => (collect.block, collect.transaction_index, collect.log_index),
149            Self::PoolFeeProtocolUpdate(update) => (update.block, update.transaction_index, update.log_index),
150            Self::PoolFeeProtocolCollect(collect) => (collect.block, collect.transaction_index, collect.log_index),
151            Self::PoolFlash(flash) => (flash.block, flash.transaction_index, flash.log_index),
152        }
153    }
154
155    /// Returns the block number associated with this DeFi data.
156    #[must_use]
157    pub fn block_number(&self) -> u64 {
158        self.block_position().0
159    }
160
161    /// Returns the transaction index associated with this DeFi data.
162    #[must_use]
163    pub fn transaction_index(&self) -> u32 {
164        self.block_position().1
165    }
166
167    /// Returns the log index associated with this DeFi data.
168    #[must_use]
169    pub fn log_index(&self) -> u32 {
170        self.block_position().2
171    }
172
173    /// Returns the event timestamp associated with this DeFi data.
174    #[must_use]
175    pub fn ts_event(&self) -> UnixNanos {
176        match self {
177            Self::Block(block) => block.timestamp,
178            Self::Pool(pool) => pool.ts_event,
179            Self::PoolSnapshot(snapshot) => snapshot.ts_event,
180            Self::PoolSwap(swap) => swap.ts_event,
181            Self::PoolLiquidityUpdate(update) => update.ts_event,
182            Self::PoolFeeCollect(collect) => collect.ts_event,
183            Self::PoolFeeProtocolUpdate(update) => update.ts_event,
184            Self::PoolFeeProtocolCollect(collect) => collect.ts_event,
185            Self::PoolFlash(flash) => flash.ts_event,
186        }
187    }
188
189    /// Returns the event timestamp associated with this DeFi data.
190    #[must_use]
191    pub fn timestamp(&self) -> UnixNanos {
192        self.ts_event()
193    }
194
195    /// Returns the initialization timestamp associated with this DeFi data.
196    #[must_use]
197    pub fn ts_init(&self) -> UnixNanos {
198        match self {
199            Self::Block(block) => block.timestamp,
200            Self::Pool(pool) => pool.ts_init,
201            Self::PoolSnapshot(snapshot) => snapshot.ts_init,
202            Self::PoolSwap(swap) => swap.ts_init,
203            Self::PoolLiquidityUpdate(update) => update.ts_init,
204            Self::PoolFeeCollect(collect) => collect.ts_init,
205            Self::PoolFeeProtocolUpdate(update) => update.ts_init,
206            Self::PoolFeeProtocolCollect(collect) => collect.ts_init,
207            Self::PoolFlash(flash) => flash.ts_init,
208        }
209    }
210
211    /// Returns the instrument ID associated with this DeFi data.
212    ///
213    /// # Panics
214    ///
215    /// Panics if the variant is a `Block` or `PoolSnapshot` where instrument IDs are not applicable.
216    #[must_use]
217    pub fn instrument_id(&self) -> InstrumentId {
218        match self {
219            Self::Block(_) => panic!("`InstrumentId` not applicable to `Block`"), // TBD?
220            Self::PoolSnapshot(snapshot) => snapshot.instrument_id,
221            Self::PoolSwap(swap) => swap.instrument_id,
222            Self::PoolLiquidityUpdate(update) => update.instrument_id,
223            Self::PoolFeeCollect(collect) => collect.instrument_id,
224            Self::PoolFeeProtocolUpdate(update) => update.instrument_id,
225            Self::PoolFeeProtocolCollect(collect) => collect.instrument_id,
226            Self::Pool(pool) => pool.instrument_id,
227            Self::PoolFlash(flash) => flash.instrument_id,
228        }
229    }
230}
231
232impl HasTsInit for DefiData {
233    fn ts_init(&self) -> UnixNanos {
234        self.ts_init()
235    }
236}
237
238impl HasTsInit for Block {
239    fn ts_init(&self) -> UnixNanos {
240        self.timestamp
241    }
242}
243
244impl HasTsInit for PoolSnapshot {
245    fn ts_init(&self) -> UnixNanos {
246        self.ts_init
247    }
248}
249
250impl HasTsInit for PoolSwap {
251    fn ts_init(&self) -> UnixNanos {
252        self.ts_init
253    }
254}
255
256impl HasTsInit for PoolLiquidityUpdate {
257    fn ts_init(&self) -> UnixNanos {
258        self.ts_init
259    }
260}
261
262impl HasTsInit for PoolFeeCollect {
263    fn ts_init(&self) -> UnixNanos {
264        self.ts_init
265    }
266}
267
268impl HasTsInit for PoolFeeProtocolUpdate {
269    fn ts_init(&self) -> UnixNanos {
270        self.ts_init
271    }
272}
273
274impl HasTsInit for PoolFeeProtocolCollect {
275    fn ts_init(&self) -> UnixNanos {
276        self.ts_init
277    }
278}
279
280impl HasTsInit for PoolFlash {
281    fn ts_init(&self) -> UnixNanos {
282        self.ts_init
283    }
284}
285
286impl Display for DefiData {
287    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
288        match self {
289            Self::Block(b) => write!(f, "{b}"),
290            Self::Pool(p) => write!(f, "{p}"),
291            Self::PoolSnapshot(s) => write!(f, "PoolSnapshot(block={})", s.block_position.number),
292            Self::PoolSwap(s) => write!(f, "{s}"),
293            Self::PoolLiquidityUpdate(u) => write!(f, "{u}"),
294            Self::PoolFeeCollect(c) => write!(f, "{c}"),
295            Self::PoolFeeProtocolUpdate(u) => write!(f, "{u}"),
296            Self::PoolFeeProtocolCollect(c) => write!(f, "{c}"),
297            Self::PoolFlash(p) => write!(f, "{p}"),
298        }
299    }
300}
301
302impl From<Pool> for DefiData {
303    fn from(value: Pool) -> Self {
304        Self::Pool(value)
305    }
306}
307
308impl From<PoolSwap> for DefiData {
309    fn from(value: PoolSwap) -> Self {
310        Self::PoolSwap(value)
311    }
312}
313
314impl From<PoolLiquidityUpdate> for DefiData {
315    fn from(value: PoolLiquidityUpdate) -> Self {
316        Self::PoolLiquidityUpdate(value)
317    }
318}
319
320impl From<PoolFeeCollect> for DefiData {
321    fn from(value: PoolFeeCollect) -> Self {
322        Self::PoolFeeCollect(value)
323    }
324}
325
326impl From<PoolFeeProtocolUpdate> for DefiData {
327    fn from(value: PoolFeeProtocolUpdate) -> Self {
328        Self::PoolFeeProtocolUpdate(value)
329    }
330}
331
332impl From<PoolFeeProtocolCollect> for DefiData {
333    fn from(value: PoolFeeProtocolCollect) -> Self {
334        Self::PoolFeeProtocolCollect(value)
335    }
336}
337
338impl From<PoolSnapshot> for DefiData {
339    fn from(value: PoolSnapshot) -> Self {
340        Self::PoolSnapshot(value)
341    }
342}
343
344impl From<PoolFlash> for DefiData {
345    fn from(value: PoolFlash) -> Self {
346        Self::PoolFlash(value)
347    }
348}