feat: add support for EIP-234 and EIP-1898 (#231)
* Add support for EIP-234 * Add support for EIP-1898 * Remove redundant field names * Remove useless conversion * Change `unwrap_or` to `unwrap_or_else`
This commit is contained in:
parent
57010c1c60
commit
530bfe2b71
|
@ -1,7 +1,7 @@
|
|||
use super::base::{decode_function_data, AbiError};
|
||||
use ethers_core::{
|
||||
abi::{Detokenize, Function, InvalidOutputType},
|
||||
types::{Address, BlockNumber, Bytes, TransactionRequest, U256},
|
||||
types::{Address, BlockId, Bytes, TransactionRequest, U256},
|
||||
};
|
||||
use ethers_providers::{Middleware, PendingTransaction, ProviderError};
|
||||
|
||||
|
@ -52,7 +52,7 @@ pub struct ContractCall<M, D> {
|
|||
/// The ABI of the function being called
|
||||
pub function: Function,
|
||||
/// Optional block number to be used when calculating the transaction's gas and nonce
|
||||
pub block: Option<BlockNumber>,
|
||||
pub block: Option<BlockId>,
|
||||
pub(crate) client: Arc<M>,
|
||||
pub(crate) datatype: PhantomData<D>,
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ impl<M, D: Detokenize> ContractCall<M, D> {
|
|||
}
|
||||
|
||||
/// Sets the `block` field for sending the tx to the chain
|
||||
pub fn block<T: Into<BlockNumber>>(mut self, block: T) -> Self {
|
||||
pub fn block<T: Into<BlockId>>(mut self, block: T) -> Self {
|
||||
self.block = Some(block.into());
|
||||
self
|
||||
}
|
||||
|
|
|
@ -40,14 +40,22 @@ impl<M, D: Detokenize> Event<'_, '_, M, D> {
|
|||
/// Sets the filter's `from` block
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn from_block<T: Into<BlockNumber>>(mut self, block: T) -> Self {
|
||||
self.filter.from_block = Some(block.into());
|
||||
self.filter = self.filter.from_block(block);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the filter's `to` block
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn to_block<T: Into<BlockNumber>>(mut self, block: T) -> Self {
|
||||
self.filter.to_block = Some(block.into());
|
||||
self.filter = self.filter.to_block(block);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the filter's `blockHash`. Setting this will override previously
|
||||
/// set `from_block` and `to_block` fields.
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn at_block_hash<T: Into<H256>>(mut self, hash: T) -> Self {
|
||||
self.filter = self.filter.at_block_hash(hash);
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ impl<M: Middleware> Deployer<M> {
|
|||
pub async fn send(self) -> Result<Contract<M>, ContractError<M>> {
|
||||
let pending_tx = self
|
||||
.client
|
||||
.send_transaction(self.tx, Some(self.block))
|
||||
.send_transaction(self.tx, Some(self.block.into()))
|
||||
.await
|
||||
.map_err(ContractError::MiddlewareError)?;
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use ethers::{contract::ContractFactory, types::H256};
|
||||
use ethers::{
|
||||
contract::ContractFactory,
|
||||
types::{BlockId, H256},
|
||||
};
|
||||
|
||||
mod common;
|
||||
pub use common::*;
|
||||
|
@ -96,7 +99,7 @@ mod eth_tests {
|
|||
let client = connect(&ganache, 0);
|
||||
let contract = deploy(client.clone(), abi, bytecode).await;
|
||||
|
||||
// make a call with `client2`
|
||||
// make a call with `client`
|
||||
let _tx_hash = *contract
|
||||
.method::<_, H256>("setValue", "hi".to_owned())
|
||||
.unwrap()
|
||||
|
@ -116,6 +119,133 @@ mod eth_tests {
|
|||
assert_eq!(logs[0].new_value, "initial value");
|
||||
assert_eq!(logs[1].new_value, "hi");
|
||||
assert_eq!(logs.len(), 2);
|
||||
|
||||
// and we can fetch the events at a block hash
|
||||
let hash = client.get_block(1).await.unwrap().unwrap().hash.unwrap();
|
||||
let logs: Vec<ValueChanged> = contract
|
||||
.event("ValueChanged")
|
||||
.unwrap()
|
||||
.at_block_hash(hash)
|
||||
.topic1(client.address()) // Corresponds to the first indexed parameter
|
||||
.query()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(logs[0].new_value, "initial value");
|
||||
assert_eq!(logs.len(), 1);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn call_past_state() {
|
||||
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
||||
let ganache = Ganache::new().spawn();
|
||||
let client = connect(&ganache, 0);
|
||||
let contract = deploy(client.clone(), abi, bytecode).await;
|
||||
let deployed_block = client.get_block_number().await.unwrap();
|
||||
|
||||
// assert initial state
|
||||
let value = contract
|
||||
.method::<_, String>("getValue", ())
|
||||
.unwrap()
|
||||
.call()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(value, "initial value");
|
||||
|
||||
// make a call with `client`
|
||||
let _tx_hash = *contract
|
||||
.method::<_, H256>("setValue", "hi".to_owned())
|
||||
.unwrap()
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// assert new value
|
||||
let value = contract
|
||||
.method::<_, String>("getValue", ())
|
||||
.unwrap()
|
||||
.call()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(value, "hi");
|
||||
|
||||
// assert previous value
|
||||
let value = contract
|
||||
.method::<_, String>("getValue", ())
|
||||
.unwrap()
|
||||
.block(BlockId::Number(deployed_block.into()))
|
||||
.call()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(value, "initial value");
|
||||
|
||||
// Here would be the place to test EIP-1898, specifying the `BlockId` of `call` as the
|
||||
// first block hash. However, Ganache does not implement this :/
|
||||
|
||||
// let hash = client.get_block(1).await.unwrap().unwrap().hash.unwrap();
|
||||
// let value = contract
|
||||
// .method::<_, String>("getValue", ())
|
||||
// .unwrap()
|
||||
// .block(BlockId::Hash(hash))
|
||||
// .call()
|
||||
// .await
|
||||
// .unwrap();
|
||||
// assert_eq!(value, "initial value");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn call_past_hash_test() {
|
||||
// geth --dev --http --http.api eth,web3
|
||||
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
||||
let provider = Provider::<Http>::try_from("http://localhost:8545").unwrap();
|
||||
let deployer = provider.get_accounts().await.unwrap()[0];
|
||||
|
||||
let client = Arc::new(provider.with_sender(deployer));
|
||||
let contract = deploy(client.clone(), abi, bytecode).await;
|
||||
let deployed_block = client.get_block_number().await.unwrap();
|
||||
|
||||
// assert initial state
|
||||
let value = contract
|
||||
.method::<_, String>("getValue", ())
|
||||
.unwrap()
|
||||
.call()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(value, "initial value");
|
||||
|
||||
// make a call with `client`
|
||||
let _tx_hash = *contract
|
||||
.method::<_, H256>("setValue", "hi".to_owned())
|
||||
.unwrap()
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// assert new value
|
||||
let value = contract
|
||||
.method::<_, String>("getValue", ())
|
||||
.unwrap()
|
||||
.call()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(value, "hi");
|
||||
|
||||
// assert previous value using block hash
|
||||
let hash = client
|
||||
.get_block(deployed_block)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.hash
|
||||
.unwrap();
|
||||
let value = contract
|
||||
.method::<_, String>("getValue", ())
|
||||
.unwrap()
|
||||
.block(BlockId::Hash(hash))
|
||||
.call()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(value, "initial value");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
|
@ -62,14 +62,63 @@ pub struct Log {
|
|||
pub removed: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum FilterBlockOption {
|
||||
Range {
|
||||
from_block: Option<BlockNumber>,
|
||||
to_block: Option<BlockNumber>,
|
||||
},
|
||||
AtBlockHash(H256),
|
||||
}
|
||||
|
||||
impl Default for FilterBlockOption {
|
||||
fn default() -> Self {
|
||||
FilterBlockOption::Range {
|
||||
from_block: None,
|
||||
to_block: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FilterBlockOption {
|
||||
pub fn set_from_block(&self, block: BlockNumber) -> Self {
|
||||
let to_block = if let FilterBlockOption::Range { to_block, .. } = self {
|
||||
*to_block
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
FilterBlockOption::Range {
|
||||
from_block: Some(block),
|
||||
to_block,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_to_block(&self, block: BlockNumber) -> Self {
|
||||
let from_block = if let FilterBlockOption::Range { from_block, .. } = self {
|
||||
*from_block
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
FilterBlockOption::Range {
|
||||
from_block,
|
||||
to_block: Some(block),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_hash(&self, hash: H256) -> Self {
|
||||
FilterBlockOption::AtBlockHash(hash)
|
||||
}
|
||||
}
|
||||
|
||||
/// Filter for
|
||||
#[derive(Default, Debug, PartialEq, Clone)]
|
||||
pub struct Filter {
|
||||
/// From Block
|
||||
pub from_block: Option<BlockNumber>,
|
||||
|
||||
/// To Block
|
||||
pub to_block: Option<BlockNumber>,
|
||||
/// Filter block options, specifying on which blocks the filter should
|
||||
/// match.
|
||||
// https://eips.ethereum.org/EIPS/eip-234
|
||||
pub block_option: FilterBlockOption,
|
||||
|
||||
/// Address
|
||||
// TODO: The spec says that this can also be an array, do we really want to
|
||||
|
@ -91,12 +140,21 @@ impl Serialize for Filter {
|
|||
S: Serializer,
|
||||
{
|
||||
let mut s = serializer.serialize_struct("Filter", 5)?;
|
||||
if let Some(ref from_block) = self.from_block {
|
||||
s.serialize_field("fromBlock", from_block)?;
|
||||
}
|
||||
match self.block_option {
|
||||
FilterBlockOption::Range {
|
||||
from_block,
|
||||
to_block,
|
||||
} => {
|
||||
if let Some(ref from_block) = from_block {
|
||||
s.serialize_field("fromBlock", from_block)?;
|
||||
}
|
||||
|
||||
if let Some(ref to_block) = self.to_block {
|
||||
s.serialize_field("toBlock", to_block)?;
|
||||
if let Some(ref to_block) = to_block {
|
||||
s.serialize_field("toBlock", to_block)?;
|
||||
}
|
||||
}
|
||||
|
||||
FilterBlockOption::AtBlockHash(ref h) => s.serialize_field("blockHash", h)?,
|
||||
}
|
||||
|
||||
if let Some(ref address) = self.address {
|
||||
|
@ -131,13 +189,19 @@ impl Filter {
|
|||
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn from_block<T: Into<BlockNumber>>(mut self, block: T) -> Self {
|
||||
self.from_block = Some(block.into());
|
||||
self.block_option = self.block_option.set_from_block(block.into());
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn to_block<T: Into<BlockNumber>>(mut self, block: T) -> Self {
|
||||
self.to_block = Some(block.into());
|
||||
self.block_option = self.block_option.set_to_block(block.into());
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn at_block_hash<T: Into<H256>>(mut self, hash: T) -> Self {
|
||||
self.block_option = self.block_option.set_hash(hash.into());
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ mod linear;
|
|||
pub use linear::LinearGasPrice;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use ethers_core::types::{BlockNumber, TransactionRequest, TxHash, U256};
|
||||
use ethers_core::types::{BlockId, TransactionRequest, TxHash, U256};
|
||||
use ethers_providers::{interval, FromErr, Middleware, PendingTransaction, StreamExt};
|
||||
use futures_util::lock::Mutex;
|
||||
use std::sync::Arc;
|
||||
|
@ -64,7 +64,7 @@ pub struct GasEscalatorMiddleware<M, E> {
|
|||
pub(crate) escalator: E,
|
||||
/// The transactions which are currently being monitored for escalation
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub txs: Arc<Mutex<Vec<(TxHash, TransactionRequest, Instant, Option<BlockNumber>)>>>,
|
||||
pub txs: Arc<Mutex<Vec<(TxHash, TransactionRequest, Instant, Option<BlockId>)>>>,
|
||||
frequency: Frequency,
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ where
|
|||
async fn send_transaction(
|
||||
&self,
|
||||
tx: TransactionRequest,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<PendingTransaction<'_, Self::Provider>, Self::Error> {
|
||||
let pending_tx = self
|
||||
.inner()
|
||||
|
|
|
@ -59,7 +59,7 @@ where
|
|||
async fn send_transaction(
|
||||
&self,
|
||||
mut tx: TransactionRequest,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<PendingTransaction<'_, Self::Provider>, Self::Error> {
|
||||
if tx.gas_price.is_none() {
|
||||
tx.gas_price = Some(self.get_gas_price().await?);
|
||||
|
|
|
@ -37,7 +37,7 @@ where
|
|||
|
||||
async fn get_transaction_count_with_manager(
|
||||
&self,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<U256, NonceManagerError<M>> {
|
||||
// initialize the nonce the first time the manager is called
|
||||
if !self.initialized.load(Ordering::SeqCst) {
|
||||
|
@ -87,7 +87,7 @@ where
|
|||
async fn send_transaction(
|
||||
&self,
|
||||
mut tx: TransactionRequest,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<PendingTransaction<'_, Self::Provider>, Self::Error> {
|
||||
if tx.nonce.is_none() {
|
||||
tx.nonce = Some(self.get_transaction_count_with_manager(block).await?);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use ethers_core::{
|
||||
types::{
|
||||
Address, BlockNumber, Bytes, NameOrAddress, Signature, Transaction, TransactionRequest,
|
||||
U256,
|
||||
Address, BlockId, Bytes, NameOrAddress, Signature, Transaction, TransactionRequest, U256,
|
||||
},
|
||||
utils::keccak256,
|
||||
};
|
||||
|
@ -176,7 +175,7 @@ where
|
|||
async fn fill_transaction(
|
||||
&self,
|
||||
tx: &mut TransactionRequest,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<(), SignerMiddlewareError<M, S>> {
|
||||
// set the `from` field
|
||||
if tx.from.is_none() {
|
||||
|
@ -246,7 +245,7 @@ where
|
|||
async fn send_transaction(
|
||||
&self,
|
||||
mut tx: TransactionRequest,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<PendingTransaction<'_, Self::Provider>, Self::Error> {
|
||||
if let Some(NameOrAddress::Name(ens_name)) = tx.to {
|
||||
let addr = self
|
||||
|
|
|
@ -56,7 +56,7 @@ where
|
|||
async fn send_transaction(
|
||||
&self,
|
||||
mut tx: TransactionRequest,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<PendingTransaction<'_, Self::Provider>, Self::Error> {
|
||||
// resolve the to field if that's an ENS name.
|
||||
if let Some(NameOrAddress::Name(ens_name)) = tx.to {
|
||||
|
|
|
@ -25,7 +25,7 @@ async fn nonce_manager() {
|
|||
let provider = NonceManagerMiddleware::new(provider, address);
|
||||
|
||||
let nonce = provider
|
||||
.get_transaction_count(address, Some(BlockNumber::Pending))
|
||||
.get_transaction_count(address, Some(BlockNumber::Pending.into()))
|
||||
.await
|
||||
.unwrap()
|
||||
.as_u64();
|
||||
|
|
|
@ -188,7 +188,7 @@ pub trait Middleware: Sync + Send + Debug {
|
|||
async fn send_transaction(
|
||||
&self,
|
||||
tx: TransactionRequest,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<PendingTransaction<'_, Self::Provider>, Self::Error> {
|
||||
self.inner()
|
||||
.send_transaction(tx, block)
|
||||
|
@ -233,7 +233,7 @@ pub trait Middleware: Sync + Send + Debug {
|
|||
async fn get_transaction_count<T: Into<NameOrAddress> + Send + Sync>(
|
||||
&self,
|
||||
from: T,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<U256, Self::Error> {
|
||||
self.inner()
|
||||
.get_transaction_count(from, block)
|
||||
|
@ -248,7 +248,7 @@ pub trait Middleware: Sync + Send + Debug {
|
|||
async fn call(
|
||||
&self,
|
||||
tx: &TransactionRequest,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<Bytes, Self::Error> {
|
||||
self.inner().call(tx, block).await.map_err(FromErr::from)
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ pub trait Middleware: Sync + Send + Debug {
|
|||
async fn get_balance<T: Into<NameOrAddress> + Send + Sync>(
|
||||
&self,
|
||||
from: T,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<U256, Self::Error> {
|
||||
self.inner()
|
||||
.get_balance(from, block)
|
||||
|
@ -375,7 +375,7 @@ pub trait Middleware: Sync + Send + Debug {
|
|||
async fn get_code<T: Into<NameOrAddress> + Send + Sync>(
|
||||
&self,
|
||||
at: T,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<Bytes, Self::Error> {
|
||||
self.inner()
|
||||
.get_code(at, block)
|
||||
|
@ -387,7 +387,7 @@ pub trait Middleware: Sync + Send + Debug {
|
|||
&self,
|
||||
from: T,
|
||||
location: H256,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<H256, Self::Error> {
|
||||
self.inner()
|
||||
.get_storage_at(from, location, block)
|
||||
|
|
|
@ -221,7 +221,7 @@ impl<P: JsonRpcClient> Middleware for Provider<P> {
|
|||
async fn get_transaction_count<T: Into<NameOrAddress> + Send + Sync>(
|
||||
&self,
|
||||
from: T,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<U256, ProviderError> {
|
||||
let from = match from.into() {
|
||||
NameOrAddress::Name(ens_name) => self.resolve_name(&ens_name).await?,
|
||||
|
@ -229,7 +229,7 @@ impl<P: JsonRpcClient> Middleware for Provider<P> {
|
|||
};
|
||||
|
||||
let from = utils::serialize(&from);
|
||||
let block = utils::serialize(&block.unwrap_or(BlockNumber::Latest));
|
||||
let block = utils::serialize(&block.unwrap_or_else(|| BlockNumber::Latest.into()));
|
||||
self.request("eth_getTransactionCount", [from, block]).await
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ impl<P: JsonRpcClient> Middleware for Provider<P> {
|
|||
async fn get_balance<T: Into<NameOrAddress> + Send + Sync>(
|
||||
&self,
|
||||
from: T,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<U256, ProviderError> {
|
||||
let from = match from.into() {
|
||||
NameOrAddress::Name(ens_name) => self.resolve_name(&ens_name).await?,
|
||||
|
@ -245,7 +245,7 @@ impl<P: JsonRpcClient> Middleware for Provider<P> {
|
|||
};
|
||||
|
||||
let from = utils::serialize(&from);
|
||||
let block = utils::serialize(&block.unwrap_or(BlockNumber::Latest));
|
||||
let block = utils::serialize(&block.unwrap_or_else(|| BlockNumber::Latest.into()));
|
||||
self.request("eth_getBalance", [from, block]).await
|
||||
}
|
||||
|
||||
|
@ -264,10 +264,10 @@ impl<P: JsonRpcClient> Middleware for Provider<P> {
|
|||
async fn call(
|
||||
&self,
|
||||
tx: &TransactionRequest,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<Bytes, ProviderError> {
|
||||
let tx = utils::serialize(tx);
|
||||
let block = utils::serialize(&block.unwrap_or(BlockNumber::Latest));
|
||||
let block = utils::serialize(&block.unwrap_or_else(|| BlockNumber::Latest.into()));
|
||||
self.request("eth_call", [tx, block]).await
|
||||
}
|
||||
|
||||
|
@ -283,7 +283,7 @@ impl<P: JsonRpcClient> Middleware for Provider<P> {
|
|||
async fn send_transaction(
|
||||
&self,
|
||||
mut tx: TransactionRequest,
|
||||
_: Option<BlockNumber>,
|
||||
_: Option<BlockId>,
|
||||
) -> Result<PendingTransaction<'_, P>, ProviderError> {
|
||||
if tx.from.is_none() {
|
||||
tx.from = self.3;
|
||||
|
@ -426,7 +426,7 @@ impl<P: JsonRpcClient> Middleware for Provider<P> {
|
|||
&self,
|
||||
from: T,
|
||||
location: H256,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<H256, ProviderError> {
|
||||
let from = match from.into() {
|
||||
NameOrAddress::Name(ens_name) => self.resolve_name(&ens_name).await?,
|
||||
|
@ -435,7 +435,7 @@ impl<P: JsonRpcClient> Middleware for Provider<P> {
|
|||
|
||||
let from = utils::serialize(&from);
|
||||
let location = utils::serialize(&location);
|
||||
let block = utils::serialize(&block.unwrap_or(BlockNumber::Latest));
|
||||
let block = utils::serialize(&block.unwrap_or_else(|| BlockNumber::Latest.into()));
|
||||
|
||||
// get the hex encoded value.
|
||||
let value: String = self
|
||||
|
@ -450,7 +450,7 @@ impl<P: JsonRpcClient> Middleware for Provider<P> {
|
|||
async fn get_code<T: Into<NameOrAddress> + Send + Sync>(
|
||||
&self,
|
||||
at: T,
|
||||
block: Option<BlockNumber>,
|
||||
block: Option<BlockId>,
|
||||
) -> Result<Bytes, ProviderError> {
|
||||
let at = match at.into() {
|
||||
NameOrAddress::Name(ens_name) => self.resolve_name(&ens_name).await?,
|
||||
|
@ -458,7 +458,7 @@ impl<P: JsonRpcClient> Middleware for Provider<P> {
|
|||
};
|
||||
|
||||
let at = utils::serialize(&at);
|
||||
let block = utils::serialize(&block.unwrap_or(BlockNumber::Latest));
|
||||
let block = utils::serialize(&block.unwrap_or_else(|| BlockNumber::Latest.into()));
|
||||
self.request("eth_getCode", [at, block]).await
|
||||
}
|
||||
|
||||
|
|
|
@ -23,11 +23,11 @@ async fn main() -> Result<()> {
|
|||
println!("{}", serde_json::to_string(&tx)?);
|
||||
|
||||
let nonce1 = provider
|
||||
.get_transaction_count(from, Some(BlockNumber::Latest))
|
||||
.get_transaction_count(from, Some(BlockNumber::Latest.into()))
|
||||
.await?;
|
||||
|
||||
let nonce2 = provider
|
||||
.get_transaction_count(from, Some(BlockNumber::Number(0.into())))
|
||||
.get_transaction_count(from, Some(BlockNumber::Number(0.into()).into()))
|
||||
.await?;
|
||||
|
||||
assert!(nonce2 < nonce1);
|
||||
|
|
Loading…
Reference in New Issue