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