From 91133a00f9d4d129bfc21d10d6ac9213fcd709e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 20 Mar 2019 15:21:29 +0100 Subject: [PATCH 1/4] Query contract events. --- .editorconfig | 2 +- src/contract/mod.rs | 40 +++++++++++++++++++++++++++++++++++++++- src/types/traces.rs | 2 +- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/.editorconfig b/.editorconfig index 37ed9966..9810695a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,7 +1,7 @@ root = true [*] indent_style=space -indent_size=2 +indent_size=4 tab_width=4 end_of_line=lf charset=utf-8 diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 93801b20..4446013e 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -6,7 +6,8 @@ use std::time; use api::{Eth, Namespace}; use confirm; use contract::tokens::{Detokenize, Tokenize}; -use types::{Address, BlockNumber, Bytes, CallRequest, H256, TransactionCondition, TransactionRequest, U256}; +use types::{Address, BlockNumber, Bytes, CallRequest, H256, TransactionCondition, TransactionRequest, U256, Log, +FilterBuilder}; use Transport; mod error; @@ -204,6 +205,43 @@ impl Contract { }) .unwrap_or_else(Into::into) } + + /// Find events matching the topics. + pub fn events( + &self, + event: &str, + topic0: A, + topic1: B, + topic2: C, + ) -> CallFuture, T::Out> + where + A: Tokenize, + B: Tokenize, + C: Tokenize, + { + fn to_topic(x: A) -> ethabi::Topic { + let tokens = x.into_tokens(); + if tokens.is_empty() { + ethabi::Topic::Any + } else { + tokens.into() + } + } + + self.abi + .event(event) + .and_then(|ev| { + ev.filter(ethabi::RawTopicFilter { + topic0: to_topic(topic0), + topic1: to_topic(topic1), + topic2: to_topic(topic2), + }) + }) + .map(|filter| { + self.eth.logs(FilterBuilder::default().topic_filter(filter).build()).into() + }) + .unwrap_or_else(Into::into) + } } #[cfg(test)] diff --git a/src/types/traces.rs b/src/types/traces.rs index 2336668d..f3496eac 100644 --- a/src/types/traces.rs +++ b/src/types/traces.rs @@ -1,5 +1,5 @@ //! Types for the Parity Ad-Hoc Trace API -use types::{H160, H256, U256, Bytes, Action, Res, Address}; +use types::{H160, H256, U256, Bytes, Action, Res}; use std::collections::BTreeMap; use serde_derive::{Deserialize, Serialize}; From 50eaf081f0b66478388a1f6df7e211c639ccc690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 20 Mar 2019 16:01:21 +0100 Subject: [PATCH 2/4] Parse logs. --- src/contract/mod.rs | 45 ++++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 4446013e..704c644c 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -6,6 +6,7 @@ use std::time; use api::{Eth, Namespace}; use confirm; use contract::tokens::{Detokenize, Tokenize}; +use futures::{Future, future::{self, Either}}; use types::{Address, BlockNumber, Bytes, CallRequest, H256, TransactionCondition, TransactionRequest, U256, Log, FilterBuilder}; use Transport; @@ -207,17 +208,18 @@ impl Contract { } /// Find events matching the topics. - pub fn events( + pub fn events( &self, event: &str, topic0: A, topic1: B, topic2: C, - ) -> CallFuture, T::Out> + ) -> impl Future, Error = Error> where A: Tokenize, B: Tokenize, C: Tokenize, + R: Detokenize, { fn to_topic(x: A) -> ethabi::Topic { let tokens = x.into_tokens(); @@ -228,19 +230,36 @@ impl Contract { } } - self.abi - .event(event) + let res = self.abi.event(event) .and_then(|ev| { - ev.filter(ethabi::RawTopicFilter { - topic0: to_topic(topic0), - topic1: to_topic(topic1), - topic2: to_topic(topic2), - }) - }) - .map(|filter| { - self.eth.logs(FilterBuilder::default().topic_filter(filter).build()).into() + let filter = ev.filter(ethabi::RawTopicFilter { + topic0: to_topic(topic0), + topic1: to_topic(topic1), + topic2: to_topic(topic2), + })?; + Ok((ev.clone(), filter)) + }); + let (ev, filter) = match res { + Ok(x) => x, + Err(e) => return Either::A(future::err(e.into())), + }; + + Either::B(self.eth.logs(FilterBuilder::default().topic_filter(filter).build()) + .map_err(Into::into) + .and_then(move |logs| { + logs + .into_iter() + .map(move |l| { + let log = ev.parse_log(ethabi::RawLog { + topics: l.topics, + data: l.data.0, + })?; + + Ok(R::from_tokens(log.params.into_iter().map(|x| x.value).collect::>())?) + }) + .collect::, Error>>() }) - .unwrap_or_else(Into::into) + ) } } From c6cb58850baaeb19b64a298066db0cd1b7aa1046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 16 Jun 2020 14:04:54 +0200 Subject: [PATCH 3/4] Add events function. --- examples/bench.rs | 2 +- src/api/accounts.rs | 26 +++++--------------------- src/api/eth_filter.rs | 6 +----- src/api/eth_subscribe.rs | 2 -- src/confirm.rs | 17 +++-------------- src/contract/deploy.rs | 3 --- src/contract/mod.rs | 27 ++++++++++----------------- src/lib.rs | 2 +- 8 files changed, 21 insertions(+), 64 deletions(-) diff --git a/examples/bench.rs b/examples/bench.rs index 5ae100a2..406d7e78 100644 --- a/examples/bench.rs +++ b/examples/bench.rs @@ -18,7 +18,7 @@ async fn main() -> web3::Result { fn bench(id: &str, transport: T, max: usize) where - T::Out: Send + Unpin + 'static, + T::Out: Send + 'static, { use futures::FutureExt; diff --git a/src/api/accounts.rs b/src/api/accounts.rs index d98eccd4..c0efa86e 100644 --- a/src/api/accounts.rs +++ b/src/api/accounts.rs @@ -16,7 +16,6 @@ use rlp::RlpStream; use secp256k1::key::ONE_KEY; use secp256k1::{Message, PublicKey, Secp256k1, SecretKey}; use std::convert::TryInto; -use std::marker::Unpin; use std::mem; use std::ops::Deref; use std::pin::Pin; @@ -49,10 +48,7 @@ impl Accounts { } /// Signs an Ethereum transaction with a given private key. - pub fn sign_transaction(&self, tx: TransactionParameters, key: &SecretKey) -> SignTransactionFuture - where - T::Out: Unpin, - { + pub fn sign_transaction(&self, tx: TransactionParameters, key: &SecretKey) -> SignTransactionFuture { SignTransactionFuture::new(self, tx, key) } @@ -179,19 +175,13 @@ type TxParams = Join3, MaybeReady, MaybeReady -where - T::Out: Unpin, -{ +pub struct SignTransactionFuture { tx: TransactionParameters, key: ZeroizeSecretKey, inner: TxParams, } -impl SignTransactionFuture -where - T::Out: Unpin, -{ +impl SignTransactionFuture { /// Creates a new SignTransactionFuture with accounts and transaction data. pub fn new(accounts: &Accounts, tx: TransactionParameters, key: &SecretKey) -> SignTransactionFuture { macro_rules! maybe { @@ -218,10 +208,7 @@ where } } -impl Future for SignTransactionFuture -where - T::Out: Unpin, -{ +impl Future for SignTransactionFuture { type Output = error::Result; fn poll(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll { @@ -243,10 +230,7 @@ where } } -impl Drop for SignTransactionFuture -where - T::Out: Unpin, -{ +impl Drop for SignTransactionFuture { fn drop(&mut self) { self.key.zeroize(); } diff --git a/src/api/eth_filter.rs b/src/api/eth_filter.rs index 4fca4a31..bae06af0 100644 --- a/src/api/eth_filter.rs +++ b/src/api/eth_filter.rs @@ -67,10 +67,7 @@ enum FilterStreamState { NextItem(vec::IntoIter), } -impl Stream for FilterStream -where - T::Out: Unpin, -{ +impl Stream for FilterStream { type Item = error::Result; fn poll_next(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll> { @@ -232,7 +229,6 @@ pub struct CreateFilter { impl Future for CreateFilter where T: Transport, - T::Out: Unpin, I: Unpin, { type Output = error::Result>; diff --git a/src/api/eth_subscribe.rs b/src/api/eth_subscribe.rs index 8e6c95d8..b99e30df 100644 --- a/src/api/eth_subscribe.rs +++ b/src/api/eth_subscribe.rs @@ -81,7 +81,6 @@ impl SubscriptionStream { impl Stream for SubscriptionStream where T: DuplexTransport, - T::Out: Unpin, T::NotificationStream: Unpin, I: serde::de::DeserializeOwned + Unpin, { @@ -122,7 +121,6 @@ impl Future for SubscriptionResult where T: DuplexTransport, I: serde::de::DeserializeOwned + Unpin, - T::Out: Unpin, { type Output = error::Result>; diff --git a/src/confirm.rs b/src/confirm.rs index 34124c04..321df3bf 100644 --- a/src/confirm.rs +++ b/src/confirm.rs @@ -54,7 +54,6 @@ where impl Future for WaitForConfirmations where T: Transport, - T::Out: Unpin, V: ConfirmationCheck + Unpin, F: Future>> + Unpin, { @@ -126,7 +125,6 @@ impl Confirmations { impl Future for Confirmations where T: Transport, - T::Out: Unpin, V: ConfirmationCheck + Unpin, F: Future>> + Unpin, { @@ -176,10 +174,7 @@ struct TransactionReceiptBlockNumber { future: CallFuture, T::Out>, } -impl Future for TransactionReceiptBlockNumber -where - T::Out: Unpin, -{ +impl Future for TransactionReceiptBlockNumber { type Output = error::Result>; fn poll(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll { @@ -199,10 +194,7 @@ impl TransactionReceiptBlockNumberCheck { } } -impl ConfirmationCheck for TransactionReceiptBlockNumberCheck -where - T::Out: Unpin, -{ +impl ConfirmationCheck for TransactionReceiptBlockNumberCheck { type Check = TransactionReceiptBlockNumber; fn check(&self) -> Self::Check { @@ -259,10 +251,7 @@ impl SendTransactionWithConfirmation { } } -impl Future for SendTransactionWithConfirmation -where - T::Out: Unpin, -{ +impl Future for SendTransactionWithConfirmation { type Output = error::Result; fn poll(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll { diff --git a/src/contract/deploy.rs b/src/contract/deploy.rs index 66cd9e7d..1bb4e7c1 100644 --- a/src/contract/deploy.rs +++ b/src/contract/deploy.rs @@ -55,7 +55,6 @@ impl Builder { where P: Tokenize, V: AsRef, - T::Out: Unpin, { let transport = self.eth.transport().clone(); let poll_interval = self.poll_interval; @@ -81,7 +80,6 @@ impl Builder { where P: Tokenize, V: AsRef, - T::Out: Unpin, { let transport = self.eth.transport().clone(); let poll_interval = self.poll_interval; @@ -176,7 +174,6 @@ impl Future for PendingContract where F: Future> + Unpin, T: Transport, - T::Out: Unpin, { type Output = Result, Error>; diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 0caffe4a..2082497f 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -5,10 +5,10 @@ use crate::confirm; use crate::contract::tokens::{Detokenize, Tokenize}; use crate::types::{ Address, BlockId, Bytes, CallRequest, TransactionCondition, TransactionParameters, TransactionReceipt, - TransactionRequest, H256, U256, + TransactionRequest, H256, U256, FilterBuilder, }; use crate::Transport; -use futures::future::Either; +use futures::{Future, FutureExt, TryFutureExt, future::{self, Either}}; use secp256k1::key::SecretKey; use std::{collections::HashMap, hash::Hash, time}; @@ -157,12 +157,7 @@ impl Contract { options: Options, confirmations: usize, key: &'a SecretKey, - ) -> impl futures::Future> + 'a - where - T::Out: Unpin, - { - use futures::TryFutureExt; - + ) -> impl Future> + 'a { let poll_interval = time::Duration::from_secs(1); self.abi @@ -198,7 +193,7 @@ impl Contract { // TODO [ToDr] SendTransactionWithConfirmation should support custom error type (so that we can return // `contract::Error` instead of more generic `Error`. let err = crate::error::Error::Decoder(format!("{:?}", e)); - Either::Right(futures::future::ready(Err(err))) + Either::Right(future::ready(Err(err))) }) } @@ -317,8 +312,7 @@ impl Contract { topic0: A, topic1: B, topic2: C, - ) -> impl Future, Error = Error> - where + ) -> impl Future>> where A: Tokenize, B: Tokenize, C: Tokenize, @@ -344,13 +338,12 @@ impl Contract { }); let (ev, filter) = match res { Ok(x) => x, - Err(e) => return Either::A(future::err(e.into())), + Err(e) => return Either::Left(future::ready(Err(e.into()))), }; - Either::B(self.eth.logs(FilterBuilder::default().topic_filter(filter).build()) + Either::Right(self.eth.logs(FilterBuilder::default().topic_filter(filter).build()) .map_err(Into::into) - .and_then(move |logs| { - logs + .map(move |logs| logs.and_then(|logs| logs .into_iter() .map(move |l| { let log = ev.parse_log(ethabi::RawLog { @@ -360,8 +353,8 @@ impl Contract { Ok(R::from_tokens(log.params.into_iter().map(|x| x.value).collect::>())?) }) - .collect::, Error>>() - }) + .collect::>>() + )) ) } } diff --git a/src/lib.rs b/src/lib.rs index 003398fd..b7de709a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,7 +41,7 @@ pub type RequestId = usize; /// Transport implementation pub trait Transport: std::fmt::Debug + Clone + Unpin { /// The type of future this transport returns when a call is made. - type Out: futures::Future>; + type Out: futures::Future> + Unpin; /// Prepare serializable RPC call for given method with parameters. fn prepare(&self, method: &str, params: Vec) -> (RequestId, rpc::Call); From 3975e6d5cca048ca7767add58f034a01bf572126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 16 Jun 2020 16:02:27 +0200 Subject: [PATCH 4/4] cargo fmt --all --- src/contract/mod.rs | 71 +++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 2082497f..209ea109 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -4,11 +4,14 @@ use crate::api::{Accounts, Eth, Namespace}; use crate::confirm; use crate::contract::tokens::{Detokenize, Tokenize}; use crate::types::{ - Address, BlockId, Bytes, CallRequest, TransactionCondition, TransactionParameters, TransactionReceipt, - TransactionRequest, H256, U256, FilterBuilder, + Address, BlockId, Bytes, CallRequest, FilterBuilder, TransactionCondition, TransactionParameters, + TransactionReceipt, TransactionRequest, H256, U256, }; use crate::Transport; -use futures::{Future, FutureExt, TryFutureExt, future::{self, Either}}; +use futures::{ + future::{self, Either}, + Future, FutureExt, TryFutureExt, +}; use secp256k1::key::SecretKey; use std::{collections::HashMap, hash::Hash, time}; @@ -307,12 +310,13 @@ impl Contract { /// Find events matching the topics. pub fn events( - &self, - event: &str, - topic0: A, - topic1: B, - topic2: C, - ) -> impl Future>> where + &self, + event: &str, + topic0: A, + topic1: B, + topic2: C, + ) -> impl Future>> + where A: Tokenize, B: Tokenize, C: Tokenize, @@ -327,34 +331,39 @@ impl Contract { } } - let res = self.abi.event(event) - .and_then(|ev| { - let filter = ev.filter(ethabi::RawTopicFilter { - topic0: to_topic(topic0), - topic1: to_topic(topic1), - topic2: to_topic(topic2), - })?; - Ok((ev.clone(), filter)) - }); + let res = self.abi.event(event).and_then(|ev| { + let filter = ev.filter(ethabi::RawTopicFilter { + topic0: to_topic(topic0), + topic1: to_topic(topic1), + topic2: to_topic(topic2), + })?; + Ok((ev.clone(), filter)) + }); let (ev, filter) = match res { Ok(x) => x, Err(e) => return Either::Left(future::ready(Err(e.into()))), }; - Either::Right(self.eth.logs(FilterBuilder::default().topic_filter(filter).build()) - .map_err(Into::into) - .map(move |logs| logs.and_then(|logs| logs - .into_iter() - .map(move |l| { - let log = ev.parse_log(ethabi::RawLog { - topics: l.topics, - data: l.data.0, - })?; - - Ok(R::from_tokens(log.params.into_iter().map(|x| x.value).collect::>())?) + Either::Right( + self.eth + .logs(FilterBuilder::default().topic_filter(filter).build()) + .map_err(Into::into) + .map(move |logs| { + logs.and_then(|logs| { + logs.into_iter() + .map(move |l| { + let log = ev.parse_log(ethabi::RawLog { + topics: l.topics, + data: l.data.0, + })?; + + Ok(R::from_tokens( + log.params.into_iter().map(|x| x.value).collect::>(), + )?) + }) + .collect::>>() }) - .collect::>>() - )) + }), ) } }