waterpump-evm-pool-sdk 0.1.0

EVM pool SDK — viewers, infusers, harvesters, swappers for Uniswap V3/V4, PancakeSwap, Slipstream, Shadow, Algebra
Documentation
use alloy::{network::Ethereum, primitives::U256, providers::Provider};
use anyhow::{Context, Result};
use tracing::info;

/// Result type for adjusted gas prices
#[derive(Debug, Clone)]
pub struct AdjustedGasPrices {
    pub max_priority_fee_per_gas: Option<U256>,
    pub max_fee_per_gas: Option<U256>,
}

/// Dynamically adjusts gas prices based on current network conditions.
///
/// This function:
/// 1. Fetches current network gas price estimates
/// 2. Applies a buffer multiplier to current estimates for reliability during
///    network volatility
/// 3. Returns the maximum of provided values or adjusted current estimates
///
/// # Arguments
///
/// * `provider` - The Ethereum provider to fetch gas prices from
/// * `provided_max_priority_fee_per_gas` - Optional provided priority fee (tip)
/// * `provided_max_fee_per_gas` - Optional provided max fee per gas
/// * `buffer_multiplier` - Buffer multiplier as a percentage (e.g., 110 for
///   110% = 1.1x)
///
/// # Returns
///
/// Returns `AdjustedGasPrices` with the dynamically adjusted gas prices.
///
/// # Example
///
/// ```ignore
/// let adjusted = adjust_gas_prices(
///     &provider,
///     swap_options.max_priority_fee_per_gas,
///     swap_options.max_fee_per_gas,
///     110u64 // 10% buffer
/// ).await?;
/// ```
#[tracing::instrument(skip(provider), fields(
    provided_max_priority_fee_per_gas = ?provided_max_priority_fee_per_gas,
    provided_max_fee_per_gas = ?provided_max_fee_per_gas,
    buffer_multiplier = buffer_multiplier
))]
pub async fn adjust_gas_prices<P: Provider<Ethereum> + ?Sized>(
    provider: &P,
    provided_max_priority_fee_per_gas: Option<U256>,
    provided_max_fee_per_gas: Option<U256>,
    buffer_multiplier: u64,
) -> Result<AdjustedGasPrices> {
    // Get current gas price estimates dynamically from the network
    let fee_estimate =
        provider.estimate_eip1559_fees().await.context("Failed to estimate EIP-1559 fees")?;

    let current_max_priority_fee = U256::from(fee_estimate.max_priority_fee_per_gas);
    let current_max_fee = U256::from(fee_estimate.max_fee_per_gas);

    // Apply buffer multiplier to current estimates for reliability during network
    // volatility This helps ensure transactions are included even if gas prices
    // spike slightly
    let buffer_multiplier_u256 = U256::from(buffer_multiplier);
    let base_multiplier = U256::from(100u64);
    let adjusted_max_priority_fee =
        (current_max_priority_fee * buffer_multiplier_u256) / base_multiplier;
    let adjusted_max_fee = (current_max_fee * buffer_multiplier_u256) / base_multiplier;

    info!(
        current_max_priority_fee_per_gas = ?current_max_priority_fee,
        current_max_fee_per_gas = ?current_max_fee,
        adjusted_max_priority_fee_per_gas = ?adjusted_max_priority_fee,
        adjusted_max_fee_per_gas = ?adjusted_max_fee,
        provided_max_priority_fee_per_gas = ?provided_max_priority_fee_per_gas,
        provided_max_fee_per_gas = ?provided_max_fee_per_gas,
        buffer_multiplier = buffer_multiplier,
        "Fetched and adjusted current gas price estimates"
    );

    // Dynamically adjust fees: use the maximum of provided values or adjusted
    // current estimates This ensures we use current network conditions while
    // respecting explicit overrides
    let max_priority_fee_per_gas = match provided_max_priority_fee_per_gas {
        Some(provided) => {
            // Use the higher of provided or adjusted current estimate
            let final_fee = if provided > adjusted_max_priority_fee {
                provided
            } else {
                adjusted_max_priority_fee
            };
            info!(
                final_max_priority_fee_per_gas = ?final_fee,
                "Using higher of provided ({:?}) or adjusted current ({:?}) priority fee",
                provided, adjusted_max_priority_fee
            );
            Some(final_fee)
        }
        None => {
            info!(
                max_priority_fee_per_gas = ?adjusted_max_priority_fee,
                "Using dynamically adjusted current priority fee estimate"
            );
            Some(adjusted_max_priority_fee)
        }
    };

    let max_fee_per_gas = match provided_max_fee_per_gas {
        Some(provided) => {
            // Use the higher of provided or adjusted current estimate
            let final_fee = if provided > adjusted_max_fee { provided } else { adjusted_max_fee };
            info!(
                final_max_fee_per_gas = ?final_fee,
                "Using higher of provided ({:?}) or adjusted current ({:?}) max fee",
                provided, adjusted_max_fee
            );
            Some(final_fee)
        }
        None => {
            info!(
                max_fee_per_gas = ?adjusted_max_fee,
                "Using dynamically adjusted current max fee estimate"
            );
            Some(adjusted_max_fee)
        }
    };

    Ok(AdjustedGasPrices { max_priority_fee_per_gas, max_fee_per_gas })
}