nautilus_blockchain/exchanges/
extended.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
16use std::{ops::Deref, sync::Arc};
17
18use hypersync_client::simple_types::Log;
19use nautilus_model::defi::dex::{Dex, SharedDex};
20
21use crate::events::{
22    burn::BurnEvent, collect::CollectEvent, flash::FlashEvent, initialize::InitializeEvent,
23    mint::MintEvent, pool_created::PoolCreatedEvent, swap::SwapEvent,
24};
25
26/// Extended DEX wrapper that adds provider-specific event parsing capabilities to the domain `Dex` model.
27#[derive(Debug, Clone)]
28pub struct DexExtended {
29    /// The core domain Dex object being extended.
30    pub dex: SharedDex,
31    /// Function to parse pool creation events.
32    pub parse_pool_created_event_fn: Option<fn(Log) -> anyhow::Result<PoolCreatedEvent>>,
33    /// Function to parse initialize events.
34    pub parse_initialize_event_fn: Option<fn(SharedDex, Log) -> anyhow::Result<InitializeEvent>>,
35    /// Function to parse swap events.
36    pub parse_swap_event_fn: Option<fn(SharedDex, Log) -> anyhow::Result<SwapEvent>>,
37    /// Function to parse mint events.
38    pub parse_mint_event_fn: Option<fn(SharedDex, Log) -> anyhow::Result<MintEvent>>,
39    /// Function to parse burn events.
40    pub parse_burn_event_fn: Option<fn(SharedDex, Log) -> anyhow::Result<BurnEvent>>,
41    /// Function to parse collect events.
42    pub parse_collect_event_fn: Option<fn(SharedDex, Log) -> anyhow::Result<CollectEvent>>,
43    /// Function to parse flash events.
44    pub parse_flash_event_fn: Option<fn(SharedDex, Log) -> anyhow::Result<FlashEvent>>,
45}
46
47impl DexExtended {
48    /// Creates a new [`DexExtended`] wrapper around a domain `Dex` object.
49    #[must_use]
50    pub fn new(dex: Dex) -> Self {
51        Self {
52            dex: Arc::new(dex),
53            parse_pool_created_event_fn: None,
54            parse_initialize_event_fn: None,
55            parse_swap_event_fn: None,
56            parse_mint_event_fn: None,
57            parse_burn_event_fn: None,
58            parse_collect_event_fn: None,
59            parse_flash_event_fn: None,
60        }
61    }
62
63    /// Sets the function used to parse pool creation events for this Dex.
64    pub fn set_pool_created_event_parsing(
65        &mut self,
66        parse_pool_created_event: fn(Log) -> anyhow::Result<PoolCreatedEvent>,
67    ) {
68        self.parse_pool_created_event_fn = Some(parse_pool_created_event);
69    }
70
71    /// Sets the function used to parse initialize events for this Dex.
72    pub fn set_initialize_event_parsing(
73        &mut self,
74        parse_initialize_event: fn(SharedDex, Log) -> anyhow::Result<InitializeEvent>,
75    ) {
76        self.parse_initialize_event_fn = Some(parse_initialize_event);
77    }
78
79    /// Sets the function used to parse swap events for this Dex.
80    pub fn set_swap_event_parsing(
81        &mut self,
82        parse_swap_event: fn(SharedDex, Log) -> anyhow::Result<SwapEvent>,
83    ) {
84        self.parse_swap_event_fn = Some(parse_swap_event);
85    }
86
87    /// Sets the function used to parse mint events for this Dex.
88    pub fn set_mint_event_parsing(
89        &mut self,
90        parse_mint_event: fn(SharedDex, Log) -> anyhow::Result<MintEvent>,
91    ) {
92        self.parse_mint_event_fn = Some(parse_mint_event);
93    }
94
95    /// Sets the function used to parse burn events for this Dex.
96    pub fn set_burn_event_parsing(
97        &mut self,
98        parse_burn_event: fn(SharedDex, Log) -> anyhow::Result<BurnEvent>,
99    ) {
100        self.parse_burn_event_fn = Some(parse_burn_event);
101    }
102
103    /// Sets the function used to parse collect events for this Dex.
104    pub fn set_collect_event_parsing(
105        &mut self,
106        parse_collect_event: fn(SharedDex, Log) -> anyhow::Result<CollectEvent>,
107    ) {
108        self.parse_collect_event_fn = Some(parse_collect_event);
109    }
110
111    /// Sets the function used to parse flash events for this Dex.
112    pub fn set_flash_event_parsing(
113        &mut self,
114        parse_flash_event: fn(SharedDex, Log) -> anyhow::Result<FlashEvent>,
115    ) {
116        self.parse_flash_event_fn = Some(parse_flash_event);
117    }
118
119    /// Parses a pool creation event log using this DEX's specific parsing function.
120    ///
121    /// # Errors
122    ///
123    /// Returns an error if the DEX does not have a pool creation event parser defined or if parsing fails.
124    pub fn parse_pool_created_event(&self, log: Log) -> anyhow::Result<PoolCreatedEvent> {
125        if let Some(parse_pool_created_event_fn) = &self.parse_pool_created_event_fn {
126            parse_pool_created_event_fn(log)
127        } else {
128            anyhow::bail!(
129                "Parsing of pool created event in not defined in this dex: {}:{}",
130                self.dex.chain,
131                self.dex.name,
132            )
133        }
134    }
135
136    /// Parses a swap event log using this DEX's specific parsing function.
137    ///
138    /// # Errors
139    ///
140    /// Returns an error if the DEX does not have a swap event parser defined or if parsing fails.
141    pub fn parse_swap_event(&self, log: Log) -> anyhow::Result<SwapEvent> {
142        if let Some(parse_swap_event_fn) = &self.parse_swap_event_fn {
143            parse_swap_event_fn(self.dex.clone(), log)
144        } else {
145            anyhow::bail!(
146                "Parsing of swap event in not defined in this dex: {}:{}",
147                self.dex.chain,
148                self.dex.name
149            )
150        }
151    }
152
153    /// Parses a mint event log using this DEX's specific parsing function.
154    ///
155    /// # Errors
156    ///
157    /// Returns an error if the DEX does not have a mint event parser defined or if parsing fails.
158    pub fn parse_mint_event(&self, log: Log) -> anyhow::Result<MintEvent> {
159        if let Some(parse_mint_event_fn) = &self.parse_mint_event_fn {
160            parse_mint_event_fn(self.dex.clone(), log)
161        } else {
162            anyhow::bail!(
163                "Parsing of mint event in not defined in this dex: {}:{}",
164                self.dex.chain,
165                self.dex.name
166            )
167        }
168    }
169
170    /// Parses a burn event log using this DEX's specific parsing function.
171    ///
172    /// # Errors
173    ///
174    /// Returns an error if the DEX does not have a burn event parser defined or if parsing fails.
175    pub fn parse_burn_event(&self, log: Log) -> anyhow::Result<BurnEvent> {
176        if let Some(parse_burn_event_fn) = &self.parse_burn_event_fn {
177            parse_burn_event_fn(self.dex.clone(), log)
178        } else {
179            anyhow::bail!(
180                "Parsing of burn event in not defined in this dex: {}",
181                self.dex.name
182            )
183        }
184    }
185
186    /// Checks if this DEX requires pool initialization events.
187    pub fn needs_initialization(&self) -> bool {
188        self.dex.initialize_event.is_some()
189    }
190
191    /// Parses an event log into an `InitializeEvent` struct.
192    ///
193    /// # Errors
194    ///
195    /// Returns an error if the DEX does not support initialize events or parsing fails.
196    pub fn parse_initialize_event(&self, log: Log) -> anyhow::Result<InitializeEvent> {
197        if let Some(parse_initialize_event_fn) = &self.parse_initialize_event_fn {
198            parse_initialize_event_fn(self.dex.clone(), log)
199        } else {
200            anyhow::bail!(
201                "Parsing of initialize event in not defined in this dex: {}",
202                self.dex.name
203            )
204        }
205    }
206
207    /// Parses a collect event log using this DEX's specific parsing function.
208    ///
209    /// # Errors
210    ///
211    /// Returns an error if the DEX does not have a collect event parser defined or if parsing fails.
212    pub fn parse_collect_event(&self, log: Log) -> anyhow::Result<CollectEvent> {
213        if let Some(parse_collect_event_fn) = &self.parse_collect_event_fn {
214            parse_collect_event_fn(self.dex.clone(), log)
215        } else {
216            anyhow::bail!(
217                "Parsing of collect event in not defined in this dex: {}:{}",
218                self.dex.chain,
219                self.dex.name
220            )
221        }
222    }
223}
224
225impl Deref for DexExtended {
226    type Target = Dex;
227
228    fn deref(&self) -> &Self::Target {
229        &self.dex
230    }
231}