1use std::any::Any;
2use std::cmp::Ordering;
3use std::fmt::{Debug, Display, Formatter};
4use std::hash::{Hash, Hasher};
5use std::ops::Deref;
6use std::sync::Arc;
7
8use crate::required_state::RequiredState;
9use crate::swap_direction::SwapDirection;
10use crate::PoolId;
11use alloy_primitives::{Address, Bytes, U256};
12use eyre::{eyre, ErrReport, Result};
13use kabu_defi_address_book::FactoryAddress;
14use kabu_evm_db::KabuDBError;
15use revm::DatabaseRef;
16use serde::{Deserialize, Serialize};
17use strum_macros::{Display, EnumIter, EnumString, VariantNames};
18
19pub fn get_protocol_by_factory(factory_address: Address) -> PoolProtocol {
20 if factory_address == FactoryAddress::UNISWAP_V2 {
21 PoolProtocol::UniswapV2
22 } else if factory_address == FactoryAddress::UNISWAP_V3 {
23 PoolProtocol::UniswapV3
24 } else if factory_address == FactoryAddress::PANCAKE_V3 {
25 PoolProtocol::PancakeV3
26 } else if factory_address == FactoryAddress::NOMISWAP {
27 PoolProtocol::NomiswapStable
28 } else if factory_address == FactoryAddress::ANTFARM {
29 PoolProtocol::AntFarm
30 } else if factory_address == FactoryAddress::SUSHISWAP_V2 {
31 PoolProtocol::Sushiswap
32 } else if factory_address == FactoryAddress::SUSHISWAP_V3 {
33 PoolProtocol::SushiswapV3
34 } else if factory_address == FactoryAddress::DOOARSWAP {
35 PoolProtocol::DooarSwap
36 } else if factory_address == FactoryAddress::SAFESWAP {
37 PoolProtocol::Safeswap
38 } else if factory_address == FactoryAddress::MINISWAP {
39 PoolProtocol::Miniswap
40 } else if factory_address == FactoryAddress::SHIBASWAP {
41 PoolProtocol::Shibaswap
42 } else if factory_address == FactoryAddress::MAVERICK {
43 PoolProtocol::Maverick
44 } else if factory_address == FactoryAddress::INTEGRAL {
45 PoolProtocol::Integral
46 } else {
47 PoolProtocol::Unknown
48 }
49}
50
51#[derive(Copy, Clone, Debug, PartialEq, Hash, Eq, EnumString, VariantNames, Display, Default, Deserialize, Serialize, EnumIter)]
52#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
53pub enum PoolClass {
54 #[default]
55 #[serde(rename = "unknown")]
56 #[strum(serialize = "unknown")]
57 Unknown,
58 #[serde(rename = "uniswap2")]
59 #[strum(serialize = "uniswap2")]
60 UniswapV2,
61 #[serde(rename = "uniswap3")]
62 #[strum(serialize = "uniswap3")]
63 UniswapV3,
64 #[serde(rename = "uniswap4")]
65 #[strum(serialize = "uniswap4")]
66 UniswapV4,
67 #[serde(rename = "maverick")]
68 #[strum(serialize = "maverick")]
69 Maverick,
70 #[serde(rename = "maverick2")]
71 #[strum(serialize = "maverick2")]
72 MaverickV2,
73 #[serde(rename = "pancake3")]
74 #[strum(serialize = "pancake3")]
75 PancakeV3,
76 #[serde(rename = "curve")]
77 #[strum(serialize = "curve")]
78 Curve,
79 #[serde(rename = "steth")]
80 #[strum(serialize = "steth")]
81 LidoStEth,
82 #[serde(rename = "wsteth")]
83 #[strum(serialize = "wsteth")]
84 LidoWstEth,
85 #[serde(rename = "rocketpool")]
86 #[strum(serialize = "rocketpool")]
87 RocketPool,
88 #[serde(rename = "balancer1")]
89 #[strum(serialize = "balancer1")]
90 BalancerV1,
91 #[serde(rename = "balancer2")]
92 #[strum(serialize = "balancer2")]
93 BalancerV2,
94 #[serde(rename = "custom")]
95 #[strum(serialize = "custom")]
96 Custom(u64),
97}
98
99#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
100pub enum PoolProtocol {
101 Unknown,
102 AaveV2,
103 AaveV3,
104 UniswapV2,
105 UniswapV2Like,
106 NomiswapStable,
107 Sushiswap,
108 SushiswapV3,
109 DooarSwap,
110 OgPepe,
111 AntFarm,
112 Safeswap,
113 Miniswap,
114 Shibaswap,
115 UniswapV3,
116 UniswapV3Like,
117 UniswapV4,
118 PancakeV3,
119 Integral,
120 Maverick,
121 MaverickV2,
122 Curve,
123 LidoStEth,
124 LidoWstEth,
125 RocketEth,
126 BalancerV1,
127 BalancerV2,
128 Custom(u64),
129}
130
131impl Display for PoolProtocol {
132 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
133 let protocol_name = match self {
134 Self::Unknown => "Unknown",
135 Self::AaveV2 => "AaveV2",
136 Self::AaveV3 => "AaveV3",
137 Self::UniswapV2 => "UniswapV2",
138 Self::UniswapV2Like => "UniswapV2Like",
139 Self::UniswapV3 => "UniswapV3",
140 Self::PancakeV3 => "PancakeV3",
141 Self::UniswapV4 => "UniswapV4",
142 Self::UniswapV3Like => "UniswapV3Like",
143 Self::NomiswapStable => "NomiswapStable",
144 Self::Sushiswap => "Sushiswap",
145 Self::SushiswapV3 => "SushiswapV3",
146 Self::DooarSwap => "Dooarswap",
147 Self::OgPepe => "OgPepe",
148 Self::AntFarm => "AntFarm",
149 Self::Miniswap => "Miniswap",
150 Self::Shibaswap => "Shibaswap",
151 Self::Safeswap => "Safeswap",
152 Self::Integral => "Integral",
153 Self::Maverick => "Maverick",
154 Self::MaverickV2 => "MaverickV2",
155 Self::Curve => "Curve",
156 Self::LidoWstEth => "WstEth",
157 Self::LidoStEth => "StEth",
158 Self::RocketEth => "RocketEth",
159 Self::BalancerV1 => "BalancerV1",
160 Self::BalancerV2 => "BalancerV2",
161 Self::Custom(x) => "Custom",
162 };
163 write!(f, "{protocol_name}")
164 }
165}
166
167pub struct PoolWrapper {
168 pub pool: Arc<dyn Pool>,
169}
170
171impl PartialOrd for PoolWrapper {
172 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
173 Some(self.cmp(other))
174 }
175}
176
177impl Eq for PoolWrapper {}
178
179impl Ord for PoolWrapper {
180 fn cmp(&self, other: &Self) -> Ordering {
181 self.get_pool_id().cmp(&other.get_pool_id())
182 }
183}
184
185impl Display for PoolWrapper {
186 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
187 write!(f, "{}@{}", self.get_protocol(), self.get_pool_id())
188 }
189}
190
191impl Debug for PoolWrapper {
192 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
193 write!(f, "{}@{}", self.get_protocol(), self.get_pool_id())
194 }
195}
196
197impl Hash for PoolWrapper {
198 fn hash<H: Hasher>(&self, state: &mut H) {
199 self.get_pool_id().hash(state)
200 }
201}
202
203impl PartialEq for PoolWrapper {
204 fn eq(&self, other: &Self) -> bool {
205 self.pool.get_pool_id() == other.pool.get_pool_id()
206 }
207}
208
209impl Clone for PoolWrapper {
210 fn clone(&self) -> Self {
211 Self { pool: self.pool.clone() }
212 }
213}
214
215impl Deref for PoolWrapper {
216 type Target = dyn Pool;
217
218 fn deref(&self) -> &Self::Target {
219 self.pool.deref()
220 }
221}
222
223impl AsRef<dyn Pool> for PoolWrapper {
224 fn as_ref(&self) -> &(dyn Pool + 'static) {
225 self.pool.as_ref()
226 }
227}
228
229impl PoolWrapper {
230 pub fn new(pool: Arc<dyn Pool>) -> Self {
231 PoolWrapper { pool }
232 }
233}
234
235impl<T: 'static + Pool> From<T> for PoolWrapper {
236 fn from(pool: T) -> Self {
237 Self { pool: Arc::new(pool) }
238 }
239}
240
241pub trait Pool: Sync + Send {
242 fn as_any(&self) -> &dyn Any;
243
244 fn get_class(&self) -> PoolClass;
245
246 fn get_protocol(&self) -> PoolProtocol;
247
248 fn get_address(&self) -> PoolId;
249
250 fn get_pool_id(&self) -> PoolId;
251
252 fn get_fee(&self) -> U256;
253
254 fn get_tokens(&self) -> Vec<Address>;
255
256 fn get_swap_directions(&self) -> Vec<SwapDirection>;
257
258 fn calculate_out_amount(
259 &self,
260 db: &dyn DatabaseRef<Error = KabuDBError>,
261 token_address_from: &Address,
262 token_address_to: &Address,
263 in_amount: U256,
264 ) -> Result<(U256, u64), ErrReport>;
265
266 fn calculate_in_amount(
268 &self,
269 db: &dyn DatabaseRef<Error = KabuDBError>,
270 token_address_from: &Address,
271 token_address_to: &Address,
272 out_amount: U256,
273 ) -> Result<(U256, u64), ErrReport>;
274
275 fn can_flash_swap(&self) -> bool;
276
277 fn can_calculate_in_amount(&self) -> bool;
278
279 fn get_abi_encoder(&self) -> Option<&dyn PoolAbiEncoder>;
280
281 fn get_read_only_cell_vec(&self) -> Vec<U256>;
282
283 fn get_state_required(&self) -> Result<RequiredState>;
284
285 fn is_native(&self) -> bool;
286
287 fn preswap_requirement(&self) -> PreswapRequirement;
288
289 fn get_pool_manager_cells(&self) -> Vec<(Address, Vec<U256>)> {
290 vec![]
291 }
292}
293
294pub struct DefaultAbiSwapEncoder {}
295
296impl PoolAbiEncoder for DefaultAbiSwapEncoder {}
297
298#[derive(Clone, Debug)]
299pub enum PreswapRequirement {
300 Unknown,
301 Transfer(Address),
302 Allowance,
303 Callback,
304 Base,
305}
306
307impl PartialEq for PreswapRequirement {
308 fn eq(&self, other: &Self) -> bool {
309 match (self, other) {
310 (PreswapRequirement::Unknown, PreswapRequirement::Unknown) => true,
311 (PreswapRequirement::Transfer(addr1), PreswapRequirement::Transfer(addr2)) => addr1 == addr2,
312 (PreswapRequirement::Allowance, PreswapRequirement::Allowance) => true,
313 (PreswapRequirement::Callback, PreswapRequirement::Callback) => true,
314 (PreswapRequirement::Base, PreswapRequirement::Base) => true,
315 _ => false,
316 }
317 }
318}
319
320impl PreswapRequirement {
321 pub fn address_or(&self, default_address: Address) -> Address {
322 match self {
323 PreswapRequirement::Transfer(address) => *address,
324 _ => default_address,
325 }
326 }
327 pub fn address(&self) -> Option<Address> {
328 match self {
329 PreswapRequirement::Transfer(address) => Some(*address),
330 _ => None,
331 }
332 }
333}
334
335pub trait PoolAbiEncoder: Send + Sync {
336 fn encode_swap_in_amount_provided(
337 &self,
338 _token_from_address: Address,
339 _token_to_address: Address,
340 _amount: U256,
341 _recipient: Address,
342 _payload: Bytes,
343 ) -> Result<Bytes> {
344 Err(eyre!("NOT_IMPLEMENTED"))
345 }
346 fn encode_swap_out_amount_provided(
347 &self,
348 _token_from_address: Address,
349 _token_to_address: Address,
350 _amount: U256,
351 _recipient: Address,
352 _payload: Bytes,
353 ) -> Result<Bytes> {
354 Err(eyre!("NOT_IMPLEMENTED"))
355 }
356
357 fn swap_in_amount_offset(&self, _token_from_address: Address, _token_to_address: Address) -> Option<u32> {
358 None
359 }
360 fn swap_out_amount_offset(&self, _token_from_address: Address, _token_to_address: Address) -> Option<u32> {
361 None
362 }
363 fn swap_out_amount_return_offset(&self, _token_from_address: Address, _token_to_address: Address) -> Option<u32> {
364 None
365 }
366 fn swap_in_amount_return_offset(&self, _token_from_address: Address, _token_to_address: Address) -> Option<u32> {
367 None
368 }
369 fn swap_out_amount_return_script(&self, _token_from_address: Address, _token_to_address: Address) -> Option<Bytes> {
370 None
371 }
372 fn swap_in_amount_return_script(&self, _token_from_address: Address, _token_to_address: Address) -> Option<Bytes> {
373 None
374 }
375}
376
377#[cfg(test)]
378mod tests {
379 use crate::PoolClass;
380
381 #[test]
382 fn test_strum() {
383 println!("{}", PoolClass::Unknown);
384 println!("{}", PoolClass::UniswapV2);
385 }
386}