kabu_execution_multicaller/pool_abi_encoder/
abi_encoder.rs

1use crate::pool_abi_encoder::pools::{
2    CurveProtocolAbiEncoder, MaverickProtocolAbiEncoder, PancakeV3ProtocolAbiEncoder, UniswapV2ProtocolAbiEncoder,
3    UniswapV3ProtocolAbiEncoder,
4};
5use crate::pool_abi_encoder::ProtocolAbiSwapEncoderTrait;
6use alloy_primitives::{Address, Bytes, U256};
7use eyre::OptionExt;
8use kabu_types_entities::{Pool, PoolClass};
9use std::collections::HashMap;
10use std::sync::Arc;
11
12#[derive(Clone)]
13pub struct ProtocolABIEncoderV2 {
14    pool_classes: HashMap<PoolClass, Arc<dyn ProtocolAbiSwapEncoderTrait>>,
15}
16
17impl Default for ProtocolABIEncoderV2 {
18    fn default() -> Self {
19        let pool_classes: HashMap<PoolClass, Arc<dyn ProtocolAbiSwapEncoderTrait>> = [
20            (PoolClass::UniswapV3, Arc::new(UniswapV3ProtocolAbiEncoder) as Arc<dyn ProtocolAbiSwapEncoderTrait>),
21            (PoolClass::UniswapV2, Arc::new(UniswapV2ProtocolAbiEncoder) as Arc<dyn ProtocolAbiSwapEncoderTrait>),
22            (PoolClass::Maverick, Arc::new(MaverickProtocolAbiEncoder) as Arc<dyn ProtocolAbiSwapEncoderTrait>),
23            (PoolClass::PancakeV3, Arc::new(PancakeV3ProtocolAbiEncoder) as Arc<dyn ProtocolAbiSwapEncoderTrait>),
24            (PoolClass::Curve, Arc::new(CurveProtocolAbiEncoder) as Arc<dyn ProtocolAbiSwapEncoderTrait>),
25        ]
26        .into_iter()
27        .collect();
28
29        Self { pool_classes }
30    }
31}
32
33impl ProtocolABIEncoderV2 {}
34
35impl ProtocolAbiSwapEncoderTrait for ProtocolABIEncoderV2 {
36    fn encode_swap_in_amount_provided(
37        &self,
38        pool: &dyn Pool,
39        token_from_address: Address,
40        token_to_address: Address,
41        amount: U256,
42        recipient: Address,
43        payload: Bytes,
44    ) -> eyre::Result<Bytes> {
45        self.pool_classes.get(&pool.get_class()).ok_or_eyre("CLASS_NOT_SUPPORTED")?.encode_swap_in_amount_provided(
46            pool,
47            token_from_address,
48            token_to_address,
49            amount,
50            recipient,
51            payload,
52        )
53    }
54
55    fn encode_swap_out_amount_provided(
56        &self,
57        pool: &dyn Pool,
58        token_from_address: Address,
59        token_to_address: Address,
60        amount: U256,
61        recipient: Address,
62        payload: Bytes,
63    ) -> eyre::Result<Bytes> {
64        self.pool_classes.get(&pool.get_class()).ok_or_eyre("CLASS_NOT_SUPPORTED")?.encode_swap_out_amount_provided(
65            pool,
66            token_from_address,
67            token_to_address,
68            amount,
69            recipient,
70            payload,
71        )
72    }
73
74    fn swap_in_amount_offset(&self, pool: &dyn Pool, token_from_address: Address, token_to_address: Address) -> Option<u32> {
75        self.pool_classes
76            .get(&pool.get_class())
77            .and_then(|encoder| encoder.swap_in_amount_offset(pool, token_from_address, token_to_address))
78    }
79
80    fn swap_out_amount_offset(&self, pool: &dyn Pool, token_from_address: Address, token_to_address: Address) -> Option<u32> {
81        self.pool_classes
82            .get(&pool.get_class())
83            .and_then(|encoder| encoder.swap_out_amount_offset(pool, token_from_address, token_to_address))
84    }
85
86    fn swap_in_amount_return_offset(&self, pool: &dyn Pool, token_from_address: Address, token_to_address: Address) -> Option<u32> {
87        self.pool_classes
88            .get(&pool.get_class())
89            .and_then(|encoder| encoder.swap_in_amount_return_offset(pool, token_from_address, token_to_address))
90    }
91    fn swap_out_amount_return_offset(&self, pool: &dyn Pool, token_from_address: Address, token_to_address: Address) -> Option<u32> {
92        self.pool_classes
93            .get(&pool.get_class())
94            .and_then(|encoder| encoder.swap_out_amount_return_offset(pool, token_from_address, token_to_address))
95    }
96
97    fn swap_in_amount_return_script(&self, pool: &dyn Pool, token_from_address: Address, token_to_address: Address) -> Option<Bytes> {
98        self.pool_classes
99            .get(&pool.get_class())
100            .and_then(|encoder| encoder.swap_in_amount_return_script(pool, token_from_address, token_to_address))
101    }
102    fn swap_out_amount_return_script(&self, pool: &dyn Pool, token_from_address: Address, token_to_address: Address) -> Option<Bytes> {
103        self.pool_classes
104            .get(&pool.get_class())
105            .and_then(|encoder| encoder.swap_out_amount_return_script(pool, token_from_address, token_to_address))
106    }
107}
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112    use kabu_defi_pools::UniswapV3Pool;
113    use kabu_types_entities::PreswapRequirement;
114
115    #[test]
116    fn test_default() {
117        let abi_encoder_v2 = ProtocolABIEncoderV2::default();
118        assert_eq!(abi_encoder_v2.pool_classes.len(), 5);
119    }
120
121    #[test]
122    fn test_preswap_requirement() {
123        let uni3 = UniswapV3Pool::new(Address::random());
124
125        let pr = uni3.preswap_requirement();
126
127        assert_eq!(pr, PreswapRequirement::Callback)
128    }
129}