From 5b7578296b9f695300a5ef7f931e3aa2883d68fd Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Thu, 17 Dec 2020 11:23:10 +0200 Subject: [PATCH] fix: reschedule waker even if receipt is not available (#104) PR #103 did not address the Future hanging when the receipt was not immediately available, e.g. in non dev environments --- ethers-providers/src/pending_transaction.rs | 2 +- ethers-providers/tests/provider.rs | 49 +++++++++++++++++---- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/ethers-providers/src/pending_transaction.rs b/ethers-providers/src/pending_transaction.rs index 858dab0c..85c88ce4 100644 --- a/ethers-providers/src/pending_transaction.rs +++ b/ethers-providers/src/pending_transaction.rs @@ -75,7 +75,6 @@ impl<'a, P: JsonRpcClient> Future for PendingTransaction<'a, P> { PendingTxState::GettingReceipt(fut) => { if let Ok(receipt) = futures_util::ready!(fut.as_mut().poll(ctx)) { if let Some(receipt) = receipt { - ctx.waker().wake_by_ref(); *this.state = PendingTxState::CheckingReceipt(Box::new(receipt)) } else { *this.state = PendingTxState::PausedGettingReceipt @@ -83,6 +82,7 @@ impl<'a, P: JsonRpcClient> Future for PendingTransaction<'a, P> { } else { *this.state = PendingTxState::PausedGettingReceipt } + ctx.waker().wake_by_ref(); } PendingTxState::CheckingReceipt(receipt) => { // If we requested more than 1 confirmation, we need to compare the receipt's diff --git a/ethers-providers/tests/provider.rs b/ethers-providers/tests/provider.rs index 62ff0695..5e77f689 100644 --- a/ethers-providers/tests/provider.rs +++ b/ethers-providers/tests/provider.rs @@ -5,8 +5,10 @@ use std::{convert::TryFrom, time::Duration}; mod eth_tests { use super::*; use ethers::{ + middleware::SignerMiddleware, + signers::LocalWallet, types::{BlockId, TransactionRequest, H256}, - utils::{parse_ether, Ganache}, + utils::Ganache, }; #[tokio::test] @@ -87,7 +89,38 @@ mod eth_tests { let provider = Provider::::try_from(ganache.endpoint()) .unwrap() .interval(Duration::from_millis(500u64)); - generic_pending_txs_test(provider).await; + let accounts = provider.get_accounts().await.unwrap(); + generic_pending_txs_test(provider, accounts[0]).await; + } + + #[tokio::test] + async fn pending_txs_with_confirmations_testnet() { + let provider = Provider::::try_from( + "https://rinkeby.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27", + ) + .unwrap(); + let wallet = "59c37cb6b16fa2de30675f034c8008f890f4b2696c729d6267946d29736d73e4" + .parse::() + .unwrap(); + let address = wallet.address(); + let provider = SignerMiddleware::new(provider, wallet); + generic_pending_txs_test(provider, address).await; + } + + #[tokio::test] + #[cfg(any(feature = "tokio-runtime", feature = "tokio-tls"))] + // different keys to avoid nonce errors + async fn websocket_pending_txs_with_confirmations_testnet() { + let provider = + Provider::connect("wss://rinkeby.infura.io/ws/v3/c60b0bb42f8a4c6481ecd229eddaca27") + .await + .unwrap(); + let wallet = "ff7f80c6e9941865266ed1f481263d780169f1d98269c51167d20c630a5fdc8a" + .parse::() + .unwrap(); + let address = wallet.address(); + let provider = SignerMiddleware::new(provider, wallet); + generic_pending_txs_test(provider, address).await; } #[tokio::test] @@ -97,17 +130,15 @@ mod eth_tests { let ganache = Ganache::new().block_time(2u64).spawn(); let ws = Ws::connect(ganache.ws_endpoint()).await.unwrap(); let provider = Provider::new(ws); - generic_pending_txs_test(provider).await; + let accounts = provider.get_accounts().await.unwrap(); + generic_pending_txs_test(provider, accounts[0]).await; } - async fn generic_pending_txs_test(provider: M) { - let accounts = provider.get_accounts().await.unwrap(); - - let tx = TransactionRequest::pay(accounts[0], parse_ether(1u64).unwrap()).from(accounts[0]); + async fn generic_pending_txs_test(provider: M, who: ethers::types::Address) { + let tx = TransactionRequest::new().to(who).from(who); let tx_hash = provider.send_transaction(tx, None).await.unwrap(); let pending_tx = provider.pending_transaction(tx_hash); - let receipt = pending_tx.confirmations(5).await.unwrap(); - + let receipt = pending_tx.confirmations(3).await.unwrap(); // got the correct receipt assert_eq!(receipt.transaction_hash, tx_hash); }