Skip to content

Commit

Permalink
refactor: currency traits and implementations (#82)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
shuhuiluo authored Sep 23, 2024
1 parent d04f121 commit 84b773c
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 79 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "uniswap-sdk-core"
version = "2.2.0"
version = "2.3.0"
edition = "2021"
authors = ["malik <[email protected]>", "Shuhui Luo <twitter.com/aureliano_law>"]
description = "The Uniswap SDK Core in Rust provides essential functionality for interacting with the Uniswap decentralized exchange"
Expand Down
68 changes: 38 additions & 30 deletions src/entities/base_currency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,42 @@ pub trait BaseCurrency {
fn name(&self) -> Option<&String>;
}

impl<const IS_NATIVE: bool, M> BaseCurrency for CurrencyLike<IS_NATIVE, M> {
#[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<const IS_NATIVE: bool, M> 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<IS_NATIVE, M>, &CurrencyLike<IS_NATIVE, M>);
5 changes: 4 additions & 1 deletion src/entities/currency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
42 changes: 20 additions & 22 deletions src/entities/ether.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,29 @@ use crate::prelude::*;
/// Represents the native currency of the blockchain.
pub type Ether = CurrencyLike<true, Option<Token>>;

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]
Expand Down
4 changes: 2 additions & 2 deletions src/entities/fractions/currency_amount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ impl<T: Currency> CurrencyAmount<T> {

/// Wrap the currency amount if the currency is not native
#[inline]
pub fn wrapped(&self) -> Result<CurrencyAmount<Token>, Error> {
pub fn wrapped(&self) -> Result<CurrencyAmount<&Token>, Error> {
CurrencyAmount::from_fractional_amount(
self.currency.wrapped().clone(),
self.currency.wrapped(),
self.numerator().clone(),
self.denominator().clone(),
)
Expand Down
4 changes: 3 additions & 1 deletion src/entities/native_currency.rs
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -12,3 +12,5 @@ pub trait NativeCurrency: Currency {
false
}
}

impl<M> NativeCurrency for CurrencyLike<true, M> {}
39 changes: 17 additions & 22 deletions src/entities/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,26 @@ pub struct TokenMeta {
pub sell_fee_bps: Option<BigUint>,
}

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.
///
Expand Down

0 comments on commit 84b773c

Please sign in to comment.