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}, types::{BlockNumber, Filter, ValueOrArray, H256},
}; };
use std::marker::PhantomData; use std::{collections::HashMap, marker::PhantomData};
pub struct Event<'a, 'b, P, N, D> { pub struct Event<'a, 'b, P, N, D> {
pub filter: Filter, 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.filter.topics[0] = Some(topic.into());
self 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? // 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 where
P::Error: 'static, P::Error: 'static,
{ {
/// Queries the blockchain for the selected filter and returns a vector of matching /// Queries the blockchain for the selected filter and returns a vector of matching
/// event logs /// event logs
pub async fn query(self) -> Result<Vec<D>, ContractError<P>> { 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 // get the logs
let logs = self let logs = self
.provider .provider
@ -68,9 +79,12 @@ where
.collect::<Vec<_>>(); .collect::<Vec<_>>();
// convert the tokens to the requested datatype // 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) Ok(events)
} }

View File

@ -1,4 +1,4 @@
mod http; pub mod http;
mod provider; mod provider;
pub mod networks; 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 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 ////// Contract Execution
// //
// These are relatively low-level calls. The Contracts API should usually be used instead. // 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> { pub fn provider(&self) -> &Provider<P, N> {
self.provider 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. // 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; mod wallet;
pub use wallet::Wallet; pub use wallet::Wallet;
@ -11,6 +10,7 @@ use std::error::Error;
/// Trait for signing transactions and messages /// Trait for signing transactions and messages
/// ///
/// Implement this trait to support different signing modes, e.g. Ledger, hosted etc. /// 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 { pub trait Signer {
type Error: Error; type Error: Error;
/// Signs the hash of the provided message after prefixing it /// 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 /// A wallet which does not use EIP-155 and does not take the chain id into account
/// when creating transactions /// when creating transactions
pub type AnyWallet = Wallet<Any>; 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?; let _tx_hash = contract.set_value("hi".to_owned()).send().await?;
// 11. get all events // 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 // 12. get the new value
let value = contract.get_value().call().await?; let value = contract.get_value().call().await?;

View File

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