diff --git a/ethers-contract/src/event.rs b/ethers-contract/src/event.rs index c8641fc4..cc80daa8 100644 --- a/ethers-contract/src/event.rs +++ b/ethers-contract/src/event.rs @@ -4,13 +4,14 @@ use ethers_providers::{FilterStream, JsonRpcClient, Provider}; use ethers_core::{ abi::{Detokenize, Event as AbiEvent, RawLog}, - types::{BlockNumber, Filter, Log, ValueOrArray, H256}, + types::{BlockNumber, Filter, Log, TxHash, ValueOrArray, H256, U64}, }; use futures::stream::{Stream, StreamExt}; -use std::{collections::HashMap, marker::PhantomData}; +use std::marker::PhantomData; /// Helper for managing the event filter before querying or streaming its logs +#[derive(Debug)] #[must_use = "event filters do nothing unless you `query` or `stream` them"] pub struct Event<'a: 'b, 'b, P, D> { /// The event filter's state @@ -93,16 +94,16 @@ where Ok(events) } - /// Queries the blockchain for the selected filter and returns a hashmap of - /// txhash -> logs - pub async fn query_with_hashes(&self) -> Result, ContractError> { + /// Queries the blockchain for the selected filter and returns a vector of logs + /// along with their metadata + pub async fn query_with_meta(&self) -> Result, ContractError> { let logs = self.provider.get_logs(&self.filter).await?; let events = logs .into_iter() .map(|log| { - let tx_hash = log.transaction_hash.expect("should have tx hash"); + let meta = LogMeta::from(&log); let event = self.parse_log(log)?; - Ok((tx_hash, event)) + Ok((event, meta)) }) .collect::>()?; Ok(events) @@ -125,3 +126,22 @@ where Ok(D::from_tokens(tokens)?) } } + +/// Metadata inside a log +#[derive(Clone, Debug, PartialEq)] +pub struct LogMeta { + /// The block in which the log was emitted + pub block_number: U64, + + /// The transaction hash in which the log was emitted + pub transaction_hash: TxHash, +} + +impl From<&Log> for LogMeta { + fn from(src: &Log) -> Self { + LogMeta { + block_number: src.block_number.expect("should have a block number"), + transaction_hash: src.transaction_hash.expect("should have a tx hash"), + } + } +} diff --git a/ethers-contract/src/factory.rs b/ethers-contract/src/factory.rs index 8b5ec5a7..1a0fee65 100644 --- a/ethers-contract/src/factory.rs +++ b/ethers-contract/src/factory.rs @@ -2,7 +2,7 @@ use crate::{Contract, ContractError}; use ethers_core::{ abi::{Abi, Tokenize}, - types::{Bytes, TransactionRequest}, + types::{BlockNumber, Bytes, TransactionRequest}, }; use ethers_providers::JsonRpcClient; use ethers_signers::{Client, Signer}; @@ -15,6 +15,7 @@ pub struct Deployer<'a, P, S> { abi: Abi, client: &'a Client, confs: usize, + block: BlockNumber, } impl<'a, P, S> Deployer<'a, P, S> @@ -28,11 +29,19 @@ where self } + pub fn block>(mut self, block: T) -> Self { + self.block = block.into(); + self + } + /// Broadcasts the contract deployment transaction and after waiting for it to /// be sufficiently confirmed (default: 1), it returns a [`Contract`](crate::Contract) /// struct at the deployed contract's address. pub async fn send(self) -> Result, ContractError> { - let pending_tx = self.client.send_transaction(self.tx, None).await?; + let pending_tx = self + .client + .send_transaction(self.tx, Some(self.block)) + .await?; let receipt = pending_tx.confirmations(self.confs).await?; @@ -159,6 +168,7 @@ where abi: self.abi, tx, confs: 1, + block: BlockNumber::Latest, }) } } diff --git a/ethers-contract/tests/contract.rs b/ethers-contract/tests/contract.rs index e0907d32..af1ed40b 100644 --- a/ethers-contract/tests/contract.rs +++ b/ethers-contract/tests/contract.rs @@ -176,6 +176,7 @@ mod celo_tests { use ethers::{ providers::{Http, Provider}, signers::Wallet, + types::BlockNumber, }; use std::convert::TryFrom; @@ -195,7 +196,7 @@ mod celo_tests { let factory = ContractFactory::new(abi, bytecode, &client); let deployer = factory.deploy("initial value".to_string()).unwrap(); - let contract = deployer.send().await.unwrap(); + let contract = deployer.block(BlockNumber::Pending).send().await.unwrap(); let value: String = contract .method("getValue", ())