openzeppelin_relayer/services/gas/fetchers/
default.rs1use crate::{
7 models::EvmNetwork,
8 services::provider::{evm::EvmProviderTrait, ProviderError},
9};
10
11#[derive(Debug, Clone)]
13pub struct DefaultGasPriceFetcher;
14
15impl DefaultGasPriceFetcher {
16 pub async fn fetch_gas_price<P: EvmProviderTrait>(
18 &self,
19 provider: &P,
20 _network: &EvmNetwork,
21 ) -> Result<Option<u128>, ProviderError> {
22 match provider.get_gas_price().await {
23 Ok(gas_price) => Ok(Some(gas_price)),
24 Err(e) => Err(e),
25 }
26 }
27}
28
29#[cfg(test)]
30mod tests {
31 use super::*;
32 use crate::services::provider::evm::MockEvmProviderTrait;
33 use futures::FutureExt;
34
35 #[tokio::test]
36 async fn test_default_fetcher_success() {
37 let mut mock_provider = MockEvmProviderTrait::new();
38 mock_provider
39 .expect_get_gas_price()
40 .times(1)
41 .returning(|| async { Ok(20_000_000_000u128) }.boxed());
42
43 let fetcher = DefaultGasPriceFetcher;
44 let network = EvmNetwork {
45 network: "ethereum".to_string(),
46 rpc_urls: vec![crate::models::RpcConfig::new(
47 "https://mainnet.infura.io".to_string(),
48 )],
49 explorer_urls: None,
50 average_blocktime_ms: 12000,
51 is_testnet: false,
52 tags: vec![],
53 chain_id: 1,
54 required_confirmations: 12,
55 features: vec!["eip1559".to_string()],
56 symbol: "ETH".to_string(),
57 gas_price_cache: None,
58 };
59
60 let result = fetcher.fetch_gas_price(&mock_provider, &network).await;
61 assert!(result.is_ok());
62 assert_eq!(result.unwrap(), Some(20_000_000_000u128));
63 }
64
65 #[tokio::test]
66 async fn test_default_estimator_failure() {
67 let mut mock_provider = MockEvmProviderTrait::new();
68 mock_provider
69 .expect_get_gas_price()
70 .times(1)
71 .returning(|| async { Err(ProviderError::Timeout) }.boxed());
72
73 let fetcher = DefaultGasPriceFetcher;
74 let network = EvmNetwork {
75 network: "ethereum".to_string(),
76 rpc_urls: vec![crate::models::RpcConfig::new(
77 "https://mainnet.infura.io".to_string(),
78 )],
79 explorer_urls: None,
80 average_blocktime_ms: 12000,
81 is_testnet: false,
82 tags: vec![],
83 chain_id: 1,
84 required_confirmations: 12,
85 features: vec!["eip1559".to_string()],
86 symbol: "ETH".to_string(),
87 gas_price_cache: None,
88 };
89
90 let result = fetcher.fetch_gas_price(&mock_provider, &network).await;
91 assert!(result.is_err());
92 assert!(matches!(result.unwrap_err(), ProviderError::Timeout));
93 }
94
95 #[tokio::test]
96 async fn test_default_estimator_network_error() {
97 let mut mock_provider = MockEvmProviderTrait::new();
98 mock_provider.expect_get_gas_price().times(1).returning(|| {
99 async { Err(ProviderError::Other("Connection refused".to_string())) }.boxed()
100 });
101
102 let fetcher = DefaultGasPriceFetcher;
103 let network = EvmNetwork {
104 network: "polygon".to_string(),
105 rpc_urls: vec![crate::models::RpcConfig::new(
106 "https://polygon-rpc.com".to_string(),
107 )],
108 explorer_urls: None,
109 average_blocktime_ms: 2000,
110 is_testnet: false,
111 tags: vec![],
112 chain_id: 137,
113 required_confirmations: 10,
114 features: vec!["eip1559".to_string()],
115 symbol: "MATIC".to_string(),
116 gas_price_cache: None,
117 };
118
119 let result = fetcher.fetch_gas_price(&mock_provider, &network).await;
120 assert!(result.is_err());
121 assert!(matches!(result.unwrap_err(), ProviderError::Other(_)));
122 }
123
124 #[tokio::test]
125 async fn test_default_estimator_ethereum() {
126 let mut mock_provider = MockEvmProviderTrait::new();
127 mock_provider
128 .expect_get_gas_price()
129 .times(1)
130 .returning(|| async { Ok(1_000_000_000u128) }.boxed());
131
132 let fetcher = DefaultGasPriceFetcher;
133 let network = EvmNetwork {
134 network: "ethereum".to_string(),
135 rpc_urls: vec![crate::models::RpcConfig::new(
136 "https://mainnet.infura.io".to_string(),
137 )],
138 explorer_urls: None,
139 average_blocktime_ms: 12000,
140 is_testnet: false,
141 tags: vec![],
142 chain_id: 1,
143 required_confirmations: 12,
144 features: vec!["eip1559".to_string()],
145 symbol: "ETH".to_string(),
146 gas_price_cache: None,
147 };
148
149 let result = fetcher.fetch_gas_price(&mock_provider, &network).await;
150 assert!(result.is_ok());
151 assert_eq!(result.unwrap(), Some(1_000_000_000u128));
152 }
153
154 #[tokio::test]
155 async fn test_default_estimator_polygon() {
156 let mut mock_provider = MockEvmProviderTrait::new();
157 mock_provider
158 .expect_get_gas_price()
159 .times(1)
160 .returning(|| async { Ok(137_000_000_000u128) }.boxed());
161
162 let fetcher = DefaultGasPriceFetcher;
163 let network = EvmNetwork {
164 network: "polygon".to_string(),
165 rpc_urls: vec![crate::models::RpcConfig::new(
166 "https://polygon-rpc.com".to_string(),
167 )],
168 explorer_urls: None,
169 average_blocktime_ms: 2000,
170 is_testnet: false,
171 tags: vec![],
172 chain_id: 137,
173 required_confirmations: 10,
174 features: vec!["eip1559".to_string()],
175 symbol: "MATIC".to_string(),
176 gas_price_cache: None,
177 };
178
179 let result = fetcher.fetch_gas_price(&mock_provider, &network).await;
180 assert!(result.is_ok());
181 assert_eq!(result.unwrap(), Some(137_000_000_000u128));
182 }
183}