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:
parent
833ca33f60
commit
7a17e54fbd
|
@ -4,13 +4,14 @@ use ethers_providers::{FilterStream, JsonRpcClient, Provider};
|
||||||
|
|
||||||
use ethers_core::{
|
use ethers_core::{
|
||||||
abi::{Detokenize, Event as AbiEvent, RawLog},
|
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 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
|
/// 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"]
|
#[must_use = "event filters do nothing unless you `query` or `stream` them"]
|
||||||
pub struct Event<'a: 'b, 'b, P, D> {
|
pub struct Event<'a: 'b, 'b, P, D> {
|
||||||
/// The event filter's state
|
/// The event filter's state
|
||||||
|
@ -93,16 +94,16 @@ where
|
||||||
Ok(events)
|
Ok(events)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Queries the blockchain for the selected filter and returns a hashmap of
|
/// Queries the blockchain for the selected filter and returns a vector of logs
|
||||||
/// txhash -> logs
|
/// along with their metadata
|
||||||
pub async fn query_with_hashes(&self) -> Result<HashMap<H256, D>, ContractError> {
|
pub async fn query_with_meta(&self) -> Result<Vec<(D, LogMeta)>, ContractError> {
|
||||||
let logs = self.provider.get_logs(&self.filter).await?;
|
let logs = self.provider.get_logs(&self.filter).await?;
|
||||||
let events = logs
|
let events = logs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|log| {
|
.map(|log| {
|
||||||
let tx_hash = log.transaction_hash.expect("should have tx hash");
|
let meta = LogMeta::from(&log);
|
||||||
let event = self.parse_log(log)?;
|
let event = self.parse_log(log)?;
|
||||||
Ok((tx_hash, event))
|
Ok((event, meta))
|
||||||
})
|
})
|
||||||
.collect::<Result<_, ContractError>>()?;
|
.collect::<Result<_, ContractError>>()?;
|
||||||
Ok(events)
|
Ok(events)
|
||||||
|
@ -125,3 +126,22 @@ where
|
||||||
Ok(D::from_tokens(tokens)?)
|
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"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{Contract, ContractError};
|
||||||
|
|
||||||
use ethers_core::{
|
use ethers_core::{
|
||||||
abi::{Abi, Tokenize},
|
abi::{Abi, Tokenize},
|
||||||
types::{Bytes, TransactionRequest},
|
types::{BlockNumber, Bytes, TransactionRequest},
|
||||||
};
|
};
|
||||||
use ethers_providers::JsonRpcClient;
|
use ethers_providers::JsonRpcClient;
|
||||||
use ethers_signers::{Client, Signer};
|
use ethers_signers::{Client, Signer};
|
||||||
|
@ -15,6 +15,7 @@ pub struct Deployer<'a, P, S> {
|
||||||
abi: Abi,
|
abi: Abi,
|
||||||
client: &'a Client<P, S>,
|
client: &'a Client<P, S>,
|
||||||
confs: usize,
|
confs: usize,
|
||||||
|
block: BlockNumber,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, P, S> Deployer<'a, P, S>
|
impl<'a, P, S> Deployer<'a, P, S>
|
||||||
|
@ -28,11 +29,19 @@ where
|
||||||
self
|
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
|
/// Broadcasts the contract deployment transaction and after waiting for it to
|
||||||
/// be sufficiently confirmed (default: 1), it returns a [`Contract`](crate::Contract)
|
/// be sufficiently confirmed (default: 1), it returns a [`Contract`](crate::Contract)
|
||||||
/// struct at the deployed contract's address.
|
/// struct at the deployed contract's address.
|
||||||
pub async fn send(self) -> Result<Contract<'a, P, S>, ContractError> {
|
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?;
|
let receipt = pending_tx.confirmations(self.confs).await?;
|
||||||
|
|
||||||
|
@ -159,6 +168,7 @@ where
|
||||||
abi: self.abi,
|
abi: self.abi,
|
||||||
tx,
|
tx,
|
||||||
confs: 1,
|
confs: 1,
|
||||||
|
block: BlockNumber::Latest,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,6 +176,7 @@ mod celo_tests {
|
||||||
use ethers::{
|
use ethers::{
|
||||||
providers::{Http, Provider},
|
providers::{Http, Provider},
|
||||||
signers::Wallet,
|
signers::Wallet,
|
||||||
|
types::BlockNumber,
|
||||||
};
|
};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
@ -195,7 +196,7 @@ mod celo_tests {
|
||||||
|
|
||||||
let factory = ContractFactory::new(abi, bytecode, &client);
|
let factory = ContractFactory::new(abi, bytecode, &client);
|
||||||
let deployer = factory.deploy("initial value".to_string()).unwrap();
|
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
|
let value: String = contract
|
||||||
.method("getValue", ())
|
.method("getValue", ())
|
||||||
|
|
Loading…
Reference in New Issue