tycho_execution/encoding/evm/swap_encoder/
swap_encoder_registry.rs1use 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#[derive(Clone)]
28pub struct SwapEncoderRegistry {
29 chain: Chain,
30 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 pub fn new_with_defaults(chain: Chain) -> Result<Self, EncodingError> {
41 Self::new(chain).add_default_encoders(None)
42 }
43
44 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 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}