feat: allow querying logs with their respective tx hashes

This commit is contained in:
Georgios Konstantopoulos 2020-06-01 00:17:50 +03:00
parent c71c46ff56
commit 095be63b3b
No known key found for this signature in database
GPG Key ID: FA607837CD26EDBC
7 changed files with 40 additions and 8 deletions

View File

@ -7,7 +7,7 @@ use ethers_core::{
types::{BlockNumber, Filter, ValueOrArray, H256},
};
use std::marker::PhantomData;
use std::{collections::HashMap, marker::PhantomData};
pub struct Event<'a, 'b, P, N, D> {
pub filter: Filter,
@ -34,16 +34,27 @@ impl<'a, 'b, P, N, D: Detokenize> Event<'a, 'b, P, N, D> {
self.filter.topics[0] = Some(topic.into());
self
}
pub fn topic1<T: Into<ValueOrArray<H256>>>(mut self, topic: T) -> Self {
self.filter.topics[1] = Some(topic.into());
self
}
}
// TODO: Can we get rid of the static?
impl<'a, 'b, P: JsonRpcClient, N: Network, D: Detokenize> Event<'a, 'b, P, N, D>
impl<'a, 'b, P: JsonRpcClient, N: Network, D: Detokenize + Clone> Event<'a, 'b, P, N, D>
where
P::Error: 'static,
{
/// Queries the blockchain for the selected filter and returns a vector of matching
/// event logs
pub async fn query(self) -> Result<Vec<D>, ContractError<P>> {
Ok(self.query_with_hashes().await?.values().cloned().collect())
}
/// Queries the blockchain for the selected filter and returns a vector of matching
/// event logs
pub async fn query_with_hashes(self) -> Result<HashMap<H256, D>, ContractError<P>> {
// get the logs
let logs = self
.provider
@ -68,9 +79,12 @@ where
.collect::<Vec<_>>();
// convert the tokens to the requested datatype
Ok::<_, ContractError<P>>(D::from_tokens(tokens)?)
Ok::<_, ContractError<P>>((
log.transaction_hash.expect("should have tx hash"),
D::from_tokens(tokens)?,
))
})
.collect::<Result<Vec<_>, _>>()?;
.collect::<Result<HashMap<H256, D>, _>>()?;
Ok(events)
}

View File

@ -1,4 +1,4 @@
mod http;
pub mod http;
mod provider;
pub mod networks;

View File

@ -123,6 +123,12 @@ impl<P: JsonRpcClient, N: Network> Provider<P, N> {
self.0.request("eth_getBalance", Some(&[from, block])).await
}
/// Returns the currently configured chain id, a value used in replay-protected
/// transaction signing as introduced by EIP-155.
pub async fn get_chainid(&self) -> Result<U256, P::Error> {
self.0.request("eth_chainId", None::<()>).await
}
////// Contract Execution
//
// These are relatively low-level calls. The Contracts API should usually be used instead.

View File

@ -106,6 +106,11 @@ where
pub fn provider(&self) -> &Provider<P, N> {
self.provider
}
/// Returns a reference to the client's signer, will panic if no signer is set
pub fn signer_unchecked(&self) -> &S {
self.signer.as_ref().expect("no signer is configured")
}
}
// Abuse Deref to use the Provider's methods without re-writing everything.

View File

@ -1,4 +1,3 @@
// TODO: We might need a `SignerAsync` trait for HSM use cases?
mod wallet;
pub use wallet::Wallet;
@ -11,6 +10,7 @@ use std::error::Error;
/// Trait for signing transactions and messages
///
/// Implement this trait to support different signing modes, e.g. Ledger, hosted etc.
// TODO: We might need a `SignerAsync` trait for HSM use cases?
pub trait Signer {
type Error: Error;
/// Signs the hash of the provided message after prefixing it
@ -31,3 +31,6 @@ pub type MainnetWallet = Wallet<Mainnet>;
/// A wallet which does not use EIP-155 and does not take the chain id into account
/// when creating transactions
pub type AnyWallet = Wallet<Any>;
/// An HTTP client configured to work with ANY blockchain without replay protection
pub type HttpClient<'a> = Client<'a, ethers_providers::http::Provider, Any, Wallet<Any>>;

View File

@ -53,7 +53,11 @@ async fn main() -> Result<()> {
let _tx_hash = contract.set_value("hi".to_owned()).send().await?;
// 11. get all events
let logs = contract.value_changed_filter().from_block(0u64).query().await?;
let logs = contract
.value_changed_filter()
.from_block(0u64)
.query()
.await?;
// 12. get the new value
let value = contract.get_value().call().await?;

View File

@ -151,7 +151,7 @@ pub mod signers {
///
/// let message = "Some data";
/// let key = PrivateKey::new(&mut rand::thread_rng());
/// let address = Address::from(key);
/// let address = Address::from(&key);
///
/// // Sign the message
/// let signature = key.sign(message);