kabu_types_entities/
pool.rs

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    // returns (in_amount, gas_used)
267    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}