Skip to main content

tycho_execution/encoding/evm/swap_encoder/
swap_encoder_registry.rs

1use std::{collections::HashMap, str::FromStr};
2
3use tycho_common::{models::Chain, Bytes};
4
5use crate::encoding::{
6    errors::EncodingError,
7    evm::{
8        constants::{DEFAULT_EXECUTORS_JSON, PROTOCOL_SPECIFIC_CONFIG},
9        swap_encoder::{
10            balancer_v2::BalancerV2SwapEncoder, balancer_v3::BalancerV3SwapEncoder,
11            bebop::BebopSwapEncoder, curve::CurveSwapEncoder, ekubo::EkuboSwapEncoder,
12            ekubo_v3::EkuboV3SwapEncoder, erc_4626::ERC4626SwapEncoder,
13            etherfi::EtherfiSwapEncoder, fluid_v1::FluidV1SwapEncoder,
14            hashflow::HashflowSwapEncoder, maverick_v2::MaverickV2SwapEncoder,
15            rocketpool::RocketpoolSwapEncoder, slipstreams::SlipstreamsSwapEncoder,
16            uniswap_v2::UniswapV2SwapEncoder, uniswap_v3::UniswapV3SwapEncoder,
17            uniswap_v4::UniswapV4SwapEncoder, weth::WethSwapEncoder,
18        },
19    },
20    swap_encoder::SwapEncoder,
21};
22
23/// Registry containing all supported `SwapEncoders`.
24#[derive(Clone)]
25pub struct SwapEncoderRegistry {
26    chain: Chain,
27    /// A hashmap containing the protocol system as a key and the `SwapEncoder` as a value.
28    encoders: HashMap<String, Box<dyn SwapEncoder>>,
29}
30
31impl SwapEncoderRegistry {
32    pub fn new(chain: Chain) -> Self {
33        Self { chain, encoders: HashMap::new() }
34    }
35
36    /// Populates the registry with the default `SwapEncoders` for the given blockchain by
37    /// parsing the executors' addresses in the file at the given path.
38    pub fn add_default_encoders(
39        mut self,
40        executors_addresses: Option<String>,
41    ) -> Result<Self, EncodingError> {
42        let config_str = if let Some(addresses) = executors_addresses {
43            addresses
44        } else {
45            DEFAULT_EXECUTORS_JSON.to_string()
46        };
47        let config: HashMap<Chain, HashMap<String, String>> = serde_json::from_str(&config_str)?;
48        let executors = config
49            .get(&self.chain)
50            .ok_or(EncodingError::FatalError("No executors found for chain".to_string()))?;
51
52        let protocol_specific_config: HashMap<Chain, HashMap<String, HashMap<String, String>>> =
53            serde_json::from_str(PROTOCOL_SPECIFIC_CONFIG)?;
54        let protocol_specific_config = protocol_specific_config
55            .get(&self.chain)
56            .ok_or(EncodingError::FatalError(
57                "No protocol specific config found for chain".to_string(),
58            ))?;
59        for (protocol, executor_address) in executors {
60            let encoder = self.create_encoder(
61                protocol,
62                Bytes::from_str(executor_address).map_err(|_| {
63                    EncodingError::FatalError(format!(
64                        "Invalid executor address for protocol {}",
65                        protocol
66                    ))
67                })?,
68                protocol_specific_config
69                    .get(protocol)
70                    .cloned(),
71            )?;
72            self.encoders
73                .insert(protocol.to_string(), encoder);
74        }
75        Ok(self)
76    }
77
78    /// Adds an encoder to the registry, replacing any existing encoder for the same protocol.
79    pub fn register_encoder(mut self, protocol: &str, encoder: Box<dyn SwapEncoder>) -> Self {
80        self.encoders
81            .insert(protocol.to_string(), encoder);
82        self
83    }
84
85    #[allow(clippy::borrowed_box)]
86    pub fn get_encoder(&self, protocol_system: &str) -> Option<&Box<dyn SwapEncoder>> {
87        self.encoders.get(protocol_system)
88    }
89
90    fn create_encoder(
91        &self,
92        protocol_system: &str,
93        executor_address: Bytes,
94        config: Option<HashMap<String, String>>,
95    ) -> Result<Box<dyn SwapEncoder>, EncodingError> {
96        match protocol_system {
97            "uniswap_v2" => {
98                Ok(Box::new(UniswapV2SwapEncoder::new(executor_address, self.chain, config)?))
99            }
100            "sushiswap_v2" => {
101                Ok(Box::new(UniswapV2SwapEncoder::new(executor_address, self.chain, config)?))
102            }
103            "pancakeswap_v2" => {
104                Ok(Box::new(UniswapV2SwapEncoder::new(executor_address, self.chain, config)?))
105            }
106            "vm:balancer_v2" => {
107                Ok(Box::new(BalancerV2SwapEncoder::new(executor_address, self.chain, config)?))
108            }
109            "uniswap_v3" => {
110                Ok(Box::new(UniswapV3SwapEncoder::new(executor_address, self.chain, config)?))
111            }
112            "pancakeswap_v3" => {
113                Ok(Box::new(UniswapV3SwapEncoder::new(executor_address, self.chain, config)?))
114            }
115            "uniswap_v4" => {
116                Ok(Box::new(UniswapV4SwapEncoder::new(executor_address, self.chain, config)?))
117            }
118            "ekubo_v2" => {
119                Ok(Box::new(EkuboSwapEncoder::new(executor_address, self.chain, config)?))
120            }
121            "ekubo_v3" => {
122                Ok(Box::new(EkuboV3SwapEncoder::new(executor_address, self.chain, config)?))
123            }
124            "vm:curve" => {
125                Ok(Box::new(CurveSwapEncoder::new(executor_address, self.chain, config)?))
126            }
127            "vm:maverick_v2" => {
128                Ok(Box::new(MaverickV2SwapEncoder::new(executor_address, self.chain, config)?))
129            }
130            "vm:balancer_v3" => {
131                Ok(Box::new(BalancerV3SwapEncoder::new(executor_address, self.chain, config)?))
132            }
133            "rfq:bebop" => {
134                Ok(Box::new(BebopSwapEncoder::new(executor_address, self.chain, config)?))
135            }
136            "rfq:hashflow" => {
137                Ok(Box::new(HashflowSwapEncoder::new(executor_address, self.chain, config)?))
138            }
139            "fluid_v1" => {
140                Ok(Box::new(FluidV1SwapEncoder::new(executor_address, self.chain, config)?))
141            }
142            "aerodrome_slipstreams" => {
143                Ok(Box::new(SlipstreamsSwapEncoder::new(executor_address, self.chain, config)?))
144            }
145            "rocketpool" => {
146                Ok(Box::new(RocketpoolSwapEncoder::new(executor_address, self.chain, config)?))
147            }
148            "erc4626" => {
149                Ok(Box::new(ERC4626SwapEncoder::new(executor_address, self.chain, config)?))
150            }
151            "velodrome_slipstreams" => {
152                Ok(Box::new(SlipstreamsSwapEncoder::new(executor_address, self.chain, config)?))
153            }
154            "weth" => Ok(Box::new(WethSwapEncoder::new(executor_address, self.chain, config)?)),
155            "etherfi" => {
156                Ok(Box::new(EtherfiSwapEncoder::new(executor_address, self.chain, config)?))
157            }
158            _ => Err(EncodingError::FatalError(format!(
159                "Unknown protocol system: {}",
160                protocol_system
161            ))),
162        }
163    }
164}