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<T: web3::Transport>(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<T: Transport> Accounts<T> { } /// Signs an Ethereum transaction with a given private key. - pub fn sign_transaction(&self, tx: TransactionParameters, key: &SecretKey) -> SignTransactionFuture<T> - where - T::Out: Unpin, - { + pub fn sign_transaction(&self, tx: TransactionParameters, key: &SecretKey) -> SignTransactionFuture<T> { SignTransactionFuture::new(self, tx, key) } @@ -179,19 +175,13 @@ type TxParams<T> = Join3<MaybeReady<T, U256>, MaybeReady<T, U256>, MaybeReady<T, /// parameters required for signing `nonce`, `gas_price` and `chain_id`. Note /// that if all transaction parameters were provided, this future will resolve /// immediately. -pub struct SignTransactionFuture<T: Transport> -where - T::Out: Unpin, -{ +pub struct SignTransactionFuture<T: Transport> { tx: TransactionParameters, key: ZeroizeSecretKey, inner: TxParams<T>, } -impl<T: Transport> SignTransactionFuture<T> -where - T::Out: Unpin, -{ +impl<T: Transport> SignTransactionFuture<T> { /// Creates a new SignTransactionFuture with accounts and transaction data. pub fn new(accounts: &Accounts<T>, tx: TransactionParameters, key: &SecretKey) -> SignTransactionFuture<T> { macro_rules! maybe { @@ -218,10 +208,7 @@ where } } -impl<T: Transport> Future for SignTransactionFuture<T> -where - T::Out: Unpin, -{ +impl<T: Transport> Future for SignTransactionFuture<T> { type Output = error::Result<SignedTransaction>; fn poll(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Self::Output> { @@ -243,10 +230,7 @@ where } } -impl<T: Transport> Drop for SignTransactionFuture<T> -where - T::Out: Unpin, -{ +impl<T: Transport> Drop for SignTransactionFuture<T> { 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<I, O> { NextItem(vec::IntoIter<I>), } -impl<T: Transport, I: DeserializeOwned + Unpin> Stream for FilterStream<T, I> -where - T::Out: Unpin, -{ +impl<T: Transport, I: DeserializeOwned + Unpin> Stream for FilterStream<T, I> { type Item = error::Result<I>; fn poll_next(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Option<Self::Item>> { @@ -232,7 +229,6 @@ pub struct CreateFilter<T: Transport, I> { impl<T, I> Future for CreateFilter<T, I> where T: Transport, - T::Out: Unpin, I: Unpin, { type Output = error::Result<BaseFilter<T, I>>; 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<T: DuplexTransport, I> SubscriptionStream<T, I> { impl<T, I> Stream for SubscriptionStream<T, I> where T: DuplexTransport, - T::Out: Unpin, T::NotificationStream: Unpin, I: serde::de::DeserializeOwned + Unpin, { @@ -122,7 +121,6 @@ impl<T, I> Future for SubscriptionResult<T, I> where T: DuplexTransport, I: serde::de::DeserializeOwned + Unpin, - T::Out: Unpin, { type Output = error::Result<SubscriptionStream<T, I>>; 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<T, V, F> Future for WaitForConfirmations<T, V, F> where T: Transport, - T::Out: Unpin, V: ConfirmationCheck<Check = F> + Unpin, F: Future<Output = error::Result<Option<U64>>> + Unpin, { @@ -126,7 +125,6 @@ impl<T: Transport, V, F> Confirmations<T, V, F> { impl<T, V, F> Future for Confirmations<T, V, F> where T: Transport, - T::Out: Unpin, V: ConfirmationCheck<Check = F> + Unpin, F: Future<Output = error::Result<Option<U64>>> + Unpin, { @@ -176,10 +174,7 @@ struct TransactionReceiptBlockNumber<T: Transport> { future: CallFuture<Option<TransactionReceipt>, T::Out>, } -impl<T: Transport> Future for TransactionReceiptBlockNumber<T> -where - T::Out: Unpin, -{ +impl<T: Transport> Future for TransactionReceiptBlockNumber<T> { type Output = error::Result<Option<U64>>; fn poll(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Self::Output> { @@ -199,10 +194,7 @@ impl<T: Transport> TransactionReceiptBlockNumberCheck<T> { } } -impl<T: Transport> ConfirmationCheck for TransactionReceiptBlockNumberCheck<T> -where - T::Out: Unpin, -{ +impl<T: Transport> ConfirmationCheck for TransactionReceiptBlockNumberCheck<T> { type Check = TransactionReceiptBlockNumber<T>; fn check(&self) -> Self::Check { @@ -259,10 +251,7 @@ impl<T: Transport> SendTransactionWithConfirmation<T> { } } -impl<T: Transport> Future for SendTransactionWithConfirmation<T> -where - T::Out: Unpin, -{ +impl<T: Transport> Future for SendTransactionWithConfirmation<T> { type Output = error::Result<TransactionReceipt>; fn poll(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Self::Output> { 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<T: Transport> Builder<T> { where P: Tokenize, V: AsRef<str>, - T::Out: Unpin, { let transport = self.eth.transport().clone(); let poll_interval = self.poll_interval; @@ -81,7 +80,6 @@ impl<T: Transport> Builder<T> { where P: Tokenize, V: AsRef<str>, - T::Out: Unpin, { let transport = self.eth.transport().clone(); let poll_interval = self.poll_interval; @@ -176,7 +174,6 @@ impl<T, F> Future for PendingContract<T, F> where F: Future<Output = error::Result<TransactionReceipt>> + Unpin, T: Transport, - T::Out: Unpin, { type Output = Result<Contract<T>, Error>; diff --git a/src/contract/mod.rs b/src/contract/mod.rs index a6ddcdd0..209ea109 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -1,16 +1,17 @@ //! Ethereum Contract Interface -use ethabi; - 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, + Address, BlockId, Bytes, CallRequest, FilterBuilder, TransactionCondition, TransactionParameters, + TransactionReceipt, TransactionRequest, H256, U256, }; use crate::Transport; -use futures::future::Either; +use futures::{ + future::{self, Either}, + Future, FutureExt, TryFutureExt, +}; use secp256k1::key::SecretKey; use std::{collections::HashMap, hash::Hash, time}; @@ -159,12 +160,7 @@ impl<T: Transport> Contract<T> { options: Options, confirmations: usize, key: &'a SecretKey, - ) -> impl futures::Future<Output = crate::Result<TransactionReceipt>> + 'a - where - T::Out: Unpin, - { - use futures::TryFutureExt; - + ) -> impl Future<Output = crate::Result<TransactionReceipt>> + 'a { let poll_interval = time::Duration::from_secs(1); self.abi @@ -200,7 +196,7 @@ impl<T: Transport> Contract<T> { // 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))) }) } @@ -311,6 +307,65 @@ impl<T: Transport> Contract<T> { }) .unwrap_or_else(Into::into) } + + /// Find events matching the topics. + pub fn events<A, B, C, R>( + &self, + event: &str, + topic0: A, + topic1: B, + topic2: C, + ) -> impl Future<Output = Result<Vec<R>>> + where + A: Tokenize, + B: Tokenize, + C: Tokenize, + R: Detokenize, + { + fn to_topic<A: Tokenize>(x: A) -> ethabi::Topic<ethabi::Token> { + let tokens = x.into_tokens(); + if tokens.is_empty() { + ethabi::Topic::Any + } else { + tokens.into() + } + } + + 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::<Vec<_>>(), + )?) + }) + .collect::<Result<Vec<R>>>() + }) + }), + ) + } } #[cfg(test)] 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<Output = error::Result<rpc::Value>>; + type Out: futures::Future<Output = error::Result<rpc::Value>> + Unpin; /// Prepare serializable RPC call for given method with parameters. fn prepare(&self, method: &str, params: Vec<rpc::Value>) -> (RequestId, rpc::Call); diff --git a/src/types/traces.rs b/src/types/traces.rs index edbbf06c..f0da17fa 100644 --- a/src/types/traces.rs +++ b/src/types/traces.rs @@ -1,8 +1,8 @@ //! Types for the Parity Ad-Hoc Trace API -use std::collections::BTreeMap; use crate::types::{Action, ActionType, Bytes, Res, H160, H256, U256}; use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; #[derive(Debug, Clone, Serialize)] /// Description of the type of trace to make