use crate::contracts::{IAlgebraFactory, IUniswapV2Factory, IUniswapV3Factory, IVeloPoolFactory};
use crate::erc4626::ERC4626Pool;
use crate::erc4626::VerioIP;
use crate::lb::LBPool;
use crate::v2::UniswapV2Pool;
use crate::v3::UniswapV3Pool;
use alloy::sol_types::SolEvent;
use alloy::{
primitives::{Address, FixedBytes, U256},
rpc::types::Log,
};
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::any::Any;
pub type Topic = FixedBytes<32>;
pub trait PoolTypeTrait: Send + Sync {
fn pool_type(&self) -> PoolType;
}
pub trait PoolInterface: std::fmt::Debug + Send + Sync + PoolTypeTrait + EventApplicable {
fn calculate_output(&self, token_in: &Address, amount_in: U256) -> Result<U256>;
fn calculate_input(&self, token_out: &Address, amount_out: U256) -> Result<U256>;
fn apply_swap(&mut self, token_in: &Address, amount_in: U256, amount_out: U256) -> Result<()>;
fn address(&self) -> Address;
fn tokens(&self) -> (Address, Address);
fn token0(&self) -> Address {
self.tokens().0
}
fn token1(&self) -> Address {
self.tokens().1
}
fn fee(&self) -> f64;
fn fee_raw(&self) -> u64;
fn id(&self) -> String;
fn contains_token(&self, token: &Address) -> bool;
fn clone_box(&self) -> Box<dyn PoolInterface + Send + Sync>;
fn log_summary(&self) -> String;
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
impl dyn PoolInterface + Send + Sync {
pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
self.as_any().downcast_ref::<T>()
}
pub fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
self.as_any_mut().downcast_mut::<T>()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum PoolType {
UniswapV2,
UniswapV3,
ERC4626(ERC4626Pool),
TraderJoeLB,
}
impl std::fmt::Display for PoolType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
PoolType::UniswapV2 => write!(f, "uniswap_v2"),
PoolType::UniswapV3 => write!(f, "uniswap_v3"),
PoolType::ERC4626(ERC4626Pool::VerioIP) => write!(f, "verio_ip"),
PoolType::TraderJoeLB => write!(f, "traderjoe_liquidity_book"),
}
}
}
impl From<PoolType> for String {
fn from(pool_type: PoolType) -> Self {
pool_type.to_string()
}
}
impl Default for PoolType {
fn default() -> Self {
PoolType::UniswapV2
}
}
impl PoolType {
pub fn topics(&self) -> Vec<FixedBytes<32>> {
match self {
Self::UniswapV2 => UniswapV2Pool::topics(),
Self::UniswapV3 => UniswapV3Pool::topics(),
Self::ERC4626(ERC4626Pool::VerioIP) => VerioIP::topics(),
Self::TraderJoeLB => LBPool::topics(),
}
}
pub fn profitable_topics(&self) -> Vec<FixedBytes<32>> {
match self {
Self::UniswapV2 => UniswapV2Pool::profitable_topics(),
Self::UniswapV3 => UniswapV3Pool::profitable_topics(),
Self::ERC4626(ERC4626Pool::VerioIP) => VerioIP::profitable_topics(),
Self::TraderJoeLB => LBPool::profitable_topics(),
}
}
}
pub trait EventApplicable {
fn apply_log(&mut self, event: &Log) -> Result<()>;
}
pub trait TopicList {
fn topics() -> Vec<Topic>;
fn profitable_topics() -> Vec<Topic>;
}
pub const POOL_CREATED_TOPICS: &[Topic] = &[
IUniswapV2Factory::PairCreated::SIGNATURE_HASH,
IUniswapV3Factory::PoolCreated::SIGNATURE_HASH,
IAlgebraFactory::Pool::SIGNATURE_HASH,
IVeloPoolFactory::PoolCreated::SIGNATURE_HASH,
];