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, curve::CurveSwapEncoder,
12 ekubo::EkuboSwapEncoder, ekubo_v3::EkuboV3SwapEncoder, erc_4626::ERC4626SwapEncoder,
13 etherfi::EtherfiSwapEncoder, fluid_v1::FluidV1SwapEncoder,
14 hashflow::HashflowSwapEncoder, liquidity_party::LiquidityPartySwapEncoder,
15 liquorice::LiquoriceSwapEncoder, maverick_v2::MaverickV2SwapEncoder,
16 rocketpool::RocketpoolSwapEncoder, slipstreams::SlipstreamsSwapEncoder,
17 uniswap_v2::UniswapV2SwapEncoder, uniswap_v3::UniswapV3SwapEncoder,
18 uniswap_v4::UniswapV4SwapEncoder, weth::WethSwapEncoder,
19 },
20 },
21 swap_encoder::SwapEncoder,
22};
23
24#[derive(Clone)]
26pub struct SwapEncoderRegistry {
27 chain: Chain,
28 encoders: HashMap<String, Box<dyn SwapEncoder>>,
30}
31
32impl SwapEncoderRegistry {
33 pub fn new(chain: Chain) -> Self {
34 Self { chain, encoders: HashMap::new() }
35 }
36
37 pub fn new_with_defaults(chain: Chain) -> Result<Self, EncodingError> {
39 Self::new(chain).add_default_encoders(None)
40 }
41
42 pub fn add_default_encoders(
45 mut self,
46 executors_addresses: Option<String>,
47 ) -> Result<Self, EncodingError> {
48 let config_str = if let Some(addresses) = executors_addresses {
49 addresses
50 } else {
51 DEFAULT_EXECUTORS_JSON.to_string()
52 };
53 let config: HashMap<Chain, HashMap<String, String>> = serde_json::from_str(&config_str)?;
54 let executors = config
55 .get(&self.chain)
56 .ok_or(EncodingError::FatalError("No executors found for chain".to_string()))?;
57
58 let protocol_specific_config: HashMap<Chain, HashMap<String, HashMap<String, String>>> =
59 serde_json::from_str(PROTOCOL_SPECIFIC_CONFIG)?;
60 let protocol_specific_config = protocol_specific_config
61 .get(&self.chain)
62 .ok_or(EncodingError::FatalError(
63 "No protocol specific config found for chain".to_string(),
64 ))?;
65 for (protocol, executor_address) in executors {
66 let encoder = self.create_encoder(
67 protocol,
68 Bytes::from_str(executor_address).map_err(|_| {
69 EncodingError::FatalError(format!(
70 "Invalid executor address for protocol {}",
71 protocol
72 ))
73 })?,
74 protocol_specific_config
75 .get(protocol)
76 .cloned(),
77 )?;
78 self.encoders
79 .insert(protocol.to_string(), encoder);
80 }
81 Ok(self)
82 }
83
84 pub fn register_encoder(mut self, protocol: &str, encoder: Box<dyn SwapEncoder>) -> Self {
86 self.encoders
87 .insert(protocol.to_string(), encoder);
88 self
89 }
90
91 #[allow(clippy::borrowed_box)]
92 pub fn get_encoder(&self, protocol_system: &str) -> Option<&Box<dyn SwapEncoder>> {
93 self.encoders.get(protocol_system)
94 }
95
96 fn create_encoder(
97 &self,
98 protocol_system: &str,
99 executor_address: Bytes,
100 config: Option<HashMap<String, String>>,
101 ) -> Result<Box<dyn SwapEncoder>, EncodingError> {
102 match protocol_system {
103 "uniswap_v2" | "sushiswap_v2" | "pancakeswap_v2" | "quickswap_v2" => {
104 Ok(Box::new(UniswapV2SwapEncoder::new(executor_address, self.chain, config)?))
105 }
106 "aerodrome_v1" => {
107 Ok(Box::new(AerodromeV1SwapEncoder::new(executor_address, self.chain, config)?))
108 }
109 "vm:balancer_v2" => {
110 Ok(Box::new(BalancerV2SwapEncoder::new(executor_address, self.chain, config)?))
111 }
112 "uniswap_v3" | "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 "rfq:liquorice" => {
140 Ok(Box::new(LiquoriceSwapEncoder::new(executor_address, self.chain, config)?))
141 }
142 "fluid_v1" => {
143 Ok(Box::new(FluidV1SwapEncoder::new(executor_address, self.chain, config)?))
144 }
145 "vm:liquidityparty" => {
146 Ok(Box::new(LiquidityPartySwapEncoder::new(executor_address, self.chain, config)?))
147 }
148 "aerodrome_slipstreams" => {
149 Ok(Box::new(SlipstreamsSwapEncoder::new(executor_address, self.chain, config)?))
150 }
151 "rocketpool" => {
152 Ok(Box::new(RocketpoolSwapEncoder::new(executor_address, self.chain, config)?))
153 }
154 "erc4626" => {
155 Ok(Box::new(ERC4626SwapEncoder::new(executor_address, self.chain, config)?))
156 }
157 "velodrome_slipstreams" => {
158 Ok(Box::new(SlipstreamsSwapEncoder::new(executor_address, self.chain, config)?))
159 }
160 "weth" => Ok(Box::new(WethSwapEncoder::new(executor_address, self.chain, config)?)),
161 "etherfi" => {
162 Ok(Box::new(EtherfiSwapEncoder::new(executor_address, self.chain, config)?))
163 }
164 _ => Err(EncodingError::FatalError(format!(
165 "Unknown protocol system: {}",
166 protocol_system
167 ))),
168 }
169 }
170}