nautilus_blockchain/exchanges/
extended.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 Posei Systems Pty Ltd. All rights reserved.
3//  https://poseitrader.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::{
20    defi::{
21        dex::{Dex, SharedDex},
22        token::Token,
23    },
24    enums::OrderSide,
25    types::{Price, Quantity},
26};
27
28use crate::events::{
29    burn::BurnEvent, mint::MintEvent, pool_created::PoolCreatedEvent, swap::SwapEvent,
30};
31
32/// Extended DEX wrapper that adds provider-specific event parsing capabilities to the domain `Dex` model.
33#[derive(Debug, Clone)]
34pub struct DexExtended {
35    /// The core domain Dex object being extended
36    pub dex: SharedDex,
37    /// Function to parse pool creation events
38    pub parse_pool_created_event_fn: Option<fn(Log) -> anyhow::Result<PoolCreatedEvent>>,
39    /// Function to parse swap events
40    pub parse_swap_event_fn: Option<fn(Log) -> anyhow::Result<SwapEvent>>,
41    /// Function to parse mint events
42    pub parse_mint_event_fn: Option<fn(Log) -> anyhow::Result<MintEvent>>,
43    /// Function to parse burn events
44    pub parse_burn_event_fn: Option<fn(Log) -> anyhow::Result<BurnEvent>>,
45    /// Function to convert to trade data
46    pub convert_to_trade_data_fn:
47        Option<fn(&Token, &Token, &SwapEvent) -> anyhow::Result<(OrderSide, Quantity, Price)>>,
48}
49
50impl DexExtended {
51    /// Creates a new [`DexExtended`] wrapper around a domain `Dex` object.
52    #[must_use]
53    pub fn new(dex: Dex) -> Self {
54        Self {
55            dex: Arc::new(dex),
56            parse_pool_created_event_fn: None,
57            parse_swap_event_fn: None,
58            parse_mint_event_fn: None,
59            parse_burn_event_fn: None,
60            convert_to_trade_data_fn: None,
61        }
62    }
63
64    /// Sets the function used to parse pool creation events for this Dex.
65    pub fn set_pool_created_event_parsing(
66        &mut self,
67        parse_pool_created_event: fn(Log) -> anyhow::Result<PoolCreatedEvent>,
68    ) {
69        self.parse_pool_created_event_fn = Some(parse_pool_created_event);
70    }
71
72    /// Sets the function used to parse swap events for this Dex.
73    pub fn set_swap_event_parsing(
74        &mut self,
75        parse_swap_event: fn(Log) -> anyhow::Result<SwapEvent>,
76    ) {
77        self.parse_swap_event_fn = Some(parse_swap_event);
78    }
79
80    /// Sets the function used to parse mint events for this Dex.
81    pub fn set_mint_event_parsing(
82        &mut self,
83        parse_mint_event: fn(Log) -> anyhow::Result<MintEvent>,
84    ) {
85        self.parse_mint_event_fn = Some(parse_mint_event);
86    }
87
88    /// Sets the function used to parse burn events for this Dex.
89    pub fn set_burn_event_parsing(
90        &mut self,
91        parse_burn_event: fn(Log) -> anyhow::Result<BurnEvent>,
92    ) {
93        self.parse_burn_event_fn = Some(parse_burn_event);
94    }
95
96    /// Sets the function used to convert trade data for this Dex.
97    pub fn set_convert_trade_data(
98        &mut self,
99        convert_trade_data: fn(
100            &Token,
101            &Token,
102            &SwapEvent,
103        ) -> anyhow::Result<(OrderSide, Quantity, Price)>,
104    ) {
105        self.convert_to_trade_data_fn = Some(convert_trade_data);
106    }
107
108    /// Parses a pool creation event log using this DEX's specific parsing function.
109    pub fn parse_pool_created_event(&self, log: Log) -> anyhow::Result<PoolCreatedEvent> {
110        if let Some(parse_pool_created_event_fn) = &self.parse_pool_created_event_fn {
111            parse_pool_created_event_fn(log)
112        } else {
113            anyhow::bail!(
114                "Parsing of pool created event in not defined in this dex: {}",
115                self.dex.name
116            )
117        }
118    }
119
120    /// Parses a swap event log using this DEX's specific parsing function.
121    pub fn parse_swap_event(&self, log: Log) -> anyhow::Result<SwapEvent> {
122        if let Some(parse_swap_event_fn) = &self.parse_swap_event_fn {
123            parse_swap_event_fn(log)
124        } else {
125            anyhow::bail!(
126                "Parsing of swap event in not defined in this dex: {}",
127                self.dex.name
128            )
129        }
130    }
131
132    /// Convert to trade data from a log using this DEX's specific parsing function.
133    pub fn convert_to_trade_data(
134        &self,
135        token0: &Token,
136        token1: &Token,
137        swap_event: &SwapEvent,
138    ) -> anyhow::Result<(OrderSide, Quantity, Price)> {
139        if let Some(convert_to_trade_data_fn) = &self.convert_to_trade_data_fn {
140            convert_to_trade_data_fn(token0, token1, swap_event)
141        } else {
142            anyhow::bail!(
143                "Converting to trade data is not defined in this dex: {}",
144                self.dex.name
145            )
146        }
147    }
148
149    /// Parses a mint event log using this DEX's specific parsing function.
150    pub fn parse_mint_event(&self, log: Log) -> anyhow::Result<MintEvent> {
151        if let Some(parse_mint_event_fn) = &self.parse_mint_event_fn {
152            parse_mint_event_fn(log)
153        } else {
154            anyhow::bail!(
155                "Parsing of mint event in not defined in this dex: {}",
156                self.dex.name
157            )
158        }
159    }
160
161    /// Parses a burn event log using this DEX's specific parsing function.
162    pub fn parse_burn_event(&self, log: Log) -> anyhow::Result<BurnEvent> {
163        if let Some(parse_burn_event_fn) = &self.parse_burn_event_fn {
164            parse_burn_event_fn(log)
165        } else {
166            anyhow::bail!(
167                "Parsing of burn event in not defined in this dex: {}",
168                self.dex.name
169            )
170        }
171    }
172}
173
174impl Deref for DexExtended {
175    type Target = Dex;
176
177    fn deref(&self) -> &Self::Target {
178        &self.dex
179    }
180}