From 84b773c0796e434106ab7a934a5b8c57a011a412 Mon Sep 17 00:00:00 2001 From: Shuhui Luo <107524008+shuhuiluo@users.noreply.github.com> Date: Mon, 23 Sep 2024 00:35:35 -0700 Subject: [PATCH] refactor: currency traits and implementations (#82) * refactor: currency traits and implementations Streamline trait implementations for `Currency` and `NativeCurrency` by removing redundant methods and consolidating logic. Adjust various currency-related entities (`Ether`, `Token`) to align with these changes, ensuring consistency and reducing code duplication. * refactor: implement currency traits using macros Consolidated the `Currency` trait implementations using macros for `Ether`, `Token`, and `CurrencyLike` types. This reduces code duplication and improves maintainability. The macros now handle trait method definitions for multiple types. --- Cargo.toml | 2 +- src/entities/base_currency.rs | 68 +++++++++++++---------- src/entities/currency.rs | 5 +- src/entities/ether.rs | 42 +++++++------- src/entities/fractions/currency_amount.rs | 4 +- src/entities/native_currency.rs | 4 +- src/entities/token.rs | 39 ++++++------- 7 files changed, 85 insertions(+), 79 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 358ccff..4a0338e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "uniswap-sdk-core" -version = "2.2.0" +version = "2.3.0" edition = "2021" authors = ["malik ", "Shuhui Luo "] description = "The Uniswap SDK Core in Rust provides essential functionality for interacting with the Uniswap decentralized exchange" diff --git a/src/entities/base_currency.rs b/src/entities/base_currency.rs index 8224905..3b34302 100644 --- a/src/entities/base_currency.rs +++ b/src/entities/base_currency.rs @@ -23,34 +23,42 @@ pub trait BaseCurrency { fn name(&self) -> Option<&String>; } -impl BaseCurrency for CurrencyLike { - #[inline] - fn is_native(&self) -> bool { - IS_NATIVE - } - - #[inline] - fn is_token(&self) -> bool { - !IS_NATIVE - } - - #[inline] - fn chain_id(&self) -> ChainId { - self.chain_id - } - - #[inline] - fn decimals(&self) -> u8 { - self.decimals - } - - #[inline] - fn symbol(&self) -> Option<&String> { - self.symbol.as_ref() - } - - #[inline] - fn name(&self) -> Option<&String> { - self.name.as_ref() - } +macro_rules! impl_base_currency { + ($($currency:ty),*) => { + $( + impl BaseCurrency for $currency { + #[inline] + fn is_native(&self) -> bool { + IS_NATIVE + } + + #[inline] + fn is_token(&self) -> bool { + !IS_NATIVE + } + + #[inline] + fn chain_id(&self) -> ChainId { + self.chain_id + } + + #[inline] + fn decimals(&self) -> u8 { + self.decimals + } + + #[inline] + fn symbol(&self) -> Option<&String> { + self.symbol.as_ref() + } + + #[inline] + fn name(&self) -> Option<&String> { + self.name.as_ref() + } + } + )* + }; } + +impl_base_currency!(CurrencyLike, &CurrencyLike); diff --git a/src/entities/currency.rs b/src/entities/currency.rs index bc6f4cc..cf45b48 100644 --- a/src/entities/currency.rs +++ b/src/entities/currency.rs @@ -3,7 +3,10 @@ use crate::prelude::*; /// Trait for representing a currency in the Uniswap Core SDK. pub trait Currency: BaseCurrency + Clone { /// Returns the address of the currency. - fn address(&self) -> Address; + #[inline] + fn address(&self) -> Address { + self.wrapped().address + } /// Returns whether this currency is functionally equivalent to the other currency fn equals(&self, other: &impl Currency) -> bool; diff --git a/src/entities/ether.rs b/src/entities/ether.rs index f064a77..33b8855 100644 --- a/src/entities/ether.rs +++ b/src/entities/ether.rs @@ -4,31 +4,29 @@ use crate::prelude::*; /// Represents the native currency of the blockchain. pub type Ether = CurrencyLike>; -impl NativeCurrency for Ether {} +macro_rules! impl_currency { + ($($ether:ty),*) => { + $( + impl Currency for $ether { + #[inline] + fn equals(&self, other: &impl Currency) -> bool { + other.is_native() && self.chain_id() == other.chain_id() + } -impl Currency for Ether { - /// Retrieves the address associated with the currency. - #[inline] - fn address(&self) -> Address { - self.wrapped().address() - } - - /// Checks if the currency is equal to another currency. - #[inline] - fn equals(&self, other: &impl Currency) -> bool { - other.is_native() && self.chain_id() == other.chain_id() - } - - /// Returns the wrapped token representation of the currency. - #[inline] - fn wrapped(&self) -> &Token { - match &self.meta { - Some(weth) => weth, - None => panic!("WRAPPED"), - } - } + #[inline] + fn wrapped(&self) -> &Token { + match &self.meta { + Some(weth) => weth, + None => panic!("WRAPPED"), + } + } + } + )* + }; } +impl_currency!(Ether, &Ether); + impl Ether { /// Creates a new instance of [`Ether`] with the specified chain ID. #[inline] diff --git a/src/entities/fractions/currency_amount.rs b/src/entities/fractions/currency_amount.rs index 31122fc..04076a4 100644 --- a/src/entities/fractions/currency_amount.rs +++ b/src/entities/fractions/currency_amount.rs @@ -139,9 +139,9 @@ impl CurrencyAmount { /// Wrap the currency amount if the currency is not native #[inline] - pub fn wrapped(&self) -> Result, Error> { + pub fn wrapped(&self) -> Result, Error> { CurrencyAmount::from_fractional_amount( - self.currency.wrapped().clone(), + self.currency.wrapped(), self.numerator().clone(), self.denominator().clone(), ) diff --git a/src/entities/native_currency.rs b/src/entities/native_currency.rs index 58a89e6..c2a0914 100644 --- a/src/entities/native_currency.rs +++ b/src/entities/native_currency.rs @@ -1,7 +1,7 @@ use crate::prelude::*; /// Represents the native currency of the chain on which it resides -pub trait NativeCurrency: Currency { +pub trait NativeCurrency: BaseCurrency { #[inline] fn is_native(&self) -> bool { true @@ -12,3 +12,5 @@ pub trait NativeCurrency: Currency { false } } + +impl NativeCurrency for CurrencyLike {} diff --git a/src/entities/token.rs b/src/entities/token.rs index d9aee14..230f681 100644 --- a/src/entities/token.rs +++ b/src/entities/token.rs @@ -14,31 +14,26 @@ pub struct TokenMeta { pub sell_fee_bps: Option, } -impl Currency for Token { - #[inline] - fn address(&self) -> Address { - self.address - } - - /// Returns true if the two tokens are equivalent, i.e. have the same chainId and address. - /// - /// # Arguments - /// - /// * `other`: another token to compare - /// - /// returns: bool - #[inline] - fn equals(&self, other: &impl Currency) -> bool { - other.is_token() && self.chain_id == other.chain_id() && self.address == other.address() - } +macro_rules! impl_currency { + ($($token:ty),*) => { + $( + impl Currency for $token { + #[inline] + fn equals(&self, other: &impl Currency) -> bool { + other.is_token() && self.chain_id == other.chain_id() && self.address == other.address() + } - #[inline] - /// Return this token, which does not need to be wrapped - fn wrapped(&self) -> &Token { - self - } + #[inline] + fn wrapped(&self) -> &Token { + self + } + } + )* + }; } +impl_currency!(Token, &Token); + impl Token { /// Creates a new [`Token`] with the given parameters. ///