use crate::chain::Chain;
use crate::impl_pool_info;
use alloy::primitives::{Address, Log};
use alloy::providers::Provider;
use alloy::transports::Transport;
use alloy::network::Network;
use pool_structure::{UniswapV2Pool, UniswapV3Pool};
use serde::{Deserialize, Serialize};
use std::{fmt, sync::Arc};
use alloy::primitives::U128;
mod pool_structure;
mod gen;
mod v2_builder;
mod v3_builder;
pub mod uniswap;
pub mod sushiswap;
pub mod pancake_swap;
pub mod aerodome;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum PoolType {
UniswapV2,
SushiSwapV2,
PancakeSwapV2,
UniswapV3,
SushiSwapV3,
PancakeSwapV3,
Aerodome,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Pool {
UniswapV2(UniswapV2Pool),
SushiSwapV2(UniswapV2Pool),
PancakeSwapV2(UniswapV2Pool),
UniswapV3(UniswapV3Pool),
SushiSwapV3(UniswapV3Pool),
PancakeSwapV3(UniswapV3Pool),
Aerodome(UniswapV2Pool),
}
impl Pool {
pub fn new_v2(pool_type: PoolType, pool: UniswapV2Pool) -> Self {
match pool_type {
PoolType::UniswapV2 => Pool::UniswapV2(pool),
PoolType::SushiSwapV2 => Pool::SushiSwapV2(pool),
PoolType::PancakeSwapV2 => Pool::PancakeSwapV2(pool),
PoolType::Aerodome => Pool::Aerodome(pool),
_ => panic!("Invalid pool type")
}
}
pub fn new_v3(pool_type: PoolType, pool: UniswapV3Pool) -> Self {
match pool_type {
PoolType::UniswapV3 => Pool::UniswapV3(pool),
PoolType::SushiSwapV3 => Pool::SushiSwapV3(pool),
PoolType::PancakeSwapV3 => Pool::PancakeSwapV3(pool),
_ => panic!("Invalid pool type")
}
}
}
impl fmt::Display for PoolType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
}
}
impl_pool_info!(
Pool,
UniswapV2,
SushiSwapV2,
PancakeSwapV2,
UniswapV3,
SushiSwapV3,
PancakeSwapV3,
Aerodome
);
pub trait PoolFetcher: Send + Sync {
fn pool_type(&self) -> PoolType;
fn factory_address(&self, chain: Chain) -> Address;
fn pair_created_signature(&self) -> &str;
fn log_to_address(&self, log: &Log) -> Address;
}
impl PoolType {
pub async fn build_pools_from_addrs<P, T, N>(
&self,
provider: Arc<P>,
addresses: Vec<Address>,
) -> Vec<Pool>
where
P: Provider<T, N> + Sync + 'static,
T: Transport + Sync + Clone,
N: Network
{
match self {
PoolType::UniswapV2 => v2_builder::build_pools(provider, addresses, PoolType::UniswapV2).await,
PoolType::SushiSwapV2 => v2_builder::build_pools(provider, addresses, PoolType::SushiSwapV2).await,
PoolType::PancakeSwapV2 => v2_builder::build_pools(provider, addresses, PoolType::PancakeSwapV2).await,
PoolType::UniswapV3 => v3_builder::build_pools(provider, addresses, PoolType::UniswapV3).await,
PoolType::SushiSwapV3 => v3_builder::build_pools(provider, addresses, PoolType::SushiSwapV3).await,
PoolType::PancakeSwapV3 => v3_builder::build_pools(provider, addresses, PoolType::PancakeSwapV3).await,
PoolType::Aerodome => v2_builder::build_pools(provider, addresses, PoolType::Aerodome).await,
}
}
}
pub trait PoolInfo {
fn address(&self) -> Address;
fn token0_address(&self) -> Address;
fn token1_address(&self) -> Address;
fn token0_name(&self) -> String;
fn token1_name(&self) -> String;
fn token0_decimals(&self) -> u8;
fn token1_decimals(&self) -> u8;
fn pool_type(&self) -> PoolType;
fn reserves(&self) -> (U128, U128);
}
#[macro_export]
macro_rules! impl_pool_info {
($enum_name:ident, $($variant:ident),+) => {
impl PoolInfo for $enum_name {
fn address(&self) -> Address {
match self {
$(
$enum_name::$variant(pool) => pool.address,
)+
}
}
fn token0_address(&self) -> Address {
match self {
$(
$enum_name::$variant(pool) => pool.token0,
)+
}
}
fn token1_address(&self) -> Address {
match self {
$(
$enum_name::$variant(pool) => pool.token1,
)+
}
}
fn token0_name(&self) -> String {
match self {
$(
$enum_name::$variant(pool) => pool.token0_name.clone(),
)+
}
}
fn token1_name(&self) -> String {
match self {
$(
$enum_name::$variant(pool) => pool.token1_name.clone(),
)+
}
}
fn token0_decimals(&self) -> u8 {
match self {
$(
$enum_name::$variant(pool) => pool.token0_decimals,
)+
}
}
fn token1_decimals(&self) -> u8 {
match self {
$(
$enum_name::$variant(pool) => pool.token1_decimals,
)+
}
}
fn pool_type(&self) -> PoolType {
match self {
$(
$enum_name::$variant(_) => PoolType::$variant,
)+
}
}
fn reserves(&self) -> (U128, U128) {
match self {
$enum_name::UniswapV2(pool) => (pool.token0_reserves, pool.token1_reserves),
$enum_name::SushiSwapV2(pool) => (pool.token0_reserves, pool.token1_reserves),
$enum_name::PancakeSwapV2(pool) => (pool.token0_reserves, pool.token1_reserves),
$enum_name::Aerodome(pool) => (pool.token0_reserves, pool.token1_reserves),
$enum_name::UniswapV3(pool) => (pool.liquidity.into(), pool.liquidity.into()),
$enum_name::SushiSwapV3(pool) => (pool.liquidity.into(), pool.liquidity.into()),
$enum_name::PancakeSwapV3(pool) => (pool.liquidity.into(), pool.liquidity.into()),
}
}
}
};
}