feat(contract): add helper to query events w/ metadata (block num + tx hash) (#33)

* feat(contract): add helper to query events w/ metadata (block num + tx hash)
This commit is contained in:
Georgios Konstantopoulos 2020-06-22 01:08:40 +03:00 committed by GitHub
parent 833ca33f60
commit 7a17e54fbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 10 deletions

View File

@ -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<HashMap<H256, D>, 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<Vec<(D, LogMeta)>, 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::<Result<_, ContractError>>()?;
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"),
}
}
}

View File

@ -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<P, S>,
confs: usize,
block: BlockNumber,
}
impl<'a, P, S> Deployer<'a, P, S>
@ -28,11 +29,19 @@ where
self
}
pub fn block<T: Into<BlockNumber>>(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<Contract<'a, P, S>, 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,
})
}
}

View File

@ -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", ())