kabu_defi_pools/loaders/
uniswap2.rs

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