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 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#[derive(Clone)]
25pub struct SwapEncoderRegistry {
26 chain: Chain,
27 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 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 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}