forge_script/
providers.rs
1use alloy_primitives::map::{hash_map::Entry, HashMap};
2use alloy_provider::{utils::Eip1559Estimation, Provider};
3use eyre::{Result, WrapErr};
4use foundry_common::provider::{get_http_provider, RetryProvider};
5use foundry_config::Chain;
6use std::{ops::Deref, sync::Arc};
7
8#[derive(Default)]
10pub struct ProvidersManager {
11 pub inner: HashMap<String, ProviderInfo>,
12}
13
14impl ProvidersManager {
15 pub async fn get_or_init_provider(
17 &mut self,
18 rpc: &str,
19 is_legacy: bool,
20 ) -> Result<&ProviderInfo> {
21 Ok(match self.inner.entry(rpc.to_string()) {
22 Entry::Occupied(entry) => entry.into_mut(),
23 Entry::Vacant(entry) => {
24 let info = ProviderInfo::new(rpc, is_legacy).await?;
25 entry.insert(info)
26 }
27 })
28 }
29}
30
31impl Deref for ProvidersManager {
32 type Target = HashMap<String, ProviderInfo>;
33
34 fn deref(&self) -> &Self::Target {
35 &self.inner
36 }
37}
38
39#[derive(Debug)]
41pub struct ProviderInfo {
42 pub provider: Arc<RetryProvider>,
43 pub chain: u64,
44 pub gas_price: GasPrice,
45}
46
47#[derive(Debug)]
49pub enum GasPrice {
50 Legacy(Result<u128>),
51 EIP1559(Result<Eip1559Estimation>),
52}
53
54impl ProviderInfo {
55 pub async fn new(rpc: &str, mut is_legacy: bool) -> Result<Self> {
56 let provider = Arc::new(get_http_provider(rpc));
57 let chain = provider.get_chain_id().await?;
58
59 if let Some(chain) = Chain::from(chain).named() {
60 is_legacy |= chain.is_legacy();
61 };
62
63 let gas_price = if is_legacy {
64 GasPrice::Legacy(
65 provider.get_gas_price().await.wrap_err("Failed to get legacy gas price"),
66 )
67 } else {
68 GasPrice::EIP1559(
69 provider.estimate_eip1559_fees().await.wrap_err("Failed to get EIP-1559 fees"),
70 )
71 };
72
73 Ok(Self { provider, chain, gas_price })
74 }
75
76 pub fn gas_price(&self) -> Result<u128> {
78 let res = match &self.gas_price {
79 GasPrice::Legacy(res) => res.as_ref(),
80 GasPrice::EIP1559(res) => res.as_ref().map(|res| &res.max_fee_per_gas),
81 };
82 match res {
83 Ok(val) => Ok(*val),
84 Err(err) => Err(eyre::eyre!("{}", err)),
85 }
86 }
87}