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}