From bd930e2ebf62a94d3cc4ea3e4837a32f0ce105f6 Mon Sep 17 00:00:00 2001 From: Shuhui Luo <107524008+shuhuiluo@users.noreply.github.com> Date: Tue, 10 Dec 2024 02:11:05 -0500 Subject: [PATCH 1/4] doc: add example and documentation for pool creation with tick data This commit introduces an example demonstrating how to create a pool with a tick map data provider and simulates a swap in the README. Additionally, it includes documentation for the `from_pool_key_with_tick_data_provider` method in the codebase, enhancing clarity for developers utilizing the pool extension. These additions aim to improve understanding and usability of the library's pool-related features. --- Cargo.toml | 4 ++ README.md | 27 +++++++++ .../from_pool_key_with_tick_data_provider.rs | 60 +++++++++++++++++++ src/extensions/pool.rs | 43 +++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 examples/from_pool_key_with_tick_data_provider.rs diff --git a/Cargo.toml b/Cargo.toml index d6c0b3d..2e8fd8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,3 +61,7 @@ harness = false [[bench]] name = "tick_math" harness = false + +[[example]] +name = "from_pool_key_with_tick_data_provider" +required-features = ["extensions"] diff --git a/README.md b/README.md index a57e96f..f9b7d39 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,33 @@ use uniswap_v3_sdk::prelude::*; By default, this library does not depend on the standard library (`std`). However, the `std` feature can be enabled to use `thiserror` for error handling. +## Examples + +The code below shows an example of creating a pool with a tick map data provider and simulating a swap with it. + +```rust +#[tokio::main] +async fn main() { + // Create a pool with a tick map data provider + let pool = Pool::>::from_pool_key_with_tick_data_provider( + 1, + FACTORY_ADDRESS, + wbtc.address(), + weth.address(), + FeeAmount::LOW, + provider.clone(), + block_id, + ) + .await + .unwrap(); + // Get the output amount from the pool + let amount_in = CurrencyAmount::from_raw_amount(wbtc.clone(), 100000000).unwrap(); + let (amount_out, _pool_after) = pool.get_output_amount(&amount_in, None).unwrap(); +} +``` + +For runnable examples, see the [examples](./examples) directory. + ## Contributing Contributions are welcome. Please open an issue if you have any questions or suggestions. diff --git a/examples/from_pool_key_with_tick_data_provider.rs b/examples/from_pool_key_with_tick_data_provider.rs new file mode 100644 index 0000000..31cead8 --- /dev/null +++ b/examples/from_pool_key_with_tick_data_provider.rs @@ -0,0 +1,60 @@ +use alloy::{ + eips::BlockId, + providers::{Provider, ProviderBuilder}, + rpc::types::TransactionRequest, +}; +use alloy_primitives::{address, ruint::aliases::U256, U160}; +use alloy_sol_types::SolValue; +use uniswap_sdk_core::{prelude::*, token}; +use uniswap_v3_sdk::prelude::*; + +#[tokio::main] +async fn main() { + dotenv::dotenv().ok(); + let rpc_url = std::env::var("MAINNET_RPC_URL").unwrap().parse().unwrap(); + let provider = ProviderBuilder::new().on_http(rpc_url); + let block_id = BlockId::from(17000000); + let wbtc = token!(1, "2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", 8, "WBTC"); + let weth = token!(1, "C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", 18, "WETH"); + + // Create a pool with a tick map data provider + let pool = Pool::>::from_pool_key_with_tick_data_provider( + 1, + FACTORY_ADDRESS, + wbtc.address(), + weth.address(), + FeeAmount::LOW, + provider.clone(), + Some(block_id), + ) + .await + .unwrap(); + // Get the output amount from the pool + let amount_in = CurrencyAmount::from_raw_amount(wbtc.clone(), 100000000).unwrap(); + let (local_amount_out, _pool_after) = pool.get_output_amount(&amount_in, None).unwrap(); + println!("Local amount out: {}", local_amount_out.quotient()); + + let route = Route::new(vec![pool.clone()], wbtc, weth); + let params = quote_call_parameters( + &route, + &amount_in, + TradeType::ExactInput, + Some(QuoteOptions { + sqrt_price_limit_x96: U160::ZERO, + use_quoter_v2: false, + }), + ); + let quoter_addr = *QUOTER_ADDRESSES.get(&1).unwrap(); + let tx = TransactionRequest { + to: Some(quoter_addr.into()), + input: params.calldata.into(), + ..Default::default() + }; + // Get the output amount from the quoter + let res = provider.call(&tx).block(block_id).await.unwrap(); + let amount_out = U256::abi_decode(res.as_ref(), true).unwrap(); + println!("Quoter amount out: {}", amount_out); + + // Assert that the amounts are equal + assert_eq!(U256::from_big_int(local_amount_out.quotient()), amount_out); +} diff --git a/src/extensions/pool.rs b/src/extensions/pool.rs index 69048d2..fe1f1a9 100644 --- a/src/extensions/pool.rs +++ b/src/extensions/pool.rs @@ -103,6 +103,49 @@ impl Pool { } impl Pool> { + /// Get a [`Pool`] struct with tick data provider from pool key + /// + /// ## Arguments + /// + /// * `chain_id`: The chain id + /// * `factory`: The factory address + /// * `token_a`: One of the tokens in the pool + /// * `token_b`: The other token in the pool + /// * `fee`: Fee tier of the pool + /// * `provider`: The alloy provider + /// * `block_id`: Optional block number to query. + /// + /// ## Returns + /// + /// A [`Pool`] struct with tick data provider + /// + /// ## Examples + /// + /// ``` + /// use alloy::{eips::BlockId, providers::ProviderBuilder}; + /// use alloy_primitives::address; + /// use uniswap_v3_sdk::prelude::*; + /// + /// #[tokio::main] + /// async fn main() { + /// dotenv::dotenv().ok(); + /// let rpc_url = std::env::var("MAINNET_RPC_URL").unwrap().parse().unwrap(); + /// let provider = ProviderBuilder::new().on_http(rpc_url); + /// let block_id = Some(BlockId::from(17000000)); + /// let pool = + /// Pool::>::from_pool_key_with_tick_data_provider( + /// 1, + /// FACTORY_ADDRESS, + /// address!("2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"), + /// address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), + /// FeeAmount::LOW, + /// provider, + /// block_id, + /// ) + /// .await + /// .unwrap(); + /// } + /// ``` #[inline] pub async fn from_pool_key_with_tick_data_provider( chain_id: ChainId, From 63d60f173ba1438d9b5a5096c08f7860ac3019a3 Mon Sep 17 00:00:00 2001 From: Shuhui Luo <107524008+shuhuiluo@users.noreply.github.com> Date: Tue, 10 Dec 2024 02:25:51 -0500 Subject: [PATCH 2/4] Update examples/from_pool_key_with_tick_data_provider.rs Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- examples/from_pool_key_with_tick_data_provider.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/examples/from_pool_key_with_tick_data_provider.rs b/examples/from_pool_key_with_tick_data_provider.rs index 31cead8..f2a0c40 100644 --- a/examples/from_pool_key_with_tick_data_provider.rs +++ b/examples/from_pool_key_with_tick_data_provider.rs @@ -1,3 +1,12 @@ +//! Example demonstrating pool creation with tick data provider and swap simulation +//! +//! # Prerequisites +//! - Environment variable MAINNET_RPC_URL must be set +//! - Requires the "extensions" feature +//! +//! # Note +//! This example uses mainnet block 17000000 for consistent results + use alloy::{ eips::BlockId, providers::{Provider, ProviderBuilder}, From fa55f20fb133a486e9e707372207cc6956009824 Mon Sep 17 00:00:00 2001 From: Shuhui Luo <107524008+shuhuiluo@users.noreply.github.com> Date: Tue, 10 Dec 2024 02:27:26 -0500 Subject: [PATCH 3/4] fmt --- examples/from_pool_key_with_tick_data_provider.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/from_pool_key_with_tick_data_provider.rs b/examples/from_pool_key_with_tick_data_provider.rs index f2a0c40..dd9b682 100644 --- a/examples/from_pool_key_with_tick_data_provider.rs +++ b/examples/from_pool_key_with_tick_data_provider.rs @@ -1,9 +1,9 @@ //! Example demonstrating pool creation with tick data provider and swap simulation -//! +//! //! # Prerequisites //! - Environment variable MAINNET_RPC_URL must be set //! - Requires the "extensions" feature -//! +//! //! # Note //! This example uses mainnet block 17000000 for consistent results From ed230e5e02158dcd4022d885727a21b2fb01f4ca Mon Sep 17 00:00:00 2001 From: Shuhui Luo <107524008+shuhuiluo@users.noreply.github.com> Date: Tue, 10 Dec 2024 02:32:57 -0500 Subject: [PATCH 4/4] Simplify Pool type by removing redundant generic. Eliminate the unnecessary generic type parameter `` for `EphemeralTickMapDataProvider` in several places, streamlining the code and documentation. This change helps to reduce complexity and potential errors without affecting functionality. Additionally, improve code comments to enhance clarity and maintain accuracy. --- README.md | 2 +- .../from_pool_key_with_tick_data_provider.rs | 4 ++-- src/extensions/pool.rs | 23 +++++++++---------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index f9b7d39..c00f470 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ The code below shows an example of creating a pool with a tick map data provider #[tokio::main] async fn main() { // Create a pool with a tick map data provider - let pool = Pool::>::from_pool_key_with_tick_data_provider( + let pool = Pool::::from_pool_key_with_tick_data_provider( 1, FACTORY_ADDRESS, wbtc.address(), diff --git a/examples/from_pool_key_with_tick_data_provider.rs b/examples/from_pool_key_with_tick_data_provider.rs index dd9b682..0ebd387 100644 --- a/examples/from_pool_key_with_tick_data_provider.rs +++ b/examples/from_pool_key_with_tick_data_provider.rs @@ -27,7 +27,7 @@ async fn main() { let weth = token!(1, "C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", 18, "WETH"); // Create a pool with a tick map data provider - let pool = Pool::>::from_pool_key_with_tick_data_provider( + let pool = Pool::::from_pool_key_with_tick_data_provider( 1, FACTORY_ADDRESS, wbtc.address(), @@ -64,6 +64,6 @@ async fn main() { let amount_out = U256::abi_decode(res.as_ref(), true).unwrap(); println!("Quoter amount out: {}", amount_out); - // Assert that the amounts are equal + // Compare local calculation with on-chain quoter to ensure accuracy assert_eq!(U256::from_big_int(local_amount_out.quotient()), amount_out); } diff --git a/src/extensions/pool.rs b/src/extensions/pool.rs index fe1f1a9..8ad168a 100644 --- a/src/extensions/pool.rs +++ b/src/extensions/pool.rs @@ -132,18 +132,17 @@ impl Pool> { /// let rpc_url = std::env::var("MAINNET_RPC_URL").unwrap().parse().unwrap(); /// let provider = ProviderBuilder::new().on_http(rpc_url); /// let block_id = Some(BlockId::from(17000000)); - /// let pool = - /// Pool::>::from_pool_key_with_tick_data_provider( - /// 1, - /// FACTORY_ADDRESS, - /// address!("2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"), - /// address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), - /// FeeAmount::LOW, - /// provider, - /// block_id, - /// ) - /// .await - /// .unwrap(); + /// let pool = Pool::::from_pool_key_with_tick_data_provider( + /// 1, + /// FACTORY_ADDRESS, + /// address!("2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"), + /// address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), + /// FeeAmount::LOW, + /// provider, + /// block_id, + /// ) + /// .await + /// .unwrap(); /// } /// ``` #[inline]