From 0c6cc046dd546d8bc5215dd764ff4cabad6f448e Mon Sep 17 00:00:00 2001 From: Shuhui Luo <107524008+shuhuiluo@users.noreply.github.com> Date: Sun, 6 Oct 2024 05:37:49 -0400 Subject: [PATCH] refactor!: consolidate currency-related traits and add `Currency` enum (#85) Reorganized `BaseCurrency` and `BaseCurrencyCore` traits, encapsulating their functionalities. Introduced `Currency` enum to represent both native and token currencies, providing a unified interface for currency operations. Updated version to 3.0.0 to reflect these breaking changes. --- Cargo.toml | 2 +- README.md | 2 +- src/entities/base_currency.rs | 22 +++++-- src/entities/currency.rs | 79 +++++++++++++++++++---- src/entities/ether.rs | 8 +-- src/entities/fractions/currency_amount.rs | 4 +- src/entities/fractions/price.rs | 10 +-- src/entities/native_currency.rs | 2 +- src/entities/token.rs | 8 +-- src/prelude.rs | 4 +- src/utils/compute_price_impact.rs | 2 +- 11 files changed, 104 insertions(+), 39 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 19fa0e2..54fa16d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "uniswap-sdk-core" -version = "2.4.0" +version = "3.0.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/README.md b/README.md index 6673a8b..8bb6c6b 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Add this to your Cargo.toml ``` [dependencies] -uniswap-sdk-core = "2.4.0" +uniswap-sdk-core = "3.0.0" ``` And this to your code: diff --git a/src/entities/base_currency.rs b/src/entities/base_currency.rs index 3b34302..78e0533 100644 --- a/src/entities/base_currency.rs +++ b/src/entities/base_currency.rs @@ -3,7 +3,21 @@ use alloy_primitives::ChainId; /// A currency is any fungible financial instrument, including Ether, all ERC20 tokens, and other /// chain-native currencies -pub trait BaseCurrency { +pub trait BaseCurrency: BaseCurrencyCore + Clone { + /// Returns the address of the currency. + #[inline] + fn address(&self) -> Address { + self.wrapped().address + } + + /// Returns whether this currency is functionally equivalent to the other currency + fn equals(&self, other: &impl BaseCurrency) -> bool; + + /// Returns a Token that represents the wrapped equivalent of the native currency + fn wrapped(&self) -> &Token; +} + +pub trait BaseCurrencyCore { /// Returns whether the currency is native to the chain and must be wrapped (e.g. Ether) fn is_native(&self) -> bool; @@ -23,10 +37,10 @@ pub trait BaseCurrency { fn name(&self) -> Option<&String>; } -macro_rules! impl_base_currency { +macro_rules! impl_base_currency_core { ($($currency:ty),*) => { $( - impl BaseCurrency for $currency { + impl BaseCurrencyCore for $currency { #[inline] fn is_native(&self) -> bool { IS_NATIVE @@ -61,4 +75,4 @@ macro_rules! impl_base_currency { }; } -impl_base_currency!(CurrencyLike, &CurrencyLike); +impl_base_currency_core!(CurrencyLike, &CurrencyLike); diff --git a/src/entities/currency.rs b/src/entities/currency.rs index cf45b48..51d3605 100644 --- a/src/entities/currency.rs +++ b/src/entities/currency.rs @@ -1,18 +1,10 @@ use crate::prelude::*; +use alloy_primitives::ChainId; -/// Trait for representing a currency in the Uniswap Core SDK. -pub trait Currency: BaseCurrency + Clone { - /// Returns the address of the currency. - #[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; - - /// Returns a Token that represents the wrapped equivalent of the native currency - fn wrapped(&self) -> &Token; +#[derive(Clone, Debug, Hash, PartialEq, Eq)] +pub enum Currency { + NativeCurrency(Ether), + Token(Token), } /// [`CurrencyLike`] is a generic struct representing a currency with a specific chain ID, @@ -20,7 +12,7 @@ pub trait Currency: BaseCurrency + Clone { #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct CurrencyLike { /// The chain ID on which this currency resides - pub chain_id: alloy_primitives::ChainId, + pub chain_id: ChainId, /// The decimals for the particular currency pub decimals: u8, @@ -45,6 +37,65 @@ impl Deref for CurrencyLike { } } +macro_rules! match_currency_method { + ($method:ident, $return_type:ty) => { + #[inline] + fn $method(&self) -> $return_type { + match self { + Currency::NativeCurrency(ether) => ether.$method(), + Currency::Token(token) => token.$method(), + } + } + }; +} + +macro_rules! impl_base_currency_core { + ($($currency:ty),*) => { + $( + impl BaseCurrencyCore for $currency { + #[inline] + fn is_native(&self) -> bool { + matches!(self, Currency::NativeCurrency(_)) + } + + #[inline] + fn is_token(&self) -> bool { + matches!(self, Currency::Token(_)) + } + + match_currency_method!(chain_id, ChainId); + + match_currency_method!(decimals, u8); + + match_currency_method!(symbol, Option<&String>); + + match_currency_method!(name, Option<&String>); + } + )* + }; +} + +macro_rules! impl_base_currency { + ($($currency:ty),*) => { + $( + impl BaseCurrency for $currency { + #[inline] + fn equals(&self, other: &impl BaseCurrency) -> bool { + match self { + Currency::NativeCurrency(ether) => ether.equals(other), + Currency::Token(token) => token.equals(other), + } + } + + match_currency_method!(wrapped, &Token); + } + )* + }; +} + +impl_base_currency_core!(Currency, &Currency); +impl_base_currency!(Currency, &Currency); + #[cfg(test)] mod tests { use super::*; diff --git a/src/entities/ether.rs b/src/entities/ether.rs index 33b8855..5130168 100644 --- a/src/entities/ether.rs +++ b/src/entities/ether.rs @@ -4,12 +4,12 @@ use crate::prelude::*; /// Represents the native currency of the blockchain. pub type Ether = CurrencyLike>; -macro_rules! impl_currency { +macro_rules! impl_base_currency { ($($ether:ty),*) => { $( - impl Currency for $ether { + impl BaseCurrency for $ether { #[inline] - fn equals(&self, other: &impl Currency) -> bool { + fn equals(&self, other: &impl BaseCurrency) -> bool { other.is_native() && self.chain_id() == other.chain_id() } @@ -25,7 +25,7 @@ macro_rules! impl_currency { }; } -impl_currency!(Ether, &Ether); +impl_base_currency!(Ether, &Ether); impl Ether { /// Creates a new instance of [`Ether`] with the specified chain ID. diff --git a/src/entities/fractions/currency_amount.rs b/src/entities/fractions/currency_amount.rs index 04076a4..3bcb606 100644 --- a/src/entities/fractions/currency_amount.rs +++ b/src/entities/fractions/currency_amount.rs @@ -6,14 +6,14 @@ pub type CurrencyAmount = FractionLike>; /// Struct representing metadata about a currency #[derive(Clone, Debug, Hash, PartialEq, Eq)] -pub struct CurrencyMeta { +pub struct CurrencyMeta { /// The currency associated with this metadata pub currency: T, /// The scale factor for the currency's decimal places pub decimal_scale: BigUint, } -impl CurrencyAmount { +impl CurrencyAmount { /// Constructor method for creating a new currency amount #[inline] fn new( diff --git a/src/entities/fractions/price.rs b/src/entities/fractions/price.rs index 1d11268..5207b72 100644 --- a/src/entities/fractions/price.rs +++ b/src/entities/fractions/price.rs @@ -8,8 +8,8 @@ pub type Price = FractionLike>; #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct PriceMeta where - TBase: Currency, - TQuote: Currency, + TBase: BaseCurrency, + TQuote: BaseCurrency, { /// The base currency for the price pub base_currency: TBase, @@ -23,8 +23,8 @@ where impl Price where - TBase: Currency, - TQuote: Currency, + TBase: BaseCurrency, + TQuote: BaseCurrency, { /// Constructor for creating a new [`Price`] instance #[inline] @@ -79,7 +79,7 @@ where /// Multiply the price by another price, returning a new price. /// The other price must have the same base currency as this price's quote currency. #[inline] - pub fn multiply( + pub fn multiply( &self, other: &Price, ) -> Result, Error> { diff --git a/src/entities/native_currency.rs b/src/entities/native_currency.rs index c2a0914..ed705b7 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: BaseCurrency { +pub trait NativeCurrency: BaseCurrencyCore { #[inline] fn is_native(&self) -> bool { true diff --git a/src/entities/token.rs b/src/entities/token.rs index 230f681..190b31e 100644 --- a/src/entities/token.rs +++ b/src/entities/token.rs @@ -14,12 +14,12 @@ pub struct TokenMeta { pub sell_fee_bps: Option, } -macro_rules! impl_currency { +macro_rules! impl_base_currency { ($($token:ty),*) => { $( - impl Currency for $token { + impl BaseCurrency for $token { #[inline] - fn equals(&self, other: &impl Currency) -> bool { + fn equals(&self, other: &impl BaseCurrency) -> bool { other.is_token() && self.chain_id == other.chain_id() && self.address == other.address() } @@ -32,7 +32,7 @@ macro_rules! impl_currency { }; } -impl_currency!(Token, &Token); +impl_base_currency!(Token, &Token); impl Token { /// Creates a new [`Token`] with the given parameters. diff --git a/src/prelude.rs b/src/prelude.rs index e18f1e1..489145d 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -3,8 +3,8 @@ pub use crate::{ chains::*, constants::*, entities::{ - base_currency::BaseCurrency, - currency::{Currency, CurrencyLike}, + base_currency::*, + currency::*, ether::Ether, fractions::{ currency_amount::CurrencyAmount, diff --git a/src/utils/compute_price_impact.rs b/src/utils/compute_price_impact.rs index c36df20..a797024 100644 --- a/src/utils/compute_price_impact.rs +++ b/src/utils/compute_price_impact.rs @@ -10,7 +10,7 @@ use crate::prelude::*; /// /// returns: Percent #[inline] -pub fn compute_price_impact( +pub fn compute_price_impact( mid_price: &Price, input_amount: &CurrencyAmount, output_amount: &CurrencyAmount,