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!["https://mainnet.infura.io".to_string()],
47 explorer_urls: None,
48 average_blocktime_ms: 12000,
49 is_testnet: false,
50 tags: vec![],
51 chain_id: 1,
52 required_confirmations: 12,
53 features: vec!["eip1559".to_string()],
54 symbol: "ETH".to_string(),
55 gas_price_cache: None,
56 };
57
58 let result = fetcher.fetch_gas_price(&mock_provider, &network).await;
59 assert!(result.is_ok());
60 assert_eq!(result.unwrap(), Some(20_000_000_000u128));
61 }
62
63 #[tokio::test]
64 async fn test_default_estimator_failure() {
65 let mut mock_provider = MockEvmProviderTrait::new();
66 mock_provider
67 .expect_get_gas_price()
68 .times(1)
69 .returning(|| async { Err(ProviderError::Timeout) }.boxed());
70
71 let fetcher = DefaultGasPriceFetcher;
72 let network = EvmNetwork {
73 network: "ethereum".to_string(),
74 rpc_urls: vec!["https://mainnet.infura.io".to_string()],
75 explorer_urls: None,
76 average_blocktime_ms: 12000,
77 is_testnet: false,
78 tags: vec![],
79 chain_id: 1,
80 required_confirmations: 12,
81 features: vec!["eip1559".to_string()],
82 symbol: "ETH".to_string(),
83 gas_price_cache: None,
84 };
85
86 let result = fetcher.fetch_gas_price(&mock_provider, &network).await;
87 assert!(result.is_err());
88 assert!(matches!(result.unwrap_err(), ProviderError::Timeout));
89 }
90
91 #[tokio::test]
92 async fn test_default_estimator_network_error() {
93 let mut mock_provider = MockEvmProviderTrait::new();
94 mock_provider.expect_get_gas_price().times(1).returning(|| {
95 async { Err(ProviderError::Other("Connection refused".to_string())) }.boxed()
96 });
97
98 let fetcher = DefaultGasPriceFetcher;
99 let network = EvmNetwork {
100 network: "polygon".to_string(),
101 rpc_urls: vec!["https://polygon-rpc.com".to_string()],
102 explorer_urls: None,
103 average_blocktime_ms: 2000,
104 is_testnet: false,
105 tags: vec![],
106 chain_id: 137,
107 required_confirmations: 10,
108 features: vec!["eip1559".to_string()],
109 symbol: "MATIC".to_string(),
110 gas_price_cache: None,
111 };
112
113 let result = fetcher.fetch_gas_price(&mock_provider, &network).await;
114 assert!(result.is_err());
115 assert!(matches!(result.unwrap_err(), ProviderError::Other(_)));
116 }
117
118 #[tokio::test]
119 async fn test_default_estimator_ethereum() {
120 let mut mock_provider = MockEvmProviderTrait::new();
121 mock_provider
122 .expect_get_gas_price()
123 .times(1)
124 .returning(|| async { Ok(1_000_000_000u128) }.boxed());
125
126 let fetcher = DefaultGasPriceFetcher;
127 let network = EvmNetwork {
128 network: "ethereum".to_string(),
129 rpc_urls: vec!["https://mainnet.infura.io".to_string()],
130 explorer_urls: None,
131 average_blocktime_ms: 12000,
132 is_testnet: false,
133 tags: vec![],
134 chain_id: 1,
135 required_confirmations: 12,
136 features: vec!["eip1559".to_string()],
137 symbol: "ETH".to_string(),
138 gas_price_cache: None,
139 };
140
141 let result = fetcher.fetch_gas_price(&mock_provider, &network).await;
142 assert!(result.is_ok());
143 assert_eq!(result.unwrap(), Some(1_000_000_000u128));
144 }
145
146 #[tokio::test]
147 async fn test_default_estimator_polygon() {
148 let mut mock_provider = MockEvmProviderTrait::new();
149 mock_provider
150 .expect_get_gas_price()
151 .times(1)
152 .returning(|| async { Ok(137_000_000_000u128) }.boxed());
153
154 let fetcher = DefaultGasPriceFetcher;
155 let network = EvmNetwork {
156 network: "polygon".to_string(),
157 rpc_urls: vec!["https://polygon-rpc.com".to_string()],
158 explorer_urls: None,
159 average_blocktime_ms: 2000,
160 is_testnet: false,
161 tags: vec![],
162 chain_id: 137,
163 required_confirmations: 10,
164 features: vec!["eip1559".to_string()],
165 symbol: "MATIC".to_string(),
166 gas_price_cache: None,
167 };
168
169 let result = fetcher.fetch_gas_price(&mock_provider, &network).await;
170 assert!(result.is_ok());
171 assert_eq!(result.unwrap(), Some(137_000_000_000u128));
172 }
173}