waterpump-evm-pool-sdk 0.1.0

EVM pool SDK — viewers, infusers, harvesters, swappers for Uniswap V3/V4, PancakeSwap, Slipstream, Shadow, Algebra
Documentation
/// Macro to generate two-hop swapper helper methods
/// Assumes the struct has:
/// - pool_a() method returning &(PoolKey, Address)
/// - pool_b() method returning &(PoolKey, Address)
/// - intermediate_token() method returning Result<Currency>
#[macro_export]
macro_rules! impl_two_hop_swapper_methods {
    ($struct_name:ident) => {
        impl $struct_name {
            /// Determine the two-hop path tokens using is_to_b
            ///
            /// This function determines the token path for a two-hop swap based on the
            /// swap direction. The `is_to_b` parameter indicates the overall swap
            /// direction (towards pool_b).
            ///
            /// # Arguments
            ///
            /// * `is_to_b` - If true, swap direction is towards pool_b (input -> pool_a
            ///   -> pool_b -> output) If false, swap direction is reversed (output ->
            ///   pool_b -> pool_a -> input)
            ///
            /// # Returns
            ///
            /// Returns a tuple `(token0, token1, token2)` where:
            /// - `token0` is the input token (first token in the path)
            /// - `token1` is the intermediate token (shared between the two pools)
            /// - `token2` is the output token (last token in the path)
            ///
            /// # Example
            ///
            /// ```ignore
            /// let (input_token, intermediate_token, output_token) = swapper.determine_two_hop_path_tokens(true)?;
            /// ```
            pub fn determine_two_hop_path_tokens(
                &self,
                is_to_pool_b: bool,
            ) -> anyhow::Result<(
                uniswap_sdk_core::prelude::Currency,
                uniswap_sdk_core::prelude::Currency,
                uniswap_sdk_core::prelude::Currency,
            )> {
                $crate::pool_swappers::common::determine_two_hop_path_tokens(
                    &self.pool_a().0,
                    &self.pool_b().0,
                    is_to_pool_b,
                )
            }

            /// Get the swap directions for both pools based on the overall swap
            /// direction
            ///
            /// This function determines if each pool swaps from tokenA to tokenB based
            /// on the overall swap direction.
            ///
            /// # Arguments
            ///
            /// * `is_to_b` - The overall swap direction (towards pool_b)
            ///
            /// # Returns
            ///
            /// Returns a tuple `(pool_a_is_to_b, pool_b_is_to_b)` where:
            /// - `pool_a_is_to_b`: true if pool_a swaps from tokenA -> tokenB, false if
            ///   swapping tokenB -> tokenA
            /// - `pool_b_is_to_b`: true if pool_b swaps from tokenA -> tokenB, false if
            ///   swapping tokenB -> tokenA
            pub fn get_swap_directions(&self, is_to_pool_b: bool) -> (bool, bool) {
                let (token0, token1, _) = self
                    .determine_two_hop_path_tokens(is_to_pool_b)
                    .expect("Failed to determine two-hop path tokens");

                let pool_a = self.pool_a().0.clone();
                let pool_b = self.pool_b().0.clone();

                // token0 is the input token for pool_a
                // If token0 is pool_a's token_a, we're swapping A -> B (is_to_b = true)
                let pool_a_is_to_b = if pool_a.token_b == token1 {
                    if pool_a.token_a == token0 {
                        true
                    } else {
                        false
                    }
                } else {
                    if pool_a.token_b == token0 {
                        false
                    } else {
                        true
                    }
                };

                // token1 is the intermediate token (input for pool_b)
                // If token1 is pool_b's token_a, we're swapping A -> B (is_to_b = true)
                let pool_b_is_to_b = if pool_b.token_a == token1 {
                    if pool_b.token_b == token0 {
                        false
                    } else {
                        true
                    }
                } else {
                    if pool_b.token_a == token0 {
                        true
                    } else {
                        false
                    }
                };

                (pool_a_is_to_b, pool_b_is_to_b)
            }

            /// Get the is_to_intermediate flags for both pools based on overall swap
            /// direction
            ///
            /// This function determines whether each pool's swap is going towards the
            /// intermediate token based on the overall swap direction (is_to_b).
            ///
            /// # Arguments
            ///
            /// * `is_to_b` - The overall swap direction (towards pool_b)
            ///
            /// # Returns
            ///
            /// Returns a tuple `(pool_a_is_to_intermediate, pool_b_is_to_intermediate)`
            /// where:
            /// - `pool_a_is_to_intermediate`: true if pool_a's output token is the
            ///   intermediate token
            /// - `pool_b_is_to_intermediate`: always false (pool_b receives
            ///   intermediate as input)
            pub fn get_intermediate_flags(&self, is_to_pool_b: bool) -> (bool, bool) {
                let (token0, token1, _) = self
                    .determine_two_hop_path_tokens(is_to_pool_b)
                    .expect("Failed to determine two-hop path tokens");

                let pool_a_is_to_intermediate = if token1 == self.pool_a().0.token_b {
                    token0 == self.pool_a().0.token_a
                } else {
                    token0 == self.pool_a().0.token_b
                };

                let pool_b_is_to_intermediate = !pool_a_is_to_intermediate;

                (pool_a_is_to_intermediate, pool_b_is_to_intermediate)
            }

            /// Get currency0 (the non-intermediate token in pool_a)
            ///
            /// This is an internal helper function that returns the token in pool_a
            /// that is not the intermediate token.
            pub fn currency0_internal(&self) -> uniswap_sdk_core::prelude::Currency {
                let intermediate =
                    self.intermediate_token().expect("Failed to get intermediate token");
                if self.pool_a().0.token_a == intermediate {
                    self.pool_a().0.token_b.clone()
                } else {
                    self.pool_a().0.token_a.clone()
                }
            }

            /// Get currency1 (the non-intermediate token in pool_b)
            ///
            /// This is an internal helper function that returns the token in pool_b
            /// that is not the intermediate token.
            pub fn currency1_internal(&self) -> uniswap_sdk_core::prelude::Currency {
                let intermediate =
                    self.intermediate_token().expect("Failed to get intermediate token");
                if self.pool_b().0.token_a == intermediate {
                    self.pool_b().0.token_b.clone()
                } else {
                    self.pool_b().0.token_a.clone()
                }
            }
        }
    };
}