Skip to content

Commit

Permalink
refactor!: consolidate currency-related traits and add Currency enum (
Browse files Browse the repository at this point in the history
#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.
  • Loading branch information
shuhuiluo authored Oct 6, 2024
1 parent 6fd1059 commit 0c6cc04
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 39 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.4.0"
version = "3.0.0"
edition = "2021"
authors = ["malik <aremumalik05@gmail.com>", "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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
22 changes: 18 additions & 4 deletions src/entities/base_currency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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<const IS_NATIVE: bool, M> BaseCurrency for $currency {
impl<const IS_NATIVE: bool, M> BaseCurrencyCore for $currency {
#[inline]
fn is_native(&self) -> bool {
IS_NATIVE
Expand Down Expand Up @@ -61,4 +75,4 @@ macro_rules! impl_base_currency {
};
}

impl_base_currency!(CurrencyLike<IS_NATIVE, M>, &CurrencyLike<IS_NATIVE, M>);
impl_base_currency_core!(CurrencyLike<IS_NATIVE, M>, &CurrencyLike<IS_NATIVE, M>);
79 changes: 65 additions & 14 deletions src/entities/currency.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
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,
/// decimals, symbol, name, and additional metadata.
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct CurrencyLike<const IS_NATIVE: bool, M> {
/// 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,
Expand All @@ -45,6 +37,65 @@ impl<const IS_NATIVE: bool, M> Deref for CurrencyLike<IS_NATIVE, M> {
}
}

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::*;
Expand Down
8 changes: 4 additions & 4 deletions src/entities/ether.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ use crate::prelude::*;
/// Represents the native currency of the blockchain.
pub type Ether = CurrencyLike<true, Option<Token>>;

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()
}

Expand All @@ -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.
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 @@ -6,14 +6,14 @@ pub type CurrencyAmount<T> = FractionLike<CurrencyMeta<T>>;

/// Struct representing metadata about a currency
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct CurrencyMeta<T: Currency> {
pub struct CurrencyMeta<T: BaseCurrency> {
/// The currency associated with this metadata
pub currency: T,
/// The scale factor for the currency's decimal places
pub decimal_scale: BigUint,
}

impl<T: Currency> CurrencyAmount<T> {
impl<T: BaseCurrency> CurrencyAmount<T> {
/// Constructor method for creating a new currency amount
#[inline]
fn new(
Expand Down
10 changes: 5 additions & 5 deletions src/entities/fractions/price.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ pub type Price<TBase, TQuote> = FractionLike<PriceMeta<TBase, TQuote>>;
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct PriceMeta<TBase, TQuote>
where
TBase: Currency,
TQuote: Currency,
TBase: BaseCurrency,
TQuote: BaseCurrency,
{
/// The base currency for the price
pub base_currency: TBase,
Expand All @@ -23,8 +23,8 @@ where

impl<TBase, TQuote> Price<TBase, TQuote>
where
TBase: Currency,
TQuote: Currency,
TBase: BaseCurrency,
TQuote: BaseCurrency,
{
/// Constructor for creating a new [`Price`] instance
#[inline]
Expand Down Expand Up @@ -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<TOtherQuote: Currency>(
pub fn multiply<TOtherQuote: BaseCurrency>(
&self,
other: &Price<TQuote, TOtherQuote>,
) -> Result<Price<TBase, TOtherQuote>, Error> {
Expand Down
2 changes: 1 addition & 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: BaseCurrency {
pub trait NativeCurrency: BaseCurrencyCore {
#[inline]
fn is_native(&self) -> bool {
true
Expand Down
8 changes: 4 additions & 4 deletions src/entities/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ pub struct TokenMeta {
pub sell_fee_bps: Option<BigUint>,
}

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()
}

Expand All @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/utils/compute_price_impact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::prelude::*;
///
/// returns: Percent
#[inline]
pub fn compute_price_impact<TBase: Currency, TQuote: Currency>(
pub fn compute_price_impact<TBase: BaseCurrency, TQuote: BaseCurrency>(
mid_price: &Price<TBase, TQuote>,
input_amount: &CurrencyAmount<TBase>,
output_amount: &CurrencyAmount<TQuote>,
Expand Down

0 comments on commit 0c6cc04

Please sign in to comment.