diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 4db2849..7fcad88 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -8,6 +8,7 @@ on: env: CARGO_TERM_COLOR: always + INFURA_API_KEY: ${{ secrets.INFURA_API_KEY }} jobs: lint: @@ -59,5 +60,7 @@ jobs: ${{ runner.os }}-cargo-registry- - name: Build run: cargo build --all-features - - name: Run tests - run: cargo test --all-features + - name: Run tests for core library + run: cargo test + - name: Run tests for extensions + run: cargo test --all-features --lib extensions -- --test-threads=1 diff --git a/.gitignore b/.gitignore index 4b9bd67..e7e10f8 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,5 @@ Cargo.lock # IDEs .idea .vscode + +.env* diff --git a/Cargo.toml b/Cargo.toml index 13d9119..d6941a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "uniswap-v3-sdk" -version = "0.29.2" +version = "0.30.0" edition = "2021" authors = ["Shuhui Luo "] description = "Uniswap V3 SDK for Rust" @@ -14,8 +14,8 @@ exclude = [".github", ".gitignore", "rustfmt.toml"] all-features = true [dependencies] -alloy-primitives = "0.7" -alloy-sol-types = "0.7" +alloy-primitives = "0.7.6" +alloy-sol-types = "0.7.6" anyhow = "1.0" aperture-lens = { version = "0.4", optional = true } base64 = { version = "0.22", optional = true } @@ -30,14 +30,15 @@ regex = { version = "1.10", optional = true } ruint = "1.12" serde_json = { version = "1.0", optional = true } thiserror = "1.0" -uniswap-sdk-core = "0.21.0" -uniswap_v3_math = "0.4" +uniswap-sdk-core = "0.23.0" +uniswap_v3_math = "0.5.1" [features] extensions = ["aperture-lens", "base64", "ethers", "regex", "serde_json"] [dev-dependencies] criterion = "0.5.1" +dotenv = "0.15.0" ethers = "2.0" tokio = { version = "1.37", features = ["full"] } diff --git a/README.md b/README.md index c097e91..dfd243c 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ expect. The error handling is still a work in progress. Add the following to your `Cargo.toml` file: ```toml -uniswap-v3-sdk = { version = "0.25.0", features = ["extensions"] } +uniswap-v3-sdk = { version = "0.30.0", features = ["extensions"] } ``` ### Usage @@ -64,7 +64,19 @@ Contributions are welcome. Please open an issue if you have any questions or sug ### Testing -Tests are run with `cargo test`. To test a specific module, use `cargo test --test `. +Tests are run with + +```shell +cargo test +``` + +for the core library. To run the tests for the extensions, use + +```shell +cargo test --all-features --lib extensions -- --test-threads=1 +``` + +To test a specific module, use `cargo test --test `. ### Linting diff --git a/benches/bit_math.rs b/benches/bit_math.rs index c9833ae..38cf3fb 100644 --- a/benches/bit_math.rs +++ b/benches/bit_math.rs @@ -18,7 +18,7 @@ fn most_significant_bit_benchmark_ref(c: &mut Criterion) { c.bench_function("most_significant_bit_ref", |b| { b.iter(|| { for i in 1u8..=255 { - let _ = bit_math::most_significant_bit(U256::from(1).shl(i).to_ethers()); + let _ = bit_math::most_significant_bit(U256::from(1).shl(i)); } }) }); @@ -38,7 +38,7 @@ fn least_significant_bit_benchmark_ref(c: &mut Criterion) { c.bench_function("least_significant_bit_ref", |b| { b.iter(|| { for i in 1u8..=255 { - let _ = bit_math::least_significant_bit(U256::from(1).shl(i).to_ethers()); + let _ = bit_math::least_significant_bit(U256::from(1).shl(i)); } }); }); diff --git a/benches/sqrt_price_math.rs b/benches/sqrt_price_math.rs index ca8357e..95a7301 100644 --- a/benches/sqrt_price_math.rs +++ b/benches/sqrt_price_math.rs @@ -43,9 +43,9 @@ fn get_next_sqrt_price_from_input_benchmark_ref(c: &mut Criterion) { b.iter(|| { for (sqrt_price_x_96, liquidity, amount, add) in &inputs { let _ = sqrt_price_math::get_next_sqrt_price_from_input( - sqrt_price_x_96.to_ethers(), + *sqrt_price_x_96, *liquidity, - amount.to_ethers(), + *amount, *add, ); } @@ -71,9 +71,9 @@ fn get_next_sqrt_price_from_output_benchmark_ref(c: &mut Criterion) { b.iter(|| { for (sqrt_price_x_96, liquidity, amount, add) in &inputs { let _ = sqrt_price_math::get_next_sqrt_price_from_output( - sqrt_price_x_96.to_ethers(), + *sqrt_price_x_96, *liquidity, - amount.to_ethers(), + *amount, *add, ); } @@ -99,8 +99,8 @@ fn get_amount_0_delta_benchmark_ref(c: &mut Criterion) { b.iter(|| { for (sqrt_ratio_a_x96, liquidity, sqrt_ratio_b_x96, round_up) in &inputs { let _ = sqrt_price_math::_get_amount_0_delta( - sqrt_ratio_a_x96.to_ethers(), - sqrt_ratio_b_x96.to_ethers(), + *sqrt_ratio_a_x96, + *sqrt_ratio_b_x96, *liquidity, *round_up, ); @@ -127,8 +127,8 @@ fn get_amount_1_delta_benchmark_ref(c: &mut Criterion) { b.iter(|| { for (sqrt_ratio_a_x96, liquidity, sqrt_ratio_b_x96, round_up) in &inputs { let _ = sqrt_price_math::_get_amount_1_delta( - sqrt_ratio_a_x96.to_ethers(), - sqrt_ratio_b_x96.to_ethers(), + *sqrt_ratio_a_x96, + *sqrt_ratio_b_x96, *liquidity, *round_up, ); @@ -158,8 +158,8 @@ fn get_amount_0_delta_signed_benchmark_ref(c: &mut Criterion) { b.iter(|| { for (sqrt_ratio_a_x96, liquidity, sqrt_ratio_b_x96, _) in &inputs { let _ = sqrt_price_math::get_amount_0_delta( - sqrt_ratio_a_x96.to_ethers(), - sqrt_ratio_b_x96.to_ethers(), + *sqrt_ratio_a_x96, + *sqrt_ratio_b_x96, *liquidity as i128, ); } @@ -188,8 +188,8 @@ fn get_amount_1_delta_signed_benchmark_ref(c: &mut Criterion) { b.iter(|| { for (sqrt_ratio_a_x96, liquidity, sqrt_ratio_b_x96, _) in &inputs { let _ = sqrt_price_math::get_amount_1_delta( - sqrt_ratio_a_x96.to_ethers(), - sqrt_ratio_b_x96.to_ethers(), + *sqrt_ratio_a_x96, + *sqrt_ratio_b_x96, *liquidity as i128, ); } diff --git a/benches/swap_math.rs b/benches/swap_math.rs index 63aa9d3..ba3df15 100644 --- a/benches/swap_math.rs +++ b/benches/swap_math.rs @@ -52,20 +52,7 @@ fn compute_swap_step_benchmark(c: &mut Criterion) { } fn compute_swap_step_benchmark_ref(c: &mut Criterion) { - use ethers::types::{I256, U256}; - - let inputs: Vec<(U256, U256, u128, I256, u32)> = generate_inputs() - .into_iter() - .map(|i| { - ( - i.0.to_ethers(), - i.1.to_ethers(), - i.2, - I256::from_raw(i.3.into_raw().to_ethers()), - i.4, - ) - }) - .collect(); + let inputs: Vec<(U256, U256, u128, I256, u32)> = generate_inputs(); c.bench_function("compute_swap_step_ref", |b| { b.iter(|| { for ( diff --git a/benches/tick_math.rs b/benches/tick_math.rs index ef8d6d8..f1179d2 100644 --- a/benches/tick_math.rs +++ b/benches/tick_math.rs @@ -38,7 +38,7 @@ fn get_tick_at_sqrt_ratio_benchmark_ref(c: &mut Criterion) { c.bench_function("get_tick_at_sqrt_ratio_ref", |b| { b.iter(|| { for i in 33u8..=191 { - let _ = tick_math::get_tick_at_sqrt_ratio(U256::from(1).shl(i).to_ethers()); + let _ = tick_math::get_tick_at_sqrt_ratio(U256::from(1).shl(i)); } }); }); diff --git a/src/extensions/ephemeral_tick_data_provider.rs b/src/extensions/ephemeral_tick_data_provider.rs index e31b9e4..29fbd41 100644 --- a/src/extensions/ephemeral_tick_data_provider.rs +++ b/src/extensions/ephemeral_tick_data_provider.rs @@ -88,8 +88,9 @@ impl From for TickListDataProvider { #[cfg(test)] mod tests { use super::*; + use crate::tests::*; use alloy_primitives::address; - use ethers::prelude::{Provider, MAINNET}; + use ethers::prelude::Provider; const TICK_SPACING: i32 = 10; @@ -98,7 +99,7 @@ mod tests { async fn test_ephemeral_tick_data_provider() -> Result<()> { let provider = EphemeralTickDataProvider::new( address!("88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"), - Arc::new(Provider::new_client(MAINNET.provider().url().as_str(), 3, 1000).unwrap()), + Arc::new(Provider::new_client(make_provider().await.url().as_str(), 3, 1000).unwrap()), None, None, Some(BlockId::from(17000000)), diff --git a/src/extensions/pool.rs b/src/extensions/pool.rs index d9229e5..fc00d69 100644 --- a/src/extensions/pool.rs +++ b/src/extensions/pool.rs @@ -197,6 +197,7 @@ pub async fn get_liquidity_array_for_pool( #[cfg(test)] mod tests { use super::*; + use crate::tests::make_provider; use alloy_primitives::address; async fn pool() -> Pool { @@ -206,7 +207,7 @@ mod tests { address!("2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"), address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), FeeAmount::LOW, - Arc::new(MAINNET.provider()), + Arc::new(make_provider().await), Some(BlockId::from(17000000)), ) .await @@ -235,7 +236,7 @@ mod tests { pool, tick_lower, tick_upper, - Arc::new(MAINNET.provider()), + Arc::new(make_provider().await), Some(BlockId::from(17000000)), None, None, diff --git a/src/extensions/position.rs b/src/extensions/position.rs index c4bcf51..8aa3311 100644 --- a/src/extensions/position.rs +++ b/src/extensions/position.rs @@ -375,6 +375,7 @@ where #[cfg(test)] mod tests { use super::*; + use crate::tests::make_provider; use alloy_primitives::{address, uint}; use num_traits::Signed; @@ -386,7 +387,7 @@ mod tests { 1, NPM, uint!(4_U256), - Arc::new(MAINNET.provider()), + Arc::new(make_provider().await), Some(BlockId::from(17188000)), ) .await @@ -398,7 +399,7 @@ mod tests { #[tokio::test] async fn test_get_all_positions_by_owner() { - let client = Arc::new(MAINNET.provider()); + let client = Arc::new(make_provider().await); let block_id = BlockId::from(17188000); let owner = address!("4bD047CA72fa05F0B89ad08FE5Ba5ccdC07DFFBF"); let positions = get_all_positions_by_owner(NPM, owner, client.clone(), Some(block_id)) @@ -433,7 +434,7 @@ mod tests { 1, NPM, uint!(4_U256), - Arc::new(MAINNET.provider()), + Arc::new(make_provider().await), Some(BlockId::from(17188000)), ) .await @@ -447,7 +448,7 @@ mod tests { let svg = get_token_svg( NPM, uint!(4_U256), - Arc::new(MAINNET.provider()), + Arc::new(make_provider().await), Some(BlockId::from(17188000)), ) .await @@ -464,7 +465,7 @@ mod tests { 1, NPM, uint!(4_U256), - Arc::new(MAINNET.provider()), + Arc::new(make_provider().await), Some(BlockId::from(17188000)), ) .await @@ -494,7 +495,7 @@ mod tests { 1, NPM, uint!(4_U256), - Arc::new(MAINNET.provider()), + Arc::new(make_provider().await), Some(BlockId::from(17188000)), ) .await @@ -547,7 +548,7 @@ mod tests { 1, NPM, uint!(4_U256), - Arc::new(MAINNET.provider()), + Arc::new(make_provider().await), Some(BlockId::from(17188000)), ) .await diff --git a/src/tests.rs b/src/tests.rs index b6ee1bc..5077de6 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,5 +1,7 @@ use crate::prelude::*; use alloy_primitives::U256; +use dotenv::dotenv; +use ethers::prelude::*; use once_cell::sync::Lazy; use uniswap_sdk_core::{prelude::*, token}; @@ -119,3 +121,15 @@ pub fn make_pool(token0: Token, token1: Token) -> Pool { ) .unwrap() } + +pub static RPC_URL: Lazy = Lazy::new(|| { + dotenv().ok(); + format!( + "https://mainnet.infura.io/v3/{}", + std::env::var("INFURA_API_KEY").unwrap() + ) +}); + +pub async fn make_provider() -> Provider { + Provider::::connect(&RPC_URL).await +} diff --git a/src/utils/price_tick_conversions.rs b/src/utils/price_tick_conversions.rs index ed8cd7e..8c55eaf 100644 --- a/src/utils/price_tick_conversions.rs +++ b/src/utils/price_tick_conversions.rs @@ -34,7 +34,7 @@ pub fn tick_to_price( /// ## Arguments /// /// * `price`: for which to return the closest tick that represents a price less than or equal to -/// the input price, i.e. the price of the returned tick is less than or equal to the input price +/// the input price, i.e. the price of the returned tick is less than or equal to the input price pub fn price_to_closest_tick(price: &Price) -> Result { let sorted = price.base_currency.sorts_before(&price.quote_currency)?; let sqrt_ratio_x96 = if sorted { diff --git a/src/utils/sqrt_price_math.rs b/src/utils/sqrt_price_math.rs index 94dcb5f..26bff63 100644 --- a/src/utils/sqrt_price_math.rs +++ b/src/utils/sqrt_price_math.rs @@ -355,12 +355,11 @@ mod tests { for (sqrt_price_x_96, liquidity, amount, add) in &inputs { let res = get_next_sqrt_price_from_input(*sqrt_price_x_96, *liquidity, *amount, *add); let ref_ = sqrt_price_math::get_next_sqrt_price_from_input( - sqrt_price_x_96.to_ethers(), + *sqrt_price_x_96, *liquidity, - amount.to_ethers(), + *amount, *add, - ) - .map(ToAlloy::to_alloy); + ); match_u256(res, ref_); } } @@ -371,12 +370,11 @@ mod tests { for (sqrt_price_x_96, liquidity, amount, add) in &inputs { let res = get_next_sqrt_price_from_output(*sqrt_price_x_96, *liquidity, *amount, *add); let ref_ = sqrt_price_math::get_next_sqrt_price_from_output( - sqrt_price_x_96.to_ethers(), + *sqrt_price_x_96, *liquidity, - amount.to_ethers(), + *amount, *add, - ) - .map(ToAlloy::to_alloy); + ); match_u256(res, ref_); } } @@ -388,12 +386,11 @@ mod tests { let res = get_amount_0_delta(*sqrt_ratio_a_x96, *sqrt_ratio_b_x96, *liquidity, *round_up); let ref_ = sqrt_price_math::_get_amount_0_delta( - sqrt_ratio_a_x96.to_ethers(), - sqrt_ratio_b_x96.to_ethers(), + *sqrt_ratio_a_x96, + *sqrt_ratio_b_x96, *liquidity, *round_up, - ) - .map(ToAlloy::to_alloy); + ); match_u256(res, ref_); } } @@ -405,12 +402,11 @@ mod tests { let res = get_amount_1_delta(*sqrt_ratio_a_x96, *sqrt_ratio_b_x96, *liquidity, *round_up); let ref_ = sqrt_price_math::_get_amount_1_delta( - sqrt_ratio_a_x96.to_ethers(), - sqrt_ratio_b_x96.to_ethers(), + *sqrt_ratio_a_x96, + *sqrt_ratio_b_x96, *liquidity, *round_up, - ) - .map(ToAlloy::to_alloy); + ); match_u256(res, ref_); } } @@ -423,13 +419,13 @@ mod tests { get_amount_0_delta_signed(*sqrt_ratio_a_x96, *sqrt_ratio_b_x96, *liquidity as i128) .map(I256::into_raw); let ref_ = sqrt_price_math::get_amount_0_delta( - sqrt_ratio_a_x96.to_ethers(), - sqrt_ratio_b_x96.to_ethers(), + *sqrt_ratio_a_x96, + *sqrt_ratio_b_x96, *liquidity as i128, ); match ref_ { Ok(ref_) => { - assert_eq!(res.unwrap(), ref_.into_raw().to_alloy()); + assert_eq!(res.unwrap(), ref_.into_raw()); } Err(e) => { assert_eq!(res.unwrap_err().to_string(), e.to_string()); @@ -446,13 +442,13 @@ mod tests { get_amount_1_delta_signed(*sqrt_ratio_a_x96, *sqrt_ratio_b_x96, *liquidity as i128) .map(I256::into_raw); let ref_ = sqrt_price_math::get_amount_1_delta( - sqrt_ratio_a_x96.to_ethers(), - sqrt_ratio_b_x96.to_ethers(), + *sqrt_ratio_a_x96, + *sqrt_ratio_b_x96, *liquidity as i128, ); match ref_ { Ok(ref_) => { - assert_eq!(res.unwrap(), ref_.into_raw().to_alloy()); + assert_eq!(res.unwrap(), ref_.into_raw()); } Err(e) => { assert_eq!(res.unwrap_err().to_string(), e.to_string());