kabu_defi_pools/loaders/
uniswap3.rs

1use crate::protocols::{UniswapV3Protocol, fetch_uni3_factory};
2use crate::{MaverickPool, PancakeV3Pool, UniswapV3Pool, pool_loader};
3use alloy::primitives::{Bytes, Log};
4use alloy::sol_types::SolEventInterface;
5use alloy_evm::EvmEnv;
6use eyre::eyre;
7use futures::Stream;
8use kabu_defi_abi::uniswap3::IUniswapV3Pool::IUniswapV3PoolEvents;
9use kabu_evm_db::KabuDBError;
10use kabu_types_market::PoolClass;
11use kabu_types_market::{PoolId, PoolLoader, PoolProtocol, PoolWrapper, get_protocol_by_factory};
12use reth_ethereum_primitives::EthPrimitives;
13use revm::DatabaseRef;
14use std::future::Future;
15use std::pin::Pin;
16use std::sync::Arc;
17use tracing::error;
18
19pool_loader!(UniswapV3PoolLoader);
20
21impl<P, N, LDT> PoolLoader<P, N, LDT> for UniswapV3PoolLoader<P, N, LDT>
22where
23    N: Network,
24    P: Provider<N> + Clone + 'static,
25    LDT: Send + Sync + 'static,
26{
27    fn get_pool_class_by_log(&self, log_entry: &Log) -> Option<(PoolId, PoolClass)> {
28        let log_entry: Option<Log> = Log::new(log_entry.address, log_entry.data.topics().to_vec(), log_entry.data.data.clone());
29        match log_entry {
30            Some(log_entry) => match IUniswapV3PoolEvents::decode_log(&log_entry) {
31                Ok(event) => match event.data {
32                    IUniswapV3PoolEvents::Swap(_)
33                    | IUniswapV3PoolEvents::Mint(_)
34                    | IUniswapV3PoolEvents::Burn(_)
35                    | IUniswapV3PoolEvents::Initialize(_) => Some((PoolId::Address(log_entry.address), PoolClass::UniswapV3)),
36                    _ => None,
37                },
38                Err(_) => None,
39            },
40            None => None,
41        }
42    }
43
44    fn fetch_pool_by_id<'a>(&'a self, pool_id: PoolId) -> Pin<Box<dyn Future<Output = eyre::Result<PoolWrapper>> + Send + 'a>> {
45        Box::pin(async move {
46            if let Some(provider) = self.provider.clone() {
47                self.fetch_pool_by_id_from_provider(pool_id, provider).await
48            } else {
49                Err(eyre!("NO_PROVIDER"))
50            }
51        })
52    }
53
54    fn fetch_pool_by_id_from_provider<'a>(
55        &'a self,
56        pool_id: PoolId,
57        provider: P,
58    ) -> Pin<Box<dyn Future<Output = eyre::Result<PoolWrapper>> + Send + 'a>> {
59        Box::pin(async move {
60            let pool_address = match pool_id {
61                PoolId::Address(addr) => addr,
62                PoolId::B256(_) => return Err(eyre!("UniswapV3 pools only support Address-based pool IDs")),
63            };
64
65            let factory_address_result = fetch_uni3_factory(provider.clone(), pool_address).await;
66            match factory_address_result {
67                Ok(factory_address) => match get_protocol_by_factory(factory_address) {
68                    PoolProtocol::PancakeV3 => {
69                        Ok(PoolWrapper::new(Arc::new(PancakeV3Pool::fetch_pool_data(provider.clone(), pool_address).await?)))
70                    }
71                    PoolProtocol::Maverick => {
72                        Ok(PoolWrapper::new(Arc::new(MaverickPool::fetch_pool_data(provider.clone(), pool_address).await?)))
73                    }
74                    _ => Ok(PoolWrapper::new(Arc::new(UniswapV3Pool::fetch_pool_data(provider.clone(), pool_address).await?))),
75                },
76                Err(e) => {
77                    error!("Error fetching factory address at {:#20x}: {}", pool_address, e);
78                    Err(eyre!("CANNOT_GET_FACTORY_ADDRESS"))
79                }
80            }
81        })
82    }
83
84    fn fetch_pool_by_id_from_evm(&self, pool_id: PoolId, db: &dyn DatabaseRef<Error = KabuDBError>) -> eyre::Result<PoolWrapper> {
85        let pool_address = match pool_id {
86            PoolId::Address(addr) => addr,
87            PoolId::B256(_) => return Err(eyre!("UniswapV3 pools only support Address-based pool IDs")),
88        };
89        Ok(PoolWrapper::new(Arc::new(UniswapV3Pool::fetch_pool_data_evm(db, &EvmEnv::default(), pool_address)?)))
90    }
91
92    fn is_code(&self, code: &Bytes) -> bool {
93        UniswapV3Protocol::is_code(code)
94    }
95
96    fn protocol_loader(&self) -> eyre::Result<Pin<Box<dyn Stream<Item = (PoolId, PoolClass)> + Send>>> {
97        Err(eyre!("NOT_IMPLEMENTED"))
98    }
99}