### Run Default Quickstart Example Source: https://github.com/propeller-heads/tycho-simulation/blob/main/examples/quickstart/Readme.md Execute the default quickstart example to trade 10 USDC to WETH on Ethereum Mainnet. Ensure your RPC_URL is set. ```bash export RPC_URL= cargo run --release --example quickstart ``` -------------------------------- ### Run RFQ Quickstart Example Source: https://github.com/propeller-heads/tycho-simulation/blob/main/examples/rfq_quickstart/Readme.md Execute the rfq_quickstart example to request price levels for a default token pair on Ethereum Mainnet. ```bash cargo run --release --example rfq_quickstart ``` -------------------------------- ### Run Quickstart with Private Key Source: https://github.com/propeller-heads/tycho-simulation/blob/main/examples/quickstart/Readme.md Execute the quickstart example after setting your private key as an environment variable. This is required to execute or simulate the best swap. Ensure HISTFILE is unset to avoid saving the private key to history. ```bash unset HISTFILE export PRIVATE_KEY= cargo run --release --example quickstart ``` -------------------------------- ### Run Quickstart with Custom Trade Parameters Source: https://github.com/propeller-heads/tycho-simulation/blob/main/examples/quickstart/Readme.md Run the quickstart example with custom trade parameters, specifying sell and buy tokens, sell amount, and the target chain. Ensure your RPC_URL is set for the specified chain. ```bash export RPC_URL= cargo run --release --example quickstart -- --sell-token "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" --buy-token "0x4200000000000000000000000000000000000006" --sell-amount 10 --chain "base" ``` -------------------------------- ### Run RFQ Quickstart with Custom Parameters Source: https://github.com/propeller-heads/tycho-simulation/blob/main/examples/rfq_quickstart/Readme.md Run the rfq_quickstart example with custom sell/buy tokens, sell amount, and chain parameters. ```bash cargo run --release --example rfq_quickstart -- --sell-token "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb" --buy-token "0x4200000000000000000000000000000000000006" --sell-amount 10 --chain "base" ``` -------------------------------- ### Install Twine for Publishing Source: https://github.com/propeller-heads/tycho-simulation/blob/main/tycho_simulation_py/Readme.md Install the twine package if you need to publish wheels to a repository. ```bash pip install twine ``` -------------------------------- ### Run Serialized State Example Source: https://github.com/propeller-heads/tycho-simulation/blob/main/examples/use_serialized_state/Readme.md Execute the example to see how serialized state is used. This command assumes you are in the project's root directory. ```bash cargo run --example use_serialized_state ``` -------------------------------- ### Run Price Printer Example Source: https://github.com/propeller-heads/tycho-simulation/blob/main/examples/price_printer/Readme.md Execute the price printer example by setting the RPC URL and providing a TVL threshold and chain. Ensure you replace placeholders with your specific values. ```bash export RPC_URL= cargo run --release --example price_printer -- --tvl-threshold 1000 --chain ``` -------------------------------- ### Install Python Wheel Source: https://github.com/propeller-heads/tycho-simulation/blob/main/tycho_simulation_py/Readme.md After building the wheel, install it into your target Python environment using pip. ```bash pip install ``` -------------------------------- ### Build Project with Forge Source: https://github.com/propeller-heads/tycho-simulation/blob/main/token-proxy/README.md Use this command to compile your smart contracts. Ensure Foundry is installed. ```shell forge build ``` -------------------------------- ### Install tycho-simulation-py from CodeArtifact Source: https://github.com/propeller-heads/tycho-simulation/blob/main/tycho_simulation_py/Readme.md Use this command to install the tycho-simulation-py package from AWS CodeArtifact. Ensure your AWS CLI is configured correctly. ```shell aws --region eu-central-1 codeartifact pip --tool twine --domain propeller --domain-owner 827659017777 --repository protosim pip install tycho-simulation-py ``` -------------------------------- ### Get Cast Help Source: https://github.com/propeller-heads/tycho-simulation/blob/main/token-proxy/README.md Display help information for the Cast tool, detailing its subcommands for EVM interaction. ```shell cast --help ``` -------------------------------- ### Start Local Node with Anvil Source: https://github.com/propeller-heads/tycho-simulation/blob/main/token-proxy/README.md Launch a local Ethereum node using Anvil. This is useful for local development and testing. ```shell anvil ``` -------------------------------- ### Set RFQ WebSocket Credentials Source: https://github.com/propeller-heads/tycho-simulation/blob/main/examples/rfq_quickstart/Readme.md Set your Bebop and Hashflow WebSocket API credentials as environment variables before running the quickstart. ```bash export BEBOP_USER= export BEBOP_KEY= export HASHFLOW_USER= export HASHFLOW_KEY= ``` -------------------------------- ### Get Anvil Help Source: https://github.com/propeller-heads/tycho-simulation/blob/main/token-proxy/README.md Display help information for the Anvil local node runner. This outlines its configuration and usage options. ```shell anvil --help ``` -------------------------------- ### Get Forge Help Source: https://github.com/propeller-heads/tycho-simulation/blob/main/token-proxy/README.md Display help information for the Forge command-line tool. This provides an overview of available commands and options. ```shell forge --help ``` -------------------------------- ### Build and install tycho-simulation-py in development mode Source: https://github.com/propeller-heads/tycho-simulation/blob/main/tycho_simulation_py/Readme.md Use `maturin develop` to build and install the tycho_simulation_py module directly into your current Python virtual environment. This is faster but may result in less optimized code compared to a release build. ```shell maturin develop ``` -------------------------------- ### Run Tycho Integration Test with Custom Parameters Source: https://github.com/propeller-heads/tycho-simulation/blob/main/tycho-integration-test/README.md Execute the Tycho integration test with specific command-line arguments to customize the test environment. This example disables RFQ, specifies a protocol, and adjusts simulation and parallelism settings. ```bash # Run with custom parameters cargo run --package tycho-integration-test -- \ --chain ethereum \ --disable-rfq \ --protocols uniswap_v2 \ --max-simulations 20 \ --parallel-simulations 10 ``` -------------------------------- ### Install maturin in Python virtual environment Source: https://github.com/propeller-heads/tycho-simulation/blob/main/tycho_simulation_py/Readme.md Install the maturin build tool into your activated Python virtual environment. This is a prerequisite for building the Rust crate as a Python package. ```shell pip install maturin ``` -------------------------------- ### Query Uniswap V3 State and Calculate Amount Out Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Process a `UniswapV3State` to get the spot price and calculate the output amount for a swap. This AMM uses concentrated liquidity and tick-based fee tiers. ```rust use tycho_simulation::evm::protocol::uniswap_v3::state::UniswapV3State; use tycho_common::simulation::protocol_sim::ProtocolSim; // UniswapV3State is typically constructed by the stream decoder from live data. // When received in an Update, use it like any other ProtocolSim: fn process_v3_pool(state: &UniswapV3State, sell_token: &tycho_common::models::token::Token, buy_token: &tycho_common::models::token::Token) { let spot = state.spot_price(sell_token, buy_token).unwrap(); println!("V3 spot price: {:.8}", spot); println!("Fee tier: {:.4}%", state.fee() * 100.0); let amount_in = num_bigint::BigUint::from(1_000_000u64); // 1 USDC if let Ok(result) = state.get_amount_out(amount_in, sell_token, buy_token) { println!("V3 amount out: {}", result.amount); println!("Ticks crossed gas: {}", result.gas); } } ``` -------------------------------- ### Run Tycho Integration Test Locally Source: https://github.com/propeller-heads/tycho-simulation/blob/main/tycho-integration-test/README.md Set environment variables for logging, Tycho indexer URL, and RPC endpoint before running the integration test. This example shows default settings. ```bash # Set required environment variables export RUST_LOG=tycho_integration_test=info,tycho_test=debug,error export TYCHO_URL=tycho-dev.propellerheads.xyz export RPC_URL=https://your-rpc-endpoint # Run with default settings cargo run --package tycho-integration-test ``` -------------------------------- ### Get Default Tycho Server URL Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Retrieve the default Tycho server URL for a given chain, falling back to environment variables. Useful when `TYCHO_URL` is not set. ```rust use tycho_simulation::utils::get_default_url; use tycho_common::models::Chain; fn resolve_tycho_url(chain: Chain) -> String { std::env::var("TYCHO_URL") .unwrap_or_else(|_| { get_default_url(&chain) .unwrap_or_else(|| panic!("No default URL for chain {chain}")) }) } fn main() { println!("{}", resolve_tycho_url(Chain::Ethereum)); // tycho-beta.propellerheads.xyz println!("{}", resolve_tycho_url(Chain::Base)); // tycho-base-beta.propellerheads.xyz println!("{}", resolve_tycho_url(Chain::Unichain)); // tycho-unichain-beta.propellerheads.xyz } ``` -------------------------------- ### Get Maximum Tradeable Amounts (Uniswap V2) Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Calculates the maximum input and output amounts for a trade while maintaining approximately 90% price impact. This is crucial for optimizers to bound search spaces in routing algorithms. ```rust use tycho_simulation::evm::protocol::uniswap_v2::state::UniswapV2State; use tycho_common::{simulation::protocol_sim::ProtocolSim, Bytes}; use alloy::primitives::U256; use std::str::FromStr; fn main() { let state = UniswapV2State::new( U256::from_str("1000000000").unwrap(), // reserve0 U256::from_str("500000000").unwrap(), // reserve1 ); let token0 = Bytes::from_str("0x0000000000000000000000000000000000000000").unwrap(); let token1 = Bytes::from_str("0x0000000000000000000000000000000000000001").unwrap(); match state.get_limits(token0, token1) { Ok((max_in, max_out)) => { println!("Max sell (token0): {max_in}"); println!("Max buy (token1): {max_out}"); // Use max_in to cap amount_in before calling get_amount_out } Err(e) => eprintln!("Error: {e:?}"), } } ``` -------------------------------- ### Get Current Marginal Price (Uniswap V3) Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Retrieves the current marginal price of a token pair, including protocol fees. Useful for understanding real-time market prices in AMMs. ```rust use tycho_simulation::evm::protocol::uniswap_v3::state::UniswapV3State; use tycho_common::{models::{token::Token, Chain}, simulation::protocol_sim::ProtocolSim, Bytes}; use std::str::FromStr; fn print_price(state: &dyn ProtocolSim, base: &Token, quote: &Token) { match state.spot_price(base, quote) { Ok(price) => println!( "Price {}/{}: {:.8} (fee: {:.4}%)", base.symbol, quote.symbol, price, state.fee() * 100.0 ), Err(e) => eprintln!("Price error: {e:?}"), } } // Example: reading spot price from an Update message in the stream fn process_update(update: &tycho_simulation::protocol::models::Update) { for (pool_id, state) in &update.states { if let Some(component) = update.new_pairs.get(pool_id) { let tokens = &component.tokens; if tokens.len() >= 2 { print_price(state.as_ref(), &tokens[0], &tokens[1]); } } } } ``` -------------------------------- ### Initialize Account with State Overrides Source: https://github.com/propeller-heads/tycho-simulation/blob/main/src/evm/Readme.md Use `state.init_account()` to manually configure account information, including balance, nonce, code, and permanent storage slots. The `mocked` parameter determines if the account queries external data. ```rust state.init_account( address, account, Some(permanent_storage), mocked, ); ``` -------------------------------- ### Initialize and Query Uniswap V2 State Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Create a `UniswapV2State` with initial reserves and calculate the output amount for a swap. This implementation includes a 0.3% fee. ```rust use tycho_simulation::evm::protocol::uniswap_v2::state::UniswapV2State; use tycho_common::{models::{token::Token, Chain}, simulation::protocol_sim::ProtocolSim, Bytes}; use num_bigint::BigUint; use alloy::primitives::U256; use std::str::FromStr; fn main() { // USDC-WETH pool: realistic mainnet reserves let state = UniswapV2State::new( U256::from_str("6770398782322527849696614").unwrap(), // reserve0 (token with lower address) U256::from_str("5124813135806900540214").unwrap(), // reserve1 ); println!("Fee: {:.3}%", state.fee() * 100.0); // 0.300% let t0 = Token::new( &Bytes::from_str("0x0000000000000000000000000000000000000000").unwrap(), "T0", 18, 0, &[Some(10_000)], Chain::Ethereum, 100, ); let t1 = Token::new( &Bytes::from_str("0x0000000000000000000000000000000000000001").unwrap(), "T1", 18, 0, &[Some(10_000)], Chain::Ethereum, 100, ); let amount_in = BigUint::from_str("10000000000000000000000").unwrap(); // 10,000 tokens let result = state.get_amount_out(amount_in, &t0, &t1).unwrap(); println!("Amount out: {}", result.amount); // 7535635391574243447 println!("Gas estimate: {}", result.gas); // 120000 } ``` -------------------------------- ### `UniswapV3State` methods Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Provides methods for interacting with Uniswap V3 concentrated liquidity pools, including calculating spot prices, fees, and output amounts for swaps. ```APIDOC ## `UniswapV3State` — Concentrated liquidity AMM state Represents a Uniswap V3 (or PancakeSwap V3) pool with concentrated liquidity, tick-based fee tiers, and a square-root price encoding. Supports get_amount_out, spot_price, get_limits (capped to gas budget), and query_pool_swap via CLMM arithmetic. ### Methods #### `spot_price` Calculates the current spot price between two tokens in the V3 pool. - **Parameters**: `sell_token: &Token`, `buy_token: &Token` - **Returns**: `Result` #### `get_amount_out` Calculates the amount of output tokens for a given input amount in a V3 pool. - **Parameters**: `amount_in: BigUint`, `sell_token: &Token`, `buy_token: &Token` - **Returns**: `Result` - `amount`: `BigUint` - The calculated amount of output tokens. - `gas`: `u64` - An estimate of the gas cost. ### Request Example ```rust use tycho_simulation::evm::protocol::uniswap_v3::state::UniswapV3State; use tycho_common::models::token::Token; use num_bigint::BigUint; // Assuming 'state' is an initialized UniswapV3State object let sell_token: Token = ...; let buy_token: Token = ...; let spot = state.spot_price(&sell_token, &buy_token).unwrap(); println!("V3 spot price: {:.8}", spot); let amount_in = BigUint::from(1_000_000u64); // 1 USDC if let Ok(result) = state.get_amount_out(amount_in, &sell_token, &buy_token) { println!("V3 amount out: {}", result.amount); println!("Ticks crossed gas: {}", result.gas); } ``` ``` -------------------------------- ### Generate Contract Binaries and ABI Source: https://github.com/propeller-heads/tycho-simulation/blob/main/token-proxy/README.md Compile the specified Solidity file to generate its runtime binary and ABI. The output is saved to the 'assets' directory. ```shell solc --optimize --bin-runtime --abi src/TokenProxy.sol -o assets ``` -------------------------------- ### Calculate Swap Output Amount with ProtocolSim::get_amount_out Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Calculates the output amount for a swap given an exact input amount, sell token, and buy token. Returns the output amount, estimated gas, and the new pool state. The original state remains unchanged. ```rust use tycho_simulation::evm::protocol::uniswap_v2::state::UniswapV2State; use tycho_common::{models::{token::Token, Chain}, simulation::protocol_sim::ProtocolSim, Bytes}; use num_bigint::BigUint; use alloy::primitives::U256; use std::str::FromStr; fn main() { // Create a Uniswap V2 pool state with USDC/WETH reserves let state = UniswapV2State::new( U256::from_str("36925554990922").unwrap(), // reserve0: USDC (6 decimals) U256::from_str("30314846538607556521556").unwrap(), // reserve1: WETH (18 decimals) ); let usdc = Token::new( &Bytes::from_str("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48").unwrap(), "USDC", 6, 0, &[Some(10_000)], Chain::Ethereum, 100, ); let weth = Token::new( &Bytes::from_str("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2").unwrap(), "WETH", 18, 0, &[Some(10_000)], Chain::Ethereum, 100, ); // Sell 1000 USDC (1000 * 10^6 = 1_000_000_000 raw units) let amount_in = BigUint::from(1_000_000_000u64); match state.get_amount_out(amount_in, &usdc, &weth) { Ok(result) => { // result.amount: WETH received (18 decimals) let weth_out = result.amount.to_string().parse::().unwrap() / 1e18; println!("WETH out: {{:.6}}", weth_out); println!("Gas estimate: {}", result.gas); // new_state reflects pool after the swap (original state is unmodified) let new_state = result.new_state; println!("New spot price: {{:.6}}", new_state.spot_price(&usdc, &weth).unwrap()); } Err(e) => eprintln!("Simulation error: {{:?}}", e), } } ``` -------------------------------- ### Set Private Key for Execution Source: https://github.com/propeller-heads/tycho-simulation/blob/main/examples/rfq_quickstart/Readme.md Unset your terminal history and export your private key as an environment variable to enable swap execution or simulation. ```bash unset HISTFILE export PRIVATE_KEY= ``` -------------------------------- ### Run All Checks Source: https://github.com/propeller-heads/tycho-simulation/blob/main/CLAUDE.md Execute all project checks, including formatting and linting. ```bash ./check.sh ``` -------------------------------- ### Interact with EVM using Cast Source: https://github.com/propeller-heads/tycho-simulation/blob/main/token-proxy/README.md Use the Cast tool for interacting with the EVM, sending transactions, and retrieving chain data. Use subcommands for specific actions. ```shell cast ``` -------------------------------- ### Run All Tests Source: https://github.com/propeller-heads/tycho-simulation/blob/main/CLAUDE.md Execute all tests across the workspace with all features enabled. ```bash cargo nextest run --workspace --lib --all-targets --all-features ``` -------------------------------- ### Run EVM Transaction Simulation with SimulationEngine Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Use `SimulationEngine` to execute arbitrary EVM transactions against a pre-cached database. This is useful for simulating on-chain interactions like approvals off-chain. Ensure necessary imports are included. ```rust use tycho_simulation::evm::{ simulation::{SimulationEngine, SimulationParameters}, engine_db::tycho_db::PreCachedDB, }; use alloy::primitives::{Address, U256}; use std::str::FromStr; fn run_simulation(db: PreCachedDB) { let engine = SimulationEngine::new(db, false /* traces off */); let params = SimulationParameters { caller: Address::from_str("0xDeaDBeef00000000000000000000000000000000").unwrap(), to: Address::from_str("0xContractAddress00000000000000000000000000").unwrap(), data: hex::decode("70a08231000000000000000000000000DeaDBeef00000000000000000000000000000000").unwrap(), value: U256::ZERO, gas_limit: Some(500_000), overrides: None, block_number: None, timestamp: None, transient_storage: None, }; match engine.simulate(¶ms) { Ok(result) => { println!("Result bytes: 0x{}", hex::encode(&result.result)); println!("Gas used: {}", result.gas_used); println!("State changes: {} accounts modified", result.state_updates.len()); } Err(e) => eprintln!("Simulation error: {e:?}"), } } ``` -------------------------------- ### Run Tests with Forge Source: https://github.com/propeller-heads/tycho-simulation/blob/main/token-proxy/README.md Execute your smart contract tests using the Forge testing framework. This command runs all tests in your project. ```shell forge test ``` -------------------------------- ### Format Code Source: https://github.com/propeller-heads/tycho-simulation/blob/main/CLAUDE.md Format all code in the workspace. Requires a nightly Rust toolchain. ```bash cargo +nightly fmt --all ``` -------------------------------- ### Build tycho-simulation wheel in manylinux Docker Source: https://github.com/propeller-heads/tycho-simulation/blob/main/tycho_simulation_py/Readme.md Execute this script from the repository root to build a wheel file for tycho_simulation_py within a manylinux Docker environment. The resulting wheel will be placed in `tycho_simulation_py/target/wheels`. ```shell sudo ./tycho_simulation_py/build_tycho_simulation_wheel.sh ``` -------------------------------- ### `UniswapV2State::new` Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Constructs a new `UniswapV2State` representing a Uniswap V2 pool with initial token reserves. This state object implements the constant product formula `x * y = k` and supports fee calculations. ```APIDOC ## `UniswapV2State::new` — Initialize Uniswap V2 State Represents a Uniswap V2 (or fork) pool with two token reserves. Implements the constant product formula `x * y = k` with a 0.3% fee. Also used for SushiSwap V2 forks. Serializable/deserializable via `serde`. ### Method `UniswapV2State::new(reserve0: U256, reserve1: U256)` ### Parameters - **reserve0** (U256) - Required - The initial reserve amount for the first token. - **reserve1** (U256) - Required - The initial reserve amount for the second token. ### Request Example ```rust use tycho_simulation::evm::protocol::uniswap_v2::state::UniswapV2State; use alloy::primitives::U256; let state = UniswapV2State::new( U256::from_str("6770398782322527849696614").unwrap(), // reserve0 U256::from_str("5124813135806900540214").unwrap(), // reserve1 ); ``` ### Response - **state** (`UniswapV2State`) - An initialized Uniswap V2 state object. ``` -------------------------------- ### Deploy Contract with Forge Script Source: https://github.com/propeller-heads/tycho-simulation/blob/main/token-proxy/README.md Deploy your smart contracts using Forge's scripting capabilities. Replace placeholders with your actual RPC URL and private key. ```shell forge script script/Counter.s.sol:CounterScript --rpc-url --private-key ``` -------------------------------- ### Run Tycho Integration Test for Specific Blocks and Protocols Source: https://github.com/propeller-heads/tycho-simulation/blob/main/tycho-integration-test/README.md Execute the Tycho integration test for a defined number of blocks and specify the protocols to include in the test. ```bash cargo run --package tycho-integration-test -- \ --chain ethereum \ --max-blocks 10 \ --protocols uniswap_v2,uniswap_v3 ``` -------------------------------- ### Format Code with Forge Source: https://github.com/propeller-heads/tycho-simulation/blob/main/token-proxy/README.md Automatically format your Solidity code according to standard conventions. This helps maintain code readability and consistency. ```shell forge fmt ``` -------------------------------- ### Build Python Wheel with Maturin Source: https://github.com/propeller-heads/tycho-simulation/blob/main/tycho_simulation_py/Readme.md Use this command to build a release wheel for the Python bindings. Ensure your build environment matches the target Python version. ```bash maturin build --release ``` -------------------------------- ### Generate Gas Snapshots with Forge Source: https://github.com/propeller-heads/tycho-simulation/blob/main/token-proxy/README.md Create gas snapshots for your contract functions. This is useful for analyzing gas consumption and optimizing your code. ```shell forge snapshot ``` -------------------------------- ### Initialize EVMPoolState with ProtocolStreamBuilder Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Use EVMPoolState with PreCachedDB for complex protocols like Balancer V2/V3 and Curve. A filter_fn is required to exclude unsupported pool types. ```rust use tycho_simulation::evm:: protocol:: vm::state::EVMPoolState, filters::balancer_v2_pool_filter, engine_db::tycho_db::PreCachedDB, }; use tycho_client::feed::component_tracker::ComponentFilter; use tycho_common::models::Chain; // EVMPoolState is decoded automatically via the stream. // Must pass filter_fn to exclude unsupported pools. let stream = ProtocolStreamBuilder::new("tycho-beta.propellerheads.xyz", Chain::Ethereum) .auth_key(Some("sampletoken".to_string())) .exchange::>( "vm:balancer_v2", ComponentFilter::with_tvl_range(100.0, 100.0), Some(balancer_v2_pool_filter), // REQUIRED: filters known-broken pools ) // Access via Update.states like any other ProtocolSim: // update.states[pool_id].get_amount_out(amount_in, sell_token, buy_token) ; ``` -------------------------------- ### Compute Swap to Target Price (Uniswap V2) Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Computes the input and output amounts required to shift a pool's price to a specified target. This is primarily used for arbitrage calculations to align pool prices with external references. ```rust use tycho_simulation::evm::protocol::uniswap_v2::state::UniswapV2State; use tycho_common::{ models::{token::Token, Chain}, simulation::protocol_sim::{ProtocolSim, QueryPoolSwapParams, SwapConstraint, Price}, Bytes, }; use num_bigint::BigUint; use alloy::primitives::U256; use std::str::FromStr; fn main() { let state = UniswapV2State::new(U256::from(2_000_000u32), U256::from(1_000_000u32)); let token_in = Token::new( &Bytes::from_str("0x0000000000000000000000000000000000000000").unwrap(), "T0", 18, 0, &[Some(10_000)], Chain::Ethereum, 100, ); let token_out = Token::new( &Bytes::from_str("0x0000000000000000000000000000000000000001").unwrap(), "T1", 18, 0, &[Some(10_000)], Chain::Ethereum, 100, ); // Target: move pool price to 2/5 = 0.4 (from current 0.5) let target_price = Price::new(BigUint::from(2u32), BigUint::from(5u32)); let params = QueryPoolSwapParams::new( token_in, token_out, SwapConstraint::PoolTargetPrice { target: target_price, tolerance: 0.0, min_amount_in: None, max_amount_in: None, }, ); match state.query_pool_swap(¶ms) { Ok(pool_swap) => { println!("Amount in: {}", pool_swap.amount_in()); println!("Amount out: {}", pool_swap.amount_out()); } Err(e) => eprintln!("Unreachable or error: {e:?}"), } } ``` -------------------------------- ### Apply Incremental State Updates with delta_transition Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Use `delta_transition` to apply `ProtocolStateDelta` to update pool state in-place. This is called automatically by the decoder or can be used for manual state replay. ```rust use tycho_simulation::evm::protocol::uniswap_v2::state::UniswapV2State; use tycho_common::{ dto::ProtocolStateDelta, simulation::protocol_sim::{Balances, ProtocolSim}, Bytes, }; use alloy::primitives::U256; use std::collections::{HashMap, HashSet}; fn main() { let mut state = UniswapV2State::new( U256::from(1000u64), U256::from(1000u64), ); // Simulate receiving a delta from the Tycho stream let updated_attrs: HashMap = vec![ ("reserve0".to_string(), Bytes::from(1500u64.to_be_bytes().to_vec())), ("reserve1".to_string(), Bytes::from(2000u64.to_be_bytes().to_vec())), ] .into_iter() .collect(); let delta = ProtocolStateDelta { component_id: "0xPoolAddress".to_owned(), updated_attributes: updated_attrs, deleted_attributes: HashSet::new(), }; state .delta_transition(delta, &HashMap::new(), &Balances::default()) .expect("Transition failed"); assert_eq!(state.reserve0, U256::from(1500u64)); assert_eq!(state.reserve1, U256::from(2000u64)); println!("State updated: reserve0={}, reserve1={}", state.reserve0, state.reserve1); } ``` -------------------------------- ### Build Live Multi-Protocol State Stream with ProtocolStreamBuilder Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Configures and constructs an async stream that emits `Update` messages for on-chain blocks. Handles snapshot bootstrapping, delta updates, reconnects, and supervisor aggregation. Use `.exchange::(name, filter, filter_fn)` to add exchanges, specifying the decoder type. ```rust use tycho_simulation::evm:: protocol::uniswap_v2::state::UniswapV2State, protocol::uniswap_v3::state::UniswapV3State, protocol::uniswap_v4::state::UniswapV4State, protocol::filters::{balancer_v2_pool_filter, curve_pool_filter}, protocol::vm::state::EVMPoolState, engine_db::tycho_db::PreCachedDB, stream::ProtocolStreamBuilder, use tycho_client::feed::component_tracker::ComponentFilter; use tycho_common::models::Chain; use futures::StreamExt; use std::collections::HashSet; #[tokio::main] async fn main() { let all_tokens = /* load_all_tokens(...).await.unwrap() */ Default::default(); let tvl_filter = ComponentFilter::with_tvl_range(100.0, 100.0); let mut stream = ProtocolStreamBuilder::new("tycho-beta.propellerheads.xyz", Chain::Ethereum) .auth_key(Some("sampletoken".to_string())) .skip_state_decode_failures(true) // log decode errors, don't panic .exchange::("uniswap_v2", tvl_filter.clone(), None) .exchange::("sushiswap_v2", tvl_filter.clone(), None) .exchange::("uniswap_v3", tvl_filter.clone(), None) .exchange::("uniswap_v4", tvl_filter.clone(), None) .exchange::>( "vm:balancer_v2", tvl_filter.clone(), Some(balancer_v2_pool_filter), // required for vm: protocols ) .exchange::>( "vm:curve", tvl_filter.clone(), Some(curve_pool_filter), ) .blocklist_components(HashSet::new()) .set_tokens(all_tokens) .await .build() .await .expect("Failed to build stream"); while let Some(msg) = stream.next().await { match msg { Ok(update) => { println!("Block {}", update.block_number_or_timestamp); println!(" New pools: {}", update.new_pairs.len()); println!(" Updated states: {}", update.states.len()); println!(" Removed pools: {}", update.removed_pairs.len()); } Err(e) => eprintln!("Stream decode error: {{:?}}", e), } } } ``` -------------------------------- ### Build RFQStreamBuilder with multiple clients Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Aggregates price levels from multiple RFQ providers into a unified Update stream. The stream runs in a background task and sends Update messages over an mpsc channel. ```rust use tycho_simulation::rfq:: stream::RFQStreamBuilder, protocols:: bebop::{client_builder::BebopClientBuilder, state::BebopState}, hashflow::{client_builder::HashflowClientBuilder, state::HashflowState}, }; use tycho_common::models::Chain; use tokio::sync::mpsc; use std::collections::HashSet; use tycho_common::Bytes; use std::str::FromStr; #[tokio::main] async fn main() { let all_tokens = /* load_all_tokens(...).await.unwrap() */ Default::default(); let mut rfq_tokens = HashSet::new(); rfq_tokens.insert(Bytes::from_str("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48").unwrap()); // USDC rfq_tokens.insert(Bytes::from_str("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2").unwrap()); // WETH let bebop_client = BebopClientBuilder::new(Chain::Ethereum, "user".to_string(), "key".to_string()) .tokens(rfq_tokens.clone()) .tvl_threshold(1000.0) .build() .expect("Failed to create Bebop client"); let rfq_stream = RFQStreamBuilder::new() .set_tokens(all_tokens) .await .add_client::("bebop", Box::new(bebop_client)); let (tx, mut rx) = mpsc::channel(100); tokio::spawn(rfq_stream.build(tx)); while let Some(update) = rx.recv().await { for (pool_id, state) in &update.states { println!("RFQ update from pool {pool_id}, timestamp {}", update.block_number_or_timestamp); } } } ``` -------------------------------- ### ProtocolSim::query_pool_swap Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Computes the input and output amounts required to adjust the pool's price to a specified target price. This is commonly used for arbitrage calculations to align a pool's price with an external reference. ```APIDOC ## `ProtocolSim::query_pool_swap` — Compute swap to a target price Calculates the input/output amounts needed to move the pool's price to a specified target price. Used for arbitrage computations where the goal is to bring a pool into alignment with an external reference price. Currently supports `SwapConstraint::PoolTargetPrice`. ### Parameters - `params`: Configuration for the swap query, including tokens, swap constraint (e.g., target price), and optional bounds. ### Returns - `Ok(PoolSwap)`: An object containing the calculated `amount_in` and `amount_out`. - `Err(e)`: An error if the swap calculation fails. ``` -------------------------------- ### Upload Wheel to CodeArtifact Source: https://github.com/propeller-heads/tycho-simulation/blob/main/tycho_simulation_py/Readme.md Upload the built wheel to the configured code artifact repository. Ensure the version in the filename matches your project's version. ```bash twine upload --repository codeartifact target/wheels/tycho_simulation_py-[VERSION]*.whl ``` -------------------------------- ### Run Tycho Integration Test with Specific Components Source: https://github.com/propeller-heads/tycho-simulation/blob/main/tycho-integration-test/README.md Configure the Tycho integration test to always test specific component IDs, ensuring focused testing on critical parts of the system. ```bash # Run with specific components to always test cargo run --package tycho-integration-test -- \ --always-test-components component_id_1,component_id_2,component_id_3 ``` -------------------------------- ### Load All Tokens from Tycho RPC Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Fetches all known ERC-20 tokens for a given chain from the Tycho RPC endpoint. This map is required before building any protocol stream for correct decoding of pool states. Accepts optional filters for minimum quality and maximum days since last trade. ```rust use tycho_simulation::utils::load_all_tokens; use tycho_common::models::Chain; #[tokio::main] async fn main() { let all_tokens = load_all_tokens( "tycho-beta.propellerheads.xyz", // tycho_url (no https:// prefix) false, // no_tls: use HTTPS Some("sampletoken"), // auth_key true, // gzip compression Chain::Ethereum, Some(100), // min_quality (0-100) Some(42), // max_days_since_last_trade ) .await .expect("Failed to load tokens"); println!("Loaded {} tokens", all_tokens.len()); // Token lookup by address bytes let usdc_addr = tycho_common::Bytes::from( hex::decode("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48").unwrap() ); if let Some(usdc) = all_tokens.get(&usdc_addr) { println!("USDC decimals: {}", usdc.decimals); // 6 } } ``` -------------------------------- ### Login to AWS CodeArtifact Source: https://github.com/propeller-heads/tycho-simulation/blob/main/tycho_simulation_py/Readme.md Authenticate with AWS CodeArtifact to upload wheels. Replace placeholders with your specific region, domain, and repository details. ```bash aws --region eu-central-1 codeartifact login --tool twine --domain propeller --domain-owner 827659017777 --repository protosim ``` -------------------------------- ### Run Specific Test Source: https://github.com/propeller-heads/tycho-simulation/blob/main/CLAUDE.md Execute a specific test by name across the workspace with all features enabled. ```bash cargo nextest run --workspace --all-targets --all-features -E 'test(my_test_name)' ``` -------------------------------- ### `ProtocolSim::delta_transition` Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Applies incremental state updates to a pool's state based on a `ProtocolStateDelta`. This method is typically called automatically by the decoder but can be invoked manually for state replay. ```APIDOC ## `ProtocolSim::delta_transition` — Apply incremental state updates Updates the pool state in-place when a `ProtocolStateDelta` arrives from the stream (e.g., new reserves after an on-chain swap). Called automatically by the decoder internally; can also be called manually when replaying state changes. ### Method (Implicitly called via `state.delta_transition` in the example) ### Parameters - `delta`: `ProtocolStateDelta` - The state changes to apply. - `other_params`: `HashMap` - Additional parameters (context-dependent). - `balances`: `Balances` - Current balances. ### Request Example ```rust use tycho_simulation::evm::protocol::uniswap_v2::state::UniswapV2State; use tycho_common::{dto::ProtocolStateDelta, simulation::protocol_sim::{Balances, ProtocolSim}, Bytes}; use alloy::primitives::U256; use std::collections::{HashMap, HashSet}; let mut state = UniswapV2State::new(U256::from(1000u64), U256::from(1000u64)); let updated_attrs: HashMap = vec![ ("reserve0".to_string(), Bytes::from(1500u64.to_be_bytes().to_vec())), ("reserve1".to_string(), Bytes::from(2000u64.to_be_bytes().to_vec())), ] .into_iter() .collect(); let delta = ProtocolStateDelta { component_id: "0xPoolAddress".to_owned(), updated_attributes: updated_attrs, deleted_attributes: HashSet::new(), }; state.delta_transition(delta, &HashMap::new(), &Balances::default()).expect("Transition failed"); ``` ### Response (In-place modification of the state object. Returns `Result<(), anyhow::Error>` indicating success or failure.) ``` -------------------------------- ### Load component blocklist from TOML Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Loads a set of component IDs to exclude from the stream. Accepts an optional path to a TOML file; if omitted, uses the embedded default blocklist. ```rust use tycho_simulation::utils::load_blocklist; use std::path::Path; fn main() { // Use the embedded default blocklist let default_blocklist = load_blocklist(None).expect("Failed to load default blocklist"); println!("Default blocklist has {} entries", default_blocklist.len()); // Load a custom blocklist from a TOML file: // [blocklist] // components = [ // "0xDeAdBeEf...", // "0xBaDPool...", // ] let custom_blocklist = load_blocklist(Some(Path::new("my_blocklist.toml"))) .expect("Failed to load custom blocklist"); println!("Custom blocklist has {} entries", custom_blocklist.len()); } ``` -------------------------------- ### Handle Block Updates in Tycho Simulation Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Processes `Update` messages from the protocol stream to display block information, sync states, new/removed pools, and calculate potential output amounts for token swaps. Requires `tycho-simulation` and `tycho-common` crates. ```rust use tycho_simulation::protocol::models::Update; use tycho_common::simulation::protocol_sim::ProtocolSim; use num_bigint::BigUint; fn handle_block_update(update: Update, amount_in: BigUint) { println!("=== Block {} ===", update.block_number_or_timestamp); // Sync status per registered protocol for (protocol, state) in &update.sync_states { println!(" {}: {:?}", protocol, state); } // New pools this block for (id, component) in &update.new_pairs { println!(" New pool: {} ({})", id, component.protocol_system); } // Updated states — use for pricing for (id, state) in &update.states { let component = update.new_pairs.get(id); if let Some(comp) = component { if comp.tokens.len() >= 2 { let sell = &comp.tokens[0]; let buy = &comp.tokens[1]; if let Ok(result) = state.get_amount_out(amount_in.clone(), sell, buy) { println!(" {}: {} {} out", id, result.amount, buy.symbol); } } } } // Removed pools for (id, _) in &update.removed_pairs { println!(" Removed: {id}"); } } ``` -------------------------------- ### Deserialize Pool State with `typetag` Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Load and analyze serialized pool states from JSON. Requires `typetag` for dynamic dispatch with serde. ```rust use serde::Deserialize; use tycho_simulation::tycho_common::{models::token::Token, simulation::protocol_sim::ProtocolSim}; #[derive(Debug, Deserialize)] struct Pool { tokens: Vec, state: Box, } fn main() { // data.json contains serialized pool states (e.g. UniswapV2State, UniswapV3State) let json = std::fs::read_to_string("examples/use_serialized_state/data.json").unwrap(); let pools: Vec = serde_json::from_str(&json).unwrap(); for (i, pool) in pools.iter().enumerate() { let token_in = &pool.tokens[0]; let token_out = &pool.tokens[1]; let amount_in = token_in.one(); // 1 unit in smallest denomination match pool.state.get_amount_out(amount_in, token_in, token_out) { Ok(result) => { let human_out = result.amount.to_string().parse::().unwrap() / 10f64.powi(token_out.decimals as i32); println!("Pool #{}: 1 {} -> {:.6} {} (gas: {})", i + 1, token_in.symbol, human_out, token_out.symbol, result.gas); } Err(e) => println!("Pool #{} error: {e}", i + 1), } } } ``` -------------------------------- ### `UniswapV2State::get_amount_out` Source: https://context7.com/propeller-heads/tycho-simulation/llms.txt Calculates the amount of output tokens received for a given amount of input tokens, considering the pool's reserves and the constant product formula. This method is part of the `ProtocolSim` trait. ```APIDOC ## `UniswapV2State::get_amount_out` — Calculate output amount Calculates the amount of output tokens for a given input amount based on the Uniswap V2 constant product formula. ### Method `get_amount_out(amount_in: BigUint, token_in: &Token, token_out: &Token) -> Result` ### Parameters - **amount_in** (`BigUint`) - Required - The amount of input tokens. - **token_in** (`&Token`) - Required - The token being sold. - **token_out** (`&Token`) - Required - The token being bought. ### Request Example ```rust use tycho_simulation::evm::protocol::uniswap_v2::state::UniswapV2State; use tycho_common::{models::token::Token, Bytes}; use num_bigint::BigUint; use std::str::FromStr; // Assuming 'state' is an initialized UniswapV2State object let amount_in = BigUint::from_str("10000000000000000000000").unwrap(); // 10,000 tokens let t0 = Token::new(&Bytes::from_str("0x...").unwrap(), "T0", 18, 0, &[], Chain::Ethereum, 100); let t1 = Token::new(&Bytes::from_str("0x...").unwrap(), "T1", 18, 0, &[], Chain::Ethereum, 100); let result = state.get_amount_out(amount_in, &t0, &t1).unwrap(); ``` ### Response - **amount** (`BigUint`) - The calculated amount of output tokens. - **gas** (`u64`) - An estimate of the gas cost for the operation. ``` -------------------------------- ### Lint Code Source: https://github.com/propeller-heads/tycho-simulation/blob/main/CLAUDE.md Run clippy linter on the workspace code, treating warnings as errors. All features are enabled. ```bash cargo clippy --workspace --lib --all-targets --all-features -- -D warnings ```