Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor to reduce boilerplate #14

Merged
merged 4 commits into from
Dec 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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-rust"
version = "0.3.0"
version = "0.4.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
37 changes: 25 additions & 12 deletions src/entities/base_currency.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
use super::{currency::CurrencyTrait, token::Token};
#[derive(Clone, PartialEq)]
pub struct CurrencyLike<M: Clone> {
pub chain_id: u32,
pub decimals: u8,
pub symbol: Option<String>,
pub name: Option<String>,
pub meta: M,
}

/// A currency is any fungible financial instrument, including Ether, all ERC20 tokens, and other chain-native currencies
pub trait BaseCurrency: Clone {
Expand All @@ -13,16 +20,22 @@ pub trait BaseCurrency: Clone {

/// The name of the currency, i.e. a descriptive textual non-unique identifier
fn name(&self) -> Option<String>;
}

impl<M: Clone> BaseCurrency for CurrencyLike<M> {
fn chain_id(&self) -> u32 {
self.chain_id
}

fn decimals(&self) -> u8 {
self.decimals
}

fn symbol(&self) -> Option<String> {
self.symbol.clone()
}

/// Returns whether this currency is functionally equivalent to the other currency
///
/// # Arguments
///
/// * `other`: the other currency
///
fn equals(&self, other: &impl CurrencyTrait) -> bool;

/// Return the wrapped version of this currency that can be used with the Uniswap contracts.
/// Currencies must implement this to be used in Uniswap
fn wrapped(&self) -> Token;
fn name(&self) -> Option<String> {
self.name.clone()
}
}
81 changes: 71 additions & 10 deletions src/entities/currency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ pub trait CurrencyTrait: BaseCurrency {
fn is_native(&self) -> bool;

fn address(&self) -> Address;

/// Returns whether this currency is functionally equivalent to the other currency
///
/// # Arguments
///
/// * `other`: the other currency
///
fn equals(&self, other: &impl CurrencyTrait) -> bool;

/// Return the wrapped version of this currency that can be used with the Uniswap contracts.
/// Currencies must implement this to be used in Uniswap
fn wrapped(&self) -> Token;
}

impl CurrencyTrait for Currency {
Expand All @@ -28,6 +40,20 @@ impl CurrencyTrait for Currency {
Currency::Token(token) => token.address(),
}
}

fn equals(&self, other: &impl CurrencyTrait) -> bool {
match self {
Currency::NativeCurrency(native_currency) => native_currency.equals(other),
Currency::Token(token) => token.equals(other),
}
}

fn wrapped(&self) -> Token {
match self {
Currency::NativeCurrency(native_currency) => native_currency.wrapped(),
Currency::Token(token) => token.clone(),
}
}
}

impl BaseCurrency for Currency {
Expand Down Expand Up @@ -58,18 +84,53 @@ impl BaseCurrency for Currency {
Currency::Token(token) => token.name(),
}
}
}

fn equals(&self, other: &impl CurrencyTrait) -> bool {
match self {
Currency::NativeCurrency(native_currency) => native_currency.equals(other),
Currency::Token(token) => token.equals(other),
}
#[cfg(test)]
mod tests {
use super::*;
use lazy_static::lazy_static;

const ADDRESS_ZERO: &str = "0x0000000000000000000000000000000000000000";
const ADDRESS_ONE: &str = "0x0000000000000000000000000000000000000001";

lazy_static! {
static ref TOKEN0: Token =
Token::new(1, ADDRESS_ZERO.to_string(), 18, None, None, None, None,);
static ref TOKEN1: Token =
Token::new(1, ADDRESS_ONE.to_string(), 18, None, None, None, None,);
}

fn wrapped(&self) -> Token {
match self {
Currency::NativeCurrency(native_currency) => native_currency.wrapped(),
Currency::Token(token) => token.clone(),
}
#[test]
fn equals_ether_on_same_chains_is_ether() {
assert!(Ether::on_chain(1).equals(&Ether::on_chain(1)));
}

#[test]
fn equals_ether_is_not_token0() {
assert!(!Ether::on_chain(1).equals(&TOKEN0.clone()));
}

#[test]
fn equals_token1_is_not_token0() {
assert!(!TOKEN1.equals(&TOKEN0.clone()));
}

#[test]
fn equals_token0_is_token0() {
assert!(TOKEN0.equals(&TOKEN0.clone()));
}

#[test]
fn equals_token0_is_equal_to_another_token0() {
assert!(TOKEN0.equals(&Token::new(
1,
ADDRESS_ZERO.to_owned(),
18,
Some("symbol".to_owned()),
Some("name".to_owned()),
None,
None
)));
}
}
62 changes: 22 additions & 40 deletions src/entities/ether.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
use super::{base_currency::BaseCurrency, currency::CurrencyTrait, token::Token, weth9::WETH9};
use super::{
base_currency::{BaseCurrency, CurrencyLike},
currency::CurrencyTrait,
token::Token,
weth9::WETH9,
};
use alloy_primitives::Address;
use lazy_static::lazy_static;
use std::{collections::HashMap, sync::Mutex};
Expand All @@ -8,13 +13,7 @@ lazy_static! {
}

/// Ether is the main usage of a 'native' currency, i.e. for Ethereum mainnet and all testnets
#[derive(Clone, PartialEq)]
pub struct Ether {
pub chain_id: u32,
pub decimals: u8,
pub symbol: Option<String>,
pub name: Option<String>,
}
pub type Ether = CurrencyLike<()>;

impl CurrencyTrait for Ether {
fn is_native(&self) -> bool {
Expand All @@ -24,6 +23,20 @@ impl CurrencyTrait for Ether {
fn address(&self) -> Address {
self.wrapped().address()
}

fn equals(&self, other: &impl CurrencyTrait) -> bool {
match other.is_native() {
true => self.chain_id() == other.chain_id(),
_ => false,
}
}

fn wrapped(&self) -> Token {
match WETH9::default().get(self.chain_id()) {
Some(weth9) => weth9.clone(),
None => panic!("WRAPPED"),
}
}
}

impl Ether {
Expand All @@ -33,6 +46,7 @@ impl Ether {
decimals: 18,
symbol: Some("ETH".to_string()),
name: Some("Ether".to_string()),
meta: (),
}
}

Expand All @@ -49,38 +63,6 @@ impl Ether {
}
}

impl BaseCurrency for Ether {
fn chain_id(&self) -> u32 {
self.chain_id
}

fn decimals(&self) -> u8 {
self.decimals
}

fn symbol(&self) -> Option<String> {
self.symbol.clone()
}

fn name(&self) -> Option<String> {
self.name.clone()
}

fn equals(&self, other: &impl CurrencyTrait) -> bool {
match other.is_native() {
true => self.chain_id() == other.chain_id(),
_ => false,
}
}

fn wrapped(&self) -> Token {
match WETH9::default().get(self.chain_id()) {
Some(weth9) => weth9.clone(),
None => panic!("WRAPPED"),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
Loading