ethers_middleware/gas_oracle/
eth_gas_station.rs1#![allow(deprecated)]
2
3use super::{GasCategory, GasOracle, GasOracleError, Result, GWEI_TO_WEI_U256};
4use async_trait::async_trait;
5use ethers_core::types::U256;
6use reqwest::Client;
7use serde::Deserialize;
8use std::collections::HashMap;
9use url::Url;
10
11const URL: &str = "https://ethgasstation.info/api/ethgasAPI.json";
12
13#[derive(Clone, Debug)]
16#[deprecated = "ETHGasStation is shutting down: https://twitter.com/ETHGasStation/status/1597341610777317376"]
17#[must_use]
18pub struct EthGasStation {
19 client: Client,
20 url: Url,
21 gas_category: GasCategory,
22}
23
24#[derive(Clone, Debug, Deserialize, PartialEq)]
28#[serde(rename_all = "camelCase")]
29pub struct Response {
30 pub safe_low: u64,
34 pub average: u64,
38 pub fast: u64,
42 pub fastest: u64,
46
47 #[serde(rename = "block_time")] pub block_time: f64,
51 pub block_num: u64,
53 pub speed: f64,
55 pub safe_low_wait: f64,
57 pub avg_wait: f64,
59 pub fast_wait: f64,
61 pub fastest_wait: f64,
63 pub gas_price_range: HashMap<u64, f64>,
65}
66
67impl Response {
68 #[inline]
69 pub fn gas_from_category(&self, gas_category: GasCategory) -> u64 {
70 match gas_category {
71 GasCategory::SafeLow => self.safe_low,
72 GasCategory::Standard => self.average,
73 GasCategory::Fast => self.fast,
74 GasCategory::Fastest => self.fastest,
75 }
76 }
77}
78
79impl Default for EthGasStation {
80 fn default() -> Self {
81 Self::new(None)
82 }
83}
84
85#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
86#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
87impl GasOracle for EthGasStation {
88 async fn fetch(&self) -> Result<U256> {
89 let res = self.query().await?;
90 let gas_price = res.gas_from_category(self.gas_category);
91 Ok(U256::from(gas_price) * GWEI_TO_WEI_U256 / U256::from(10_u64))
93 }
94
95 async fn estimate_eip1559_fees(&self) -> Result<(U256, U256)> {
96 Err(GasOracleError::Eip1559EstimationNotSupported)
97 }
98}
99
100impl EthGasStation {
101 pub fn new(api_key: Option<&str>) -> Self {
103 Self::with_client(Client::new(), api_key)
104 }
105
106 pub fn with_client(client: Client, api_key: Option<&str>) -> Self {
108 let mut url = Url::parse(URL).unwrap();
109 if let Some(key) = api_key {
110 url.query_pairs_mut().append_pair("api-key", key);
111 }
112 EthGasStation { client, url, gas_category: GasCategory::Standard }
113 }
114
115 pub fn category(mut self, gas_category: GasCategory) -> Self {
117 self.gas_category = gas_category;
118 self
119 }
120
121 pub async fn query(&self) -> Result<Response> {
123 let response =
124 self.client.get(self.url.clone()).send().await?.error_for_status()?.json().await?;
125 Ok(response)
126 }
127}