use std::{ops::Deref, sync::Arc};
use hypersync_client::simple_types::Log;
use nautilus_model::{
defi::{
dex::{Dex, SharedDex},
token::Token,
},
enums::OrderSide,
types::{Price, Quantity},
};
use crate::events::{
burn::BurnEvent, collect::CollectEvent, flash::FlashEvent, initialize::InitializeEvent,
mint::MintEvent, pool_created::PoolCreatedEvent, swap::SwapEvent,
};
type ConvertTradeDataFn =
fn(&Token, &Token, &SwapEvent) -> anyhow::Result<(OrderSide, Quantity, Price)>;
#[derive(Debug, Clone)]
pub struct DexExtended {
pub dex: SharedDex,
pub parse_pool_created_event_fn: Option<fn(Log) -> anyhow::Result<PoolCreatedEvent>>,
pub parse_initialize_event_fn: Option<fn(SharedDex, Log) -> anyhow::Result<InitializeEvent>>,
pub parse_swap_event_fn: Option<fn(SharedDex, Log) -> anyhow::Result<SwapEvent>>,
pub parse_mint_event_fn: Option<fn(SharedDex, Log) -> anyhow::Result<MintEvent>>,
pub parse_burn_event_fn: Option<fn(SharedDex, Log) -> anyhow::Result<BurnEvent>>,
pub parse_collect_event_fn: Option<fn(SharedDex, Log) -> anyhow::Result<CollectEvent>>,
pub parse_flash_event_fn: Option<fn(SharedDex, Log) -> anyhow::Result<FlashEvent>>,
pub convert_to_trade_data_fn: Option<ConvertTradeDataFn>,
}
impl DexExtended {
#[must_use]
pub fn new(dex: Dex) -> Self {
Self {
dex: Arc::new(dex),
parse_pool_created_event_fn: None,
parse_initialize_event_fn: None,
parse_swap_event_fn: None,
parse_mint_event_fn: None,
parse_burn_event_fn: None,
parse_collect_event_fn: None,
convert_to_trade_data_fn: None,
parse_flash_event_fn: None,
}
}
pub fn set_pool_created_event_parsing(
&mut self,
parse_pool_created_event: fn(Log) -> anyhow::Result<PoolCreatedEvent>,
) {
self.parse_pool_created_event_fn = Some(parse_pool_created_event);
}
pub fn set_initialize_event_parsing(
&mut self,
parse_initialize_event: fn(SharedDex, Log) -> anyhow::Result<InitializeEvent>,
) {
self.parse_initialize_event_fn = Some(parse_initialize_event);
}
pub fn set_swap_event_parsing(
&mut self,
parse_swap_event: fn(SharedDex, Log) -> anyhow::Result<SwapEvent>,
) {
self.parse_swap_event_fn = Some(parse_swap_event);
}
pub fn set_mint_event_parsing(
&mut self,
parse_mint_event: fn(SharedDex, Log) -> anyhow::Result<MintEvent>,
) {
self.parse_mint_event_fn = Some(parse_mint_event);
}
pub fn set_burn_event_parsing(
&mut self,
parse_burn_event: fn(SharedDex, Log) -> anyhow::Result<BurnEvent>,
) {
self.parse_burn_event_fn = Some(parse_burn_event);
}
pub fn set_collect_event_parsing(
&mut self,
parse_collect_event: fn(SharedDex, Log) -> anyhow::Result<CollectEvent>,
) {
self.parse_collect_event_fn = Some(parse_collect_event);
}
pub fn set_flash_event_parsing(
&mut self,
parse_flash_event: fn(SharedDex, Log) -> anyhow::Result<FlashEvent>,
) {
self.parse_flash_event_fn = Some(parse_flash_event);
}
pub fn set_convert_trade_data(&mut self, convert_trade_data: ConvertTradeDataFn) {
self.convert_to_trade_data_fn = Some(convert_trade_data);
}
pub fn parse_pool_created_event(&self, log: Log) -> anyhow::Result<PoolCreatedEvent> {
if let Some(parse_pool_created_event_fn) = &self.parse_pool_created_event_fn {
parse_pool_created_event_fn(log)
} else {
anyhow::bail!(
"Parsing of pool created event in not defined in this dex: {}:{}",
self.dex.chain,
self.dex.name,
)
}
}
pub fn parse_swap_event(&self, log: Log) -> anyhow::Result<SwapEvent> {
if let Some(parse_swap_event_fn) = &self.parse_swap_event_fn {
parse_swap_event_fn(self.dex.clone(), log)
} else {
anyhow::bail!(
"Parsing of swap event in not defined in this dex: {}:{}",
self.dex.chain,
self.dex.name
)
}
}
pub fn convert_to_trade_data(
&self,
token0: &Token,
token1: &Token,
swap_event: &SwapEvent,
) -> anyhow::Result<(OrderSide, Quantity, Price)> {
if let Some(convert_to_trade_data_fn) = &self.convert_to_trade_data_fn {
convert_to_trade_data_fn(token0, token1, swap_event)
} else {
anyhow::bail!(
"Converting to trade data is not defined in this dex: {}:{}",
self.dex.chain,
self.dex.name
)
}
}
pub fn parse_mint_event(&self, log: Log) -> anyhow::Result<MintEvent> {
if let Some(parse_mint_event_fn) = &self.parse_mint_event_fn {
parse_mint_event_fn(self.dex.clone(), log)
} else {
anyhow::bail!(
"Parsing of mint event in not defined in this dex: {}:{}",
self.dex.chain,
self.dex.name
)
}
}
pub fn parse_burn_event(&self, log: Log) -> anyhow::Result<BurnEvent> {
if let Some(parse_burn_event_fn) = &self.parse_burn_event_fn {
parse_burn_event_fn(self.dex.clone(), log)
} else {
anyhow::bail!(
"Parsing of burn event in not defined in this dex: {}",
self.dex.name
)
}
}
pub fn needs_initialization(&self) -> bool {
self.dex.initialize_event.is_some()
}
pub fn parse_initialize_event(&self, log: Log) -> anyhow::Result<InitializeEvent> {
if let Some(parse_initialize_event_fn) = &self.parse_initialize_event_fn {
parse_initialize_event_fn(self.dex.clone(), log)
} else {
anyhow::bail!(
"Parsing of initialize event in not defined in this dex: {}",
self.dex.name
)
}
}
pub fn parse_collect_event(&self, log: Log) -> anyhow::Result<CollectEvent> {
if let Some(parse_collect_event_fn) = &self.parse_collect_event_fn {
parse_collect_event_fn(self.dex.clone(), log)
} else {
anyhow::bail!(
"Parsing of collect event in not defined in this dex: {}:{}",
self.dex.chain,
self.dex.name
)
}
}
}
impl Deref for DexExtended {
type Target = Dex;
fn deref(&self) -> &Self::Target {
&self.dex
}
}