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