2022-12-18 11:45:47 +00:00
|
|
|
pub mod blocknative;
|
2022-04-25 15:50:55 +00:00
|
|
|
pub use blocknative::BlockNative;
|
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
pub mod eth_gas_station;
|
|
|
|
#[allow(deprecated)]
|
2020-08-18 18:47:56 +00:00
|
|
|
pub use eth_gas_station::EthGasStation;
|
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
pub mod etherchain;
|
2020-08-18 18:47:56 +00:00
|
|
|
pub use etherchain::Etherchain;
|
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
pub mod etherscan;
|
2020-08-18 18:47:56 +00:00
|
|
|
pub use etherscan::Etherscan;
|
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
pub mod middleware;
|
2020-09-24 21:33:09 +00:00
|
|
|
pub use middleware::{GasOracleMiddleware, MiddlewareError};
|
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
pub mod median;
|
2022-05-06 15:16:43 +00:00
|
|
|
pub use median::Median;
|
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
pub mod cache;
|
2022-05-06 15:16:43 +00:00
|
|
|
pub use cache::Cache;
|
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
pub mod polygon;
|
2022-05-06 15:16:43 +00:00
|
|
|
pub use polygon::Polygon;
|
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
pub mod gas_now;
|
2022-08-20 23:04:08 +00:00
|
|
|
pub use gas_now::GasNow;
|
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
pub mod provider_oracle;
|
2022-08-20 23:04:08 +00:00
|
|
|
pub use provider_oracle::ProviderOracle;
|
|
|
|
|
2020-08-18 18:47:56 +00:00
|
|
|
use async_trait::async_trait;
|
2022-08-20 23:04:08 +00:00
|
|
|
use auto_impl::auto_impl;
|
2022-12-18 11:45:47 +00:00
|
|
|
use ethers_core::types::U256;
|
2020-08-18 18:47:56 +00:00
|
|
|
use reqwest::Error as ReqwestError;
|
2022-12-18 11:45:47 +00:00
|
|
|
use std::{error::Error, fmt::Debug};
|
2020-08-18 18:47:56 +00:00
|
|
|
use thiserror::Error;
|
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
pub(crate) const GWEI_TO_WEI: u64 = 1_000_000_000;
|
2022-12-30 10:46:52 +00:00
|
|
|
pub(crate) const GWEI_TO_WEI_U256: U256 = U256([GWEI_TO_WEI, 0, 0, 0]);
|
2022-12-18 11:45:47 +00:00
|
|
|
|
|
|
|
pub type Result<T, E = GasOracleError> = std::result::Result<T, E>;
|
2020-08-18 18:47:56 +00:00
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
/// Generic [`GasOracle`] gas price categories.
|
|
|
|
#[derive(Clone, Copy, Default, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
2020-08-18 18:47:56 +00:00
|
|
|
pub enum GasCategory {
|
|
|
|
SafeLow,
|
2022-12-18 11:45:47 +00:00
|
|
|
#[default]
|
2020-08-18 18:47:56 +00:00
|
|
|
Standard,
|
|
|
|
Fast,
|
|
|
|
Fastest,
|
|
|
|
}
|
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
/// Error thrown by a [`GasOracle`].
|
|
|
|
#[derive(Debug, Error)]
|
2020-08-18 18:47:56 +00:00
|
|
|
pub enum GasOracleError {
|
|
|
|
/// An internal error in the HTTP request made from the underlying
|
|
|
|
/// gas oracle
|
|
|
|
#[error(transparent)]
|
|
|
|
HttpClientError(#[from] ReqwestError),
|
|
|
|
|
2022-04-25 15:50:55 +00:00
|
|
|
/// An error decoding JSON response from gas oracle
|
|
|
|
#[error(transparent)]
|
|
|
|
SerdeJsonError(#[from] serde_json::Error),
|
|
|
|
|
|
|
|
/// An error with oracle response type
|
|
|
|
#[error("invalid oracle response")]
|
|
|
|
InvalidResponse,
|
|
|
|
|
2021-11-27 07:54:20 +00:00
|
|
|
/// An internal error in the Etherscan client request made from the underlying
|
|
|
|
/// gas oracle
|
|
|
|
#[error(transparent)]
|
|
|
|
EtherscanError(#[from] ethers_etherscan::errors::EtherscanError),
|
|
|
|
|
2020-08-18 18:47:56 +00:00
|
|
|
/// An internal error thrown when the required gas category is not
|
|
|
|
/// supported by the gas oracle API
|
|
|
|
#[error("gas category not supported")]
|
|
|
|
GasCategoryNotSupported,
|
2021-08-19 14:01:40 +00:00
|
|
|
|
|
|
|
#[error("EIP-1559 gas estimation not supported")]
|
|
|
|
Eip1559EstimationNotSupported,
|
2022-05-06 15:16:43 +00:00
|
|
|
|
|
|
|
#[error("None of the oracles returned a value")]
|
|
|
|
NoValues,
|
|
|
|
|
|
|
|
#[error("Chain is not supported by the oracle")]
|
|
|
|
UnsupportedChain,
|
2022-08-20 23:04:08 +00:00
|
|
|
|
|
|
|
/// Error thrown when the provider failed.
|
2022-12-18 11:45:47 +00:00
|
|
|
#[error("Provider error: {0}")]
|
2022-08-20 23:04:08 +00:00
|
|
|
ProviderError(#[from] Box<dyn Error + Send + Sync>),
|
2020-08-18 18:47:56 +00:00
|
|
|
}
|
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
/// An Ethereum gas price oracle.
|
2020-08-18 18:47:56 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```no_run
|
2022-12-18 11:45:47 +00:00
|
|
|
/// use ethers_core::types::U256;
|
|
|
|
/// use ethers_middleware::gas_oracle::{GasCategory, GasNow, GasOracle};
|
2020-08-18 18:47:56 +00:00
|
|
|
///
|
|
|
|
/// # async fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
2022-12-18 11:45:47 +00:00
|
|
|
/// let oracle = GasNow::default().category(GasCategory::SafeLow);
|
|
|
|
/// let gas_price = oracle.fetch().await?;
|
|
|
|
/// assert!(gas_price > U256::zero());
|
2020-08-18 18:47:56 +00:00
|
|
|
/// # Ok(())
|
|
|
|
/// # }
|
|
|
|
/// ```
|
2021-08-23 09:56:44 +00:00
|
|
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
|
|
|
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
2022-08-20 23:04:08 +00:00
|
|
|
#[auto_impl(&, Box, Arc)]
|
2022-12-18 11:45:47 +00:00
|
|
|
pub trait GasOracle: Send + Sync + Debug {
|
|
|
|
/// Makes an asynchronous HTTP query to the underlying [`GasOracle`] to fetch the current gas
|
|
|
|
/// price estimate.
|
2020-08-18 18:47:56 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2022-12-18 11:45:47 +00:00
|
|
|
/// ```no_run
|
|
|
|
/// use ethers_core::types::U256;
|
|
|
|
/// use ethers_middleware::gas_oracle::{GasCategory, GasNow, GasOracle};
|
|
|
|
///
|
|
|
|
/// # async fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
|
/// let oracle = GasNow::default().category(GasCategory::SafeLow);
|
|
|
|
/// let gas_price = oracle.fetch().await?;
|
|
|
|
/// assert!(gas_price > U256::zero());
|
|
|
|
/// # Ok(())
|
|
|
|
/// # }
|
2020-08-18 18:47:56 +00:00
|
|
|
/// ```
|
2022-12-18 11:45:47 +00:00
|
|
|
async fn fetch(&self) -> Result<U256>;
|
|
|
|
|
|
|
|
/// Makes an asynchronous HTTP query to the underlying [`GasOracle`] to fetch the current max
|
|
|
|
/// gas fee and priority gas fee estimates.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```no_run
|
|
|
|
/// use ethers_core::types::U256;
|
|
|
|
/// use ethers_middleware::gas_oracle::{GasCategory, GasNow, GasOracle};
|
2020-08-18 18:47:56 +00:00
|
|
|
///
|
|
|
|
/// # async fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
2022-12-18 11:45:47 +00:00
|
|
|
/// let oracle = GasNow::default().category(GasCategory::SafeLow);
|
|
|
|
/// let (max_fee, priority_fee) = oracle.estimate_eip1559_fees().await?;
|
|
|
|
/// assert!(max_fee > U256::zero());
|
|
|
|
/// assert!(priority_fee > U256::zero());
|
2020-08-18 18:47:56 +00:00
|
|
|
/// # Ok(())
|
|
|
|
/// # }
|
|
|
|
/// ```
|
2022-12-18 11:45:47 +00:00
|
|
|
async fn estimate_eip1559_fees(&self) -> Result<(U256, U256)>;
|
|
|
|
}
|
2021-08-19 14:01:40 +00:00
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
#[inline]
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub(crate) fn from_gwei_f64(gwei: f64) -> U256 {
|
|
|
|
ethers_core::types::u256_from_f64_saturating(gwei) * GWEI_TO_WEI_U256
|
2020-08-18 18:47:56 +00:00
|
|
|
}
|
2022-12-30 10:46:52 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_gwei_wei_constants() {
|
|
|
|
let as_u256: U256 = GWEI_TO_WEI.into();
|
|
|
|
assert_eq!(as_u256, GWEI_TO_WEI_U256);
|
|
|
|
assert_eq!(GWEI_TO_WEI_U256.as_u64(), GWEI_TO_WEI);
|
|
|
|
}
|
|
|
|
}
|