kabu_defi_pools/loaders/
uniswap2.rs

1use crate::protocols::{UniswapV2Protocol, fetch_uni2_factory};
2use crate::{UniswapV2Pool, 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::uniswap2::IUniswapV2Pair::IUniswapV2PairEvents;
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;
17
18pool_loader!(UniswapV2PoolLoader);
19
20impl<P, N, LDT> PoolLoader<P, N, LDT> for UniswapV2PoolLoader<P, N, LDT>
21where
22    N: Network,
23    P: Provider<N> + Clone + 'static,
24    LDT: Send + Sync + 'static,
25{
26    fn get_pool_class_by_log(&self, log_entry: &Log) -> Option<(PoolId, PoolClass)> {
27        let log_entry: Option<Log> = Log::new(log_entry.address, log_entry.data.topics().to_vec(), log_entry.data.data.clone());
28        match log_entry {
29            Some(log_entry) => match IUniswapV2PairEvents::decode_log(&log_entry) {
30                Ok(event) => match event.data {
31                    IUniswapV2PairEvents::Swap(_)
32                    | IUniswapV2PairEvents::Mint(_)
33                    | IUniswapV2PairEvents::Burn(_)
34                    | IUniswapV2PairEvents::Sync(_) => Some((PoolId::Address(log_entry.address), PoolClass::UniswapV2)),
35                    _ => None,
36                },
37                Err(_) => None,
38            },
39            None => None,
40        }
41    }
42
43    fn fetch_pool_by_id<'a>(&'a self, pool_id: PoolId) -> Pin<Box<dyn Future<Output = eyre::Result<PoolWrapper>> + Send + 'a>> {
44        Box::pin(async move {
45            if let Some(provider) = self.provider.clone() {
46                self.fetch_pool_by_id_from_provider(pool_id, provider).await
47            } else {
48                Err(eyre!("NO_PROVIDER"))
49            }
50        })
51    }
52
53    fn fetch_pool_by_id_from_provider<'a>(
54        &'a self,
55        pool_id: PoolId,
56        provider: P,
57    ) -> Pin<Box<dyn Future<Output = eyre::Result<PoolWrapper>> + Send + 'a>> {
58        Box::pin(async move {
59            let pool_address = match pool_id {
60                PoolId::Address(addr) => addr,
61                PoolId::B256(_) => return Err(eyre!("UniswapV2 pools only support Address-based pool IDs")),
62            };
63            let factory_address = fetch_uni2_factory(provider.clone(), pool_address).await?;
64            match get_protocol_by_factory(factory_address) {
65                PoolProtocol::NomiswapStable
66                | PoolProtocol::Miniswap
67                | PoolProtocol::Integral
68                | PoolProtocol::Safeswap
69                | PoolProtocol::AntFarm => Err(eyre!("POOL_PROTOCOL_NOT_SUPPORTED")),
70                _ => Ok(PoolWrapper::new(Arc::new(UniswapV2Pool::fetch_pool_data(provider, pool_address).await?))),
71            }
72        })
73    }
74
75    fn fetch_pool_by_id_from_evm(&self, pool_id: PoolId, db: &dyn DatabaseRef<Error = KabuDBError>) -> eyre::Result<PoolWrapper> {
76        let pool_address = match pool_id {
77            PoolId::Address(addr) => addr,
78            PoolId::B256(_) => return Err(eyre!("UniswapV2 pools only support Address-based pool IDs")),
79        };
80        Ok(PoolWrapper::new(Arc::new(UniswapV2Pool::fetch_pool_data_evm(db, &EvmEnv::default(), pool_address)?)))
81    }
82
83    fn is_code(&self, code: &Bytes) -> bool {
84        UniswapV2Protocol::is_code(code)
85    }
86
87    fn protocol_loader(&self) -> eyre::Result<Pin<Box<dyn Stream<Item = (PoolId, PoolClass)> + Send>>> {
88        Err(eyre!("NOT_IMPLEMENTED"))
89    }
90}