Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

fix: backwards compatibility for eth_feeHistory #395

Merged
merged 2 commits into from
Aug 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions ethers-providers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ pub use pubsub::{PubsubClient, SubscriptionStream};
use async_trait::async_trait;
use auto_impl::auto_impl;
use ethers_core::types::transaction::{eip2718::TypedTransaction, eip2930::AccessListWithGasUsed};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::{error::Error, fmt::Debug, future::Future, pin::Pin};
use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize};
use std::{error::Error, fmt::Debug, future::Future, pin::Pin, str::FromStr};

pub use provider::{FilterKind, Provider, ProviderError};

Expand Down Expand Up @@ -704,9 +704,9 @@ pub trait Middleware: Sync + Send + Debug {
.map_err(FromErr::from)
}

async fn fee_history(
async fn fee_history<T: Into<U256> + serde::Serialize + Send + Sync>(
&self,
block_count: u64,
block_count: T,
last_block: BlockNumber,
reward_percentiles: &[f64],
) -> Result<FeeHistory, Self::Error> {
Expand All @@ -733,10 +733,31 @@ pub trait Middleware: Sync + Send + Debug {
pub struct FeeHistory {
pub base_fee_per_gas: Vec<U256>,
pub gas_used_ratio: Vec<f64>,
pub oldest_block: u64,
#[serde(deserialize_with = "from_int_or_hex")]
/// oldestBlock is returned as an unsigned integer up to geth v1.10.6. From
/// geth v1.10.7, this has been updated to return in the hex encoded form.
/// The custom deserializer allows backward compatibility for those clients
/// not running v1.10.7 yet.
pub oldest_block: U256,
pub reward: Vec<Vec<U256>>,
}

fn from_int_or_hex<'de, D>(deserializer: D) -> Result<U256, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(untagged)]
enum IntOrHex {
Int(u64),
Hex(String),
}
match IntOrHex::deserialize(deserializer)? {
IntOrHex::Int(n) => Ok(U256::from(n)),
IntOrHex::Hex(s) => U256::from_str(s.as_str()).map_err(serde::de::Error::custom),
}
}

#[cfg(feature = "celo")]
#[async_trait]
pub trait CeloMiddleware: Middleware {
Expand Down
27 changes: 22 additions & 5 deletions ethers-providers/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -769,20 +769,37 @@ impl<P: JsonRpcClient> Middleware for Provider<P> {
self.subscribe([logs, filter]).await
}

async fn fee_history(
async fn fee_history<T: Into<U256> + serde::Serialize + Send + Sync>(
&self,
block_count: u64,
block_count: T,
last_block: BlockNumber,
reward_percentiles: &[f64],
) -> Result<FeeHistory, Self::Error> {
let block_count = utils::serialize(&block_count);
let last_block = utils::serialize(&last_block);
let reward_percentiles = utils::serialize(&reward_percentiles);

// The blockCount param is expected to be an unsigned integer up to geth v1.10.6.
// Geth v1.10.7 onwards, this has been updated to a hex encoded form. Failure to
// decode the param from client side would fallback to the old API spec.
self.request(
"eth_feeHistory",
[block_count, last_block, reward_percentiles],
[
utils::serialize(&block_count),
last_block.clone(),
reward_percentiles.clone(),
],
)
.await
.or(self
.request(
"eth_feeHistory",
[
utils::serialize(&block_count.into().as_u64()),
last_block,
reward_percentiles,
],
)
.await)
}
}

Expand Down Expand Up @@ -1123,7 +1140,7 @@ mod tests {
.unwrap();

let history = provider
.fee_history(10, BlockNumber::Latest, &[10.0, 40.0])
.fee_history(10u64, BlockNumber::Latest, &[10.0, 40.0])
.await
.unwrap();
dbg!(&history);
Expand Down