ethers-abirpc 0.3.0

ethers-rs provider encapsulation for ethereum smart contrcats
Documentation
use {
    crate::{error::Error, named::NamedChain},
    std::{clone::Clone, cmp},
    strum_macros::Display,
};

#[derive(Debug, PartialEq, Copy, Clone)]
pub struct RetryClientConfig {
    pub rate_limit_retries: u32,
    pub timeout_retries: u32,
    pub initial_backoff_ms: u64,
}

impl Default for RetryClientConfig {
    fn default() -> Self {
        Self {
            rate_limit_retries: 10,
            timeout_retries: 3,
            initial_backoff_ms: 500,
        }
    }
}

#[derive(Debug, PartialEq, Copy, Clone, Default)]
pub struct ChainConfig {
    pub chain_id: u64,
    pub retry_client_config: RetryClientConfig,
    pub assert_chain_id: bool,
}

#[derive(Debug, PartialEq, Copy, Clone, Display)]
pub enum Chain {
    Id(u64),
    ChainConfig(ChainConfig),
}

impl From<u64> for Chain {
    fn from(id: u64) -> Self {
        Self::Id(id)
    }
}

impl From<NamedChain> for Chain {
    fn from(named: NamedChain) -> Self {
        Self::Id(named as u64)
    }
}

impl Chain {
    pub fn id(&self) -> u64 {
        match self {
            Chain::Id(chain_id) => *chain_id,
            Chain::ChainConfig(config) => config.chain_id,
        }
    }

    pub fn from_id(id: u64) -> Self {
        Chain::from(id)
    }

    pub fn named(&self) -> Option<NamedChain> {
        match self {
            Chain::Id(chain_id) => NamedChain::try_from(*chain_id)
                .map_err(Error::NamedChainError)
                .ok(),
            Chain::ChainConfig(config) => NamedChain::try_from(config.chain_id)
                .map_err(Error::NamedChainError)
                .ok(),
        }
    }

    pub fn from_named(named: NamedChain) -> Self {
        Chain::from(named)
    }

    pub fn retry_client_config(&self) -> RetryClientConfig {
        match self {
            Chain::Id(chain_id) => match NamedChain::try_from(*chain_id) {
                Ok(named) => {
                    let default = RetryClientConfig::default().initial_backoff_ms;

                    let initial_backoff_ms = match named.average_blocktime_hint() {
                        Some(duration) => {
                            let interval = (duration.as_millis() as u64) / 10;
                            cmp::max(100, cmp::min(default, interval))
                        }
                        None => default,
                    };
                    RetryClientConfig {
                        initial_backoff_ms,
                        ..RetryClientConfig::default()
                    }
                }
                Err(_) => RetryClientConfig::default(),
            },
            Chain::ChainConfig(config) => config.retry_client_config,
        }
    }

    pub fn assert_chain_id(&self) -> bool {
        match self {
            Chain::Id(_) => true,
            Chain::ChainConfig(config) => config.assert_chain_id,
        }
    }
}