pool_sync/pools/
mod.rs

1//! Core definitions for pool synchronization
2//!
3//! This module defines the core structures and traits used in the pool synchronization system.
4//! It includes enumerations for supported pool types, a unified `Pool` enum, and a trait for
5//! fetching and decoding pool creation events.
6
7use alloy::dyn_abi::DynSolType;
8use alloy::dyn_abi::DynSolValue;
9use alloy::primitives::{Address, Log};
10use pool_structures::balancer_v2_structure::BalancerV2Pool;
11use pool_structures::maverick_structure::MaverickPool;
12use pool_structures::tri_crypto_curve_structure::CurveTriCryptoPool;
13use pool_structures::two_crypto_curve_structure::CurveTwoCryptoPool;
14use pool_structures::v2_structure::UniswapV2Pool;
15use pool_structures::v3_structure::UniswapV3Pool;
16
17use serde::{Deserialize, Serialize};
18use std::fmt;
19
20use crate::chain::Chain;
21use crate::impl_pool_info;
22
23mod gen;
24pub mod pool_builder;
25pub mod pool_fetchers;
26pub mod pool_structures;
27
28/// Enumerates the supported pool types
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
30pub enum PoolType {
31    UniswapV2,
32    SushiSwapV2,
33    PancakeSwapV2,
34    UniswapV3,
35    SushiSwapV3,
36    PancakeSwapV3,
37    Aerodrome,
38    Slipstream,
39    BaseSwapV2,
40    BaseSwapV3,
41    AlienBaseV2,
42    AlienBaseV3,
43    MaverickV1,
44    MaverickV2,
45    CurveTwoCrypto,
46    CurveTriCrypto,
47    BalancerV2,
48    SwapBasedV2,
49    SwapBasedV3,
50    DackieSwapV2,
51    DackieSwapV3,
52}
53
54impl PoolType {
55    pub fn is_v2(&self) -> bool {
56        matches!(
57            self,
58            PoolType::UniswapV2
59                | PoolType::SushiSwapV2
60                | PoolType::PancakeSwapV2
61                | PoolType::Aerodrome
62                | PoolType::BaseSwapV2
63                | PoolType::SwapBasedV2
64                | PoolType::DackieSwapV2
65                | PoolType::AlienBaseV2
66        )
67    }
68
69    pub fn is_v3(&self) -> bool {
70        matches!(
71            self,
72            PoolType::UniswapV3
73                | PoolType::SushiSwapV3
74                | PoolType::PancakeSwapV3
75                | PoolType::Slipstream
76                | PoolType::BaseSwapV3
77                | PoolType::AlienBaseV3
78                | PoolType::SwapBasedV3
79                | PoolType::DackieSwapV3
80        )
81    }
82
83    pub fn is_maverick(&self) -> bool {
84        matches!(self, PoolType::MaverickV1 | PoolType::MaverickV2)
85    }
86
87    pub fn is_curve_two(&self) -> bool {
88        matches!(self, PoolType::CurveTwoCrypto)
89    }
90
91    pub fn is_curve_tri(&self) -> bool {
92        matches!(self, PoolType::CurveTriCrypto)
93    }
94
95    pub fn is_balancer(&self) -> bool {
96        matches!(self, PoolType::BalancerV2)
97    }
98
99    pub fn build_pool(&self, pool_data: &[DynSolValue]) -> Pool {
100        if self.is_v2() {
101            let pool = UniswapV2Pool::from(pool_data);
102            Pool::new_v2(*self, pool)
103        } else if self.is_v3() {
104            let pool = UniswapV3Pool::from(pool_data);
105            Pool::new_v3(*self, pool)
106        } else if self.is_maverick() {
107            let pool = MaverickPool::from(pool_data);
108            Pool::new_maverick(*self, pool)
109        } else if self.is_balancer() {
110            let pool = BalancerV2Pool::from(pool_data);
111            Pool::new_balancer(*self, pool)
112        } else if self.is_curve_two() {
113            let pool = CurveTwoCryptoPool::from(pool_data);
114            Pool::new_curve_two(*self, pool)
115        } else if self.is_curve_tri() {
116            let pool = CurveTriCryptoPool::from(pool_data);
117            Pool::new_curve_tri(*self, pool)
118        } else {
119            panic!("Invalid pool type");
120        }
121    }
122}
123
124/// Represents a populated pool from any of the supported protocols
125#[derive(Debug, Clone, Serialize, Deserialize)]
126pub enum Pool {
127    UniswapV2(UniswapV2Pool),
128    SushiSwapV2(UniswapV2Pool),
129    PancakeSwapV2(UniswapV2Pool),
130    BaseSwapV2(UniswapV2Pool),
131    AlienBaseV2(UniswapV2Pool),
132    SwapBasedV2(UniswapV2Pool),
133    DackieSwapV2(UniswapV2Pool),
134
135    Aerodrome(UniswapV2Pool),
136    Slipstream(UniswapV3Pool),
137
138    UniswapV3(UniswapV3Pool),
139    SushiSwapV3(UniswapV3Pool),
140    PancakeSwapV3(UniswapV3Pool),
141    BaseSwapV3(UniswapV3Pool),
142    AlienBaseV3(UniswapV3Pool),
143    SwapBasedV3(UniswapV3Pool),
144    DackieSwapV3(UniswapV3Pool),
145
146    MaverickV1(MaverickPool),
147    MaverickV2(MaverickPool),
148
149    CurveTwoCrypto(CurveTwoCryptoPool),
150    CurveTriCrypto(CurveTriCryptoPool),
151
152    BalancerV2(BalancerV2Pool),
153}
154
155impl Pool {
156    pub fn new_v2(pool_type: PoolType, pool: UniswapV2Pool) -> Self {
157        match pool_type {
158            PoolType::UniswapV2 => Pool::UniswapV2(pool),
159            PoolType::SushiSwapV2 => Pool::SushiSwapV2(pool),
160            PoolType::PancakeSwapV2 => Pool::PancakeSwapV2(pool),
161            PoolType::Aerodrome => Pool::Aerodrome(pool),
162            PoolType::BaseSwapV2 => Pool::BaseSwapV2(pool),
163            PoolType::SwapBasedV2 => Pool::SwapBasedV2(pool),
164            PoolType::DackieSwapV2 => Pool::DackieSwapV2(pool),
165            PoolType::AlienBaseV2 => Pool::AlienBaseV2(pool),
166            _ => panic!("Invalid pool type"),
167        }
168    }
169
170    pub fn new_v3(pool_type: PoolType, pool: UniswapV3Pool) -> Self {
171        match pool_type {
172            PoolType::UniswapV3 => Pool::UniswapV3(pool),
173            PoolType::SushiSwapV3 => Pool::SushiSwapV3(pool),
174            PoolType::PancakeSwapV3 => Pool::PancakeSwapV3(pool),
175            PoolType::Slipstream => Pool::Slipstream(pool),
176            PoolType::BaseSwapV3 => Pool::BaseSwapV3(pool),
177            PoolType::SwapBasedV3 => Pool::SwapBasedV3(pool),
178            PoolType::DackieSwapV3 => Pool::DackieSwapV3(pool),
179            PoolType::AlienBaseV3 => Pool::AlienBaseV3(pool),
180            _ => panic!("Invalid pool type"),
181        }
182    }
183
184    pub fn new_maverick(pool_type: PoolType, pool: MaverickPool) -> Self {
185        match pool_type {
186            PoolType::MaverickV1 => Pool::MaverickV1(pool),
187            PoolType::MaverickV2 => Pool::MaverickV2(pool),
188            _ => panic!("Invalid pool type"),
189        }
190    }
191
192    pub fn new_curve_two(pool_type: PoolType, pool: CurveTwoCryptoPool) -> Self {
193        match pool_type {
194            PoolType::CurveTwoCrypto => Pool::CurveTwoCrypto(pool),
195            _ => panic!("Invalid pool type"),
196        }
197    }
198
199    pub fn new_curve_tri(pool_type: PoolType, pool: CurveTriCryptoPool) -> Self {
200        match pool_type {
201            PoolType::CurveTriCrypto => Pool::CurveTriCrypto(pool),
202            _ => panic!("Invalid pool type"),
203        }
204    }
205
206    pub fn new_balancer(pool_type: PoolType, pool: BalancerV2Pool) -> Self {
207        match pool_type {
208            PoolType::BalancerV2 => Pool::BalancerV2(pool),
209            _ => panic!("Invalid pool type"),
210        }
211    }
212
213    pub fn is_v2(&self) -> bool {
214        match self {
215            Pool::UniswapV2(_) => true,
216            Pool::SushiSwapV2(_) => true,
217            Pool::PancakeSwapV2(_) => true,
218            Pool::Aerodrome(_) => true,
219            Pool::BaseSwapV2(_) => true,
220            Pool::AlienBaseV2(_) => true,
221            Pool::SwapBasedV2(_) => true,
222            Pool::DackieSwapV2(_) => true,
223            _ => false,
224        }
225    }
226
227    pub fn is_v3(&self) -> bool {
228        match self {
229            Pool::UniswapV3(_) => true,
230            Pool::SushiSwapV3(_) => true,
231            Pool::PancakeSwapV3(_) => true,
232            Pool::Slipstream(_) => true,
233            Pool::BaseSwapV3(_) => true,
234            Pool::AlienBaseV3(_) => true,
235            Pool::SwapBasedV3(_) => true,
236            Pool::DackieSwapV3(_) => true,
237            _ => false,
238        }
239    }
240
241    pub fn is_maverick(&self) -> bool {
242        match self {
243            Pool::MaverickV1(_) => true,
244            Pool::MaverickV2(_) => true,
245            _ => false,
246        }
247    }
248
249    pub fn is_curve_two(&self) -> bool {
250        match self {
251            Pool::CurveTwoCrypto(_) => true,
252            _ => false,
253        }
254    }
255
256    pub fn is_curve_tri(&self) -> bool {
257        match self {
258            Pool::CurveTriCrypto(_) => true,
259            _ => false,
260        }
261    }
262
263    pub fn is_balancer(&self) -> bool {
264        match self {
265            Pool::BalancerV2(_) => true,
266            _ => false,
267        }
268    }
269
270    pub fn get_v2(&self) -> Option<&UniswapV2Pool> {
271        match self {
272            Pool::UniswapV2(pool) => Some(pool),
273            Pool::SushiSwapV2(pool) => Some(pool),
274            Pool::PancakeSwapV2(pool) => Some(pool),
275            Pool::Aerodrome(pool) => Some(pool),
276            Pool::BaseSwapV2(pool) => Some(pool),
277            Pool::SwapBasedV2(pool) => Some(pool),
278            Pool::DackieSwapV2(pool) => Some(pool),
279            Pool::AlienBaseV2(pool) => Some(pool),
280            _ => None,
281        }
282    }
283
284    pub fn get_v3(&self) -> Option<&UniswapV3Pool> {
285        match self {
286            Pool::UniswapV3(pool) => Some(pool),
287            Pool::SushiSwapV3(pool) => Some(pool),
288            Pool::PancakeSwapV3(pool) => Some(pool),
289            Pool::Slipstream(pool) => Some(pool),
290            Pool::BaseSwapV3(pool) => Some(pool),
291            Pool::AlienBaseV3(pool) => Some(pool),
292            Pool::SwapBasedV3(pool) => Some(pool),
293            Pool::DackieSwapV3(pool) => Some(pool),
294            _ => None,
295        }
296    }
297
298    pub fn get_maverick(&self) -> Option<&MaverickPool> {
299        match self {
300            Pool::MaverickV1(pool) => Some(pool),
301            Pool::MaverickV2(pool) => Some(pool),
302            _ => None,
303        }
304    }
305
306    pub fn get_curve_two(&self) -> Option<&CurveTwoCryptoPool> {
307        match self {
308            Pool::CurveTwoCrypto(pool) => Some(pool),
309            _ => None,
310        }
311    }
312
313    pub fn get_curve_tri(&self) -> Option<&CurveTriCryptoPool> {
314        match self {
315            Pool::CurveTriCrypto(pool) => Some(pool),
316            _ => None,
317        }
318    }
319
320    pub fn get_balancer(&self) -> Option<&BalancerV2Pool> {
321        match self {
322            Pool::BalancerV2(pool) => Some(pool),
323            _ => None,
324        }
325    }
326
327    pub fn get_v2_mut(&mut self) -> Option<&mut UniswapV2Pool> {
328        match self {
329            Pool::UniswapV2(pool) => Some(pool),
330            Pool::SushiSwapV2(pool) => Some(pool),
331            Pool::PancakeSwapV2(pool) => Some(pool),
332            Pool::Aerodrome(pool) => Some(pool),
333            Pool::BaseSwapV2(pool) => Some(pool),
334            Pool::AlienBaseV2(pool) => Some(pool),
335            Pool::SwapBasedV2(pool) => Some(pool),
336            Pool::DackieSwapV2(pool) => Some(pool),
337            _ => None,
338        }
339    }
340
341    pub fn get_v3_mut(&mut self) -> Option<&mut UniswapV3Pool> {
342        match self {
343            Pool::UniswapV3(pool) => Some(pool),
344            Pool::SushiSwapV3(pool) => Some(pool),
345            Pool::PancakeSwapV3(pool) => Some(pool),
346            Pool::Slipstream(pool) => Some(pool),
347            Pool::BaseSwapV3(pool) => Some(pool),
348            Pool::AlienBaseV3(pool) => Some(pool),
349            Pool::SwapBasedV3(pool) => Some(pool),
350            Pool::DackieSwapV3(pool) => Some(pool),
351            _ => None,
352        }
353    }
354
355    pub fn get_maverick_mut(&mut self) -> Option<&mut MaverickPool> {
356        match self {
357            Pool::MaverickV1(pool) => Some(pool),
358            Pool::MaverickV2(pool) => Some(pool),
359            _ => None,
360        }
361    }
362
363    pub fn get_curve_two_mut(&mut self) -> Option<&mut CurveTwoCryptoPool> {
364        match self {
365            Pool::CurveTwoCrypto(pool) => Some(pool),
366            _ => None,
367        }
368    }
369
370    pub fn get_curve_tri_mut(&mut self) -> Option<&mut CurveTriCryptoPool> {
371        match self {
372            Pool::CurveTriCrypto(pool) => Some(pool),
373            _ => None,
374        }
375    }
376
377    pub fn get_balancer_mut(&mut self) -> Option<&mut BalancerV2Pool> {
378        match self {
379            Pool::BalancerV2(pool) => Some(pool),
380            _ => None,
381        }
382    }
383
384    pub fn is_valid(&self) -> bool {
385        self.address() != Address::ZERO
386            && self.token0_address() != Address::ZERO
387            && self.token1_address() != Address::ZERO
388    }
389
390    fn update_token0_name(pool: &mut Pool, token0: String) {
391        if pool.is_v2() {
392            let pool = pool.get_v2_mut().unwrap();
393            pool.token0_name = token0;
394        } else if pool.is_v3() {
395            let pool = pool.get_v3_mut().unwrap();
396            pool.token0_name = token0;
397        } else if pool.is_curve_two() {
398            let pool = pool.get_curve_two_mut().unwrap();
399            pool.token0_name = token0;
400        } else if pool.is_curve_tri() {
401            let pool = pool.get_curve_tri_mut().unwrap();
402            pool.token0_name = token0;
403        } else if pool.is_balancer() {
404            let pool = pool.get_balancer_mut().unwrap();
405            pool.token0_name = token0;
406        } else if pool.is_maverick() {
407            let pool = pool.get_maverick_mut().unwrap();
408            pool.token0_name = token0;
409        }
410    }
411
412    pub fn update_token1_name(pool: &mut Pool, token1: String) {
413        if pool.is_v2() {
414            let pool = pool.get_v2_mut().unwrap();
415            pool.token1_name = token1;
416        } else if pool.is_v3() {
417            let pool = pool.get_v3_mut().unwrap();
418            pool.token1_name = token1;
419        } else if pool.is_curve_two() {
420            let pool = pool.get_curve_two_mut().unwrap();
421            pool.token1_name = token1;
422        } else if pool.is_curve_tri() {
423            let pool = pool.get_curve_tri_mut().unwrap();
424            pool.token1_name = token1;
425        } else if pool.is_balancer() {
426            let pool = pool.get_balancer_mut().unwrap();
427            pool.token1_name = token1;
428        } else if pool.is_maverick() {
429            let pool = pool.get_maverick_mut().unwrap();
430            pool.token1_name = token1;
431        }
432    }
433}
434
435impl fmt::Display for PoolType {
436    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
437        write!(f, "{:?}", self)
438    }
439}
440
441// Implement the PoolInfo trait for all pool variants that are supported
442impl_pool_info!(
443    Pool,
444    UniswapV2,
445    SushiSwapV2,
446    PancakeSwapV2,
447    UniswapV3,
448    SushiSwapV3,
449    PancakeSwapV3,
450    Aerodrome,
451    Slipstream,
452    BaseSwapV2,
453    BaseSwapV3,
454    AlienBaseV2,
455    AlienBaseV3,
456    MaverickV1,
457    MaverickV2,
458    CurveTwoCrypto,
459    CurveTriCrypto,
460    BalancerV2,
461    SwapBasedV2,
462    SwapBasedV3,
463    DackieSwapV2,
464    DackieSwapV3
465);
466
467/// Defines common functionality for fetching and decoding pool creation events
468///
469/// This trait provides a unified interface for different pool types to implement
470/// their specific logic for identifying and parsing pool creation events.
471pub trait PoolFetcher: Send + Sync {
472    /// Returns the type of pool this fetcher is responsible for
473    fn pool_type(&self) -> PoolType;
474
475    /// Returns the factory address for the given chain
476    fn factory_address(&self, chain: Chain) -> Address;
477
478    /// Returns the event signature for pool creation
479    fn pair_created_signature(&self) -> &str;
480
481    /// Attempts to create a `Pool` instance from a log entry
482    fn log_to_address(&self, log: &Log) -> Address;
483
484    /// Get the DynSolType for the pool
485    fn get_pool_repr(&self) -> DynSolType;
486}
487
488/// Defines common methods that are used to access information about the pools
489pub trait PoolInfo {
490    fn address(&self) -> Address;
491    fn token0_address(&self) -> Address;
492    fn token1_address(&self) -> Address;
493    fn token0_name(&self) -> String;
494    fn token1_name(&self) -> String;
495    fn token0_decimals(&self) -> u8;
496    fn token1_decimals(&self) -> u8;
497    fn pool_type(&self) -> PoolType;
498    fn fee(&self) -> u32;
499    fn stable(&self) -> bool;
500}
501
502/* 
503pub trait V2PoolInfo {
504    fn token0_reserves(&self) -> U128;
505    fn token1_reserves(&self) -> U128;
506}
507
508pub trait V3PoolInfo {
509    fn fee(&self) -> u32;
510    fn tick_spacing(&self) -> i32;
511    fn tick_bitmap(&self) -> HashMap<i16, U256>;
512    fn ticks(&self) -> HashMap<i32, TickInfo>;
513}
514*/
515
516/// Macro for generating getter methods for all of the suppored pools
517#[macro_export]
518macro_rules! impl_pool_info {
519    ($enum_name:ident, $($variant:ident),+) => {
520        impl PoolInfo for $enum_name {
521            fn address(&self) -> Address {
522                match self {
523                    $(
524                        $enum_name::$variant(pool) => pool.address,
525
526                    )+
527                }
528            }
529
530            fn token0_address(&self) -> Address {
531                match self {
532                    $(
533                        $enum_name::$variant(pool) => pool.token0,
534                    )+
535                }
536            }
537
538            fn token1_address(&self) -> Address {
539                match self {
540                    $(
541                        $enum_name::$variant(pool) => pool.token1,
542                    )+
543                }
544            }
545
546            fn token0_name(&self) -> String {
547                match self {
548                    $(
549                        $enum_name::$variant(pool) => pool.token0_name.clone(),
550                    )+
551                }
552            }
553            fn token1_name(&self) -> String {
554                match self {
555                    $(
556                        $enum_name::$variant(pool) => pool.token1_name.clone(),
557                    )+
558                }
559            }
560
561            fn token0_decimals(&self) -> u8 {
562                match self {
563                    $(
564                        $enum_name::$variant(pool) => pool.token0_decimals,
565                    )+
566                }
567            }
568            fn token1_decimals(&self) -> u8 {
569                match self {
570                    $(
571                        $enum_name::$variant(pool) => pool.token1_decimals,
572                    )+
573                }
574            }
575
576            fn pool_type(&self) -> PoolType {
577                match self {
578                    $(
579                        $enum_name::$variant(_) => PoolType::$variant,
580                    )+
581                }
582            }
583
584            fn fee(&self) -> u32 {
585                match self {
586                    Pool::UniswapV3(pool) | Pool::SushiSwapV3(pool) | Pool::PancakeSwapV3(pool) | Pool::Slipstream(pool) => pool.fee,
587                    _ => 0
588                }
589            }
590
591            fn stable(&self) -> bool {
592                match self {
593                    Pool::Aerodrome(pool) => pool.stable.unwrap(),
594                    _=> false
595                }
596            }
597        }
598    };
599}