ethers_middleware/gas_oracle/
etherchain.rs1use super::{from_gwei_f64, GasCategory, GasOracle, GasOracleError, Result};
2use async_trait::async_trait;
3use ethers_core::types::U256;
4use reqwest::Client;
5use serde::Deserialize;
6use url::Url;
7
8const URL: &str = "https://www.etherchain.org/api/gasPriceOracle";
9
10#[derive(Clone, Debug)]
13#[must_use]
14pub struct Etherchain {
15 client: Client,
16 url: Url,
17 gas_category: GasCategory,
18}
19
20#[derive(Clone, Copy, Debug, Deserialize, PartialEq)]
21#[serde(rename_all = "camelCase")]
22pub struct Response {
23 pub safe_low: f64,
24 pub standard: f64,
25 pub fast: f64,
26 pub fastest: f64,
27 pub current_base_fee: f64,
28 pub recommended_base_fee: f64,
29}
30
31impl Response {
32 #[inline]
33 pub fn gas_from_category(&self, gas_category: GasCategory) -> f64 {
34 match gas_category {
35 GasCategory::SafeLow => self.safe_low,
36 GasCategory::Standard => self.standard,
37 GasCategory::Fast => self.fast,
38 GasCategory::Fastest => self.fastest,
39 }
40 }
41}
42
43impl Default for Etherchain {
44 fn default() -> Self {
45 Self::new()
46 }
47}
48
49#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
50#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
51impl GasOracle for Etherchain {
52 async fn fetch(&self) -> Result<U256> {
53 let res = self.query().await?;
54 let gas_price = res.gas_from_category(self.gas_category);
55 Ok(from_gwei_f64(gas_price))
56 }
57
58 async fn estimate_eip1559_fees(&self) -> Result<(U256, U256)> {
59 Err(GasOracleError::Eip1559EstimationNotSupported)
60 }
61}
62
63impl Etherchain {
64 pub fn new() -> Self {
66 Self::with_client(Client::new())
67 }
68
69 pub fn with_client(client: Client) -> Self {
71 let url = Url::parse(URL).unwrap();
72 Etherchain { client, url, gas_category: GasCategory::Standard }
73 }
74
75 pub fn category(mut self, gas_category: GasCategory) -> Self {
77 self.gas_category = gas_category;
78 self
79 }
80
81 pub async fn query(&self) -> Result<Response> {
83 let response =
84 self.client.get(self.url.clone()).send().await?.error_for_status()?.json().await?;
85 Ok(response)
86 }
87}