Skip to main content

ethers_abirpc/
chain.rs

1use {
2    crate::{error::Error, named::NamedChain},
3    std::{clone::Clone, cmp},
4    strum_macros::Display,
5};
6
7#[derive(Debug, PartialEq, Copy, Clone)]
8pub struct RetryClientConfig {
9    pub rate_limit_retries: u32,
10    pub timeout_retries: u32,
11    pub initial_backoff_ms: u64,
12}
13
14impl Default for RetryClientConfig {
15    fn default() -> Self {
16        Self {
17            rate_limit_retries: 10,
18            timeout_retries: 3,
19            initial_backoff_ms: 500,
20        }
21    }
22}
23
24#[derive(Debug, PartialEq, Copy, Clone, Default)]
25pub struct ChainConfig {
26    pub chain_id: u64,
27    pub retry_client_config: RetryClientConfig,
28    pub assert_chain_id: bool,
29}
30
31#[derive(Debug, PartialEq, Copy, Clone, Display)]
32pub enum Chain {
33    Id(u64),
34    ChainConfig(ChainConfig),
35}
36
37impl From<u64> for Chain {
38    fn from(id: u64) -> Self {
39        Self::Id(id)
40    }
41}
42
43impl From<NamedChain> for Chain {
44    fn from(named: NamedChain) -> Self {
45        Self::Id(named as u64)
46    }
47}
48
49impl Chain {
50    pub fn id(&self) -> u64 {
51        match self {
52            Chain::Id(chain_id) => *chain_id,
53            Chain::ChainConfig(config) => config.chain_id,
54        }
55    }
56
57    pub fn from_id(id: u64) -> Self {
58        Chain::from(id)
59    }
60
61    pub fn named(&self) -> Option<NamedChain> {
62        match self {
63            Chain::Id(chain_id) => NamedChain::try_from(*chain_id)
64                .map_err(Error::NamedChainError)
65                .ok(),
66            Chain::ChainConfig(config) => NamedChain::try_from(config.chain_id)
67                .map_err(Error::NamedChainError)
68                .ok(),
69        }
70    }
71
72    pub fn from_named(named: NamedChain) -> Self {
73        Chain::from(named)
74    }
75
76    pub fn retry_client_config(&self) -> RetryClientConfig {
77        match self {
78            Chain::Id(chain_id) => match NamedChain::try_from(*chain_id) {
79                Ok(named) => {
80                    let default = RetryClientConfig::default().initial_backoff_ms;
81
82                    let initial_backoff_ms = match named.average_blocktime_hint() {
83                        Some(duration) => {
84                            let interval = (duration.as_millis() as u64) / 10;
85                            cmp::max(100, cmp::min(default, interval))
86                        }
87                        None => default,
88                    };
89                    RetryClientConfig {
90                        initial_backoff_ms,
91                        ..RetryClientConfig::default()
92                    }
93                }
94                Err(_) => RetryClientConfig::default(),
95            },
96            Chain::ChainConfig(config) => config.retry_client_config,
97        }
98    }
99
100    pub fn assert_chain_id(&self) -> bool {
101        match self {
102            Chain::Id(_) => true,
103            Chain::ChainConfig(config) => config.assert_chain_id,
104        }
105    }
106}