From c70cd81de01c6edd2852c00ef1f2900f2b31d827 Mon Sep 17 00:00:00 2001 From: James Prestwich <10149425+prestwich@users.noreply.github.com> Date: Thu, 5 May 2022 07:22:47 -0700 Subject: [PATCH] feature: pending transaction retries repeatedly before assuming dropped (#1221) --- CHANGELOG.md | 2 ++ ethers-providers/src/pending_transaction.rs | 22 ++++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5def5468..810d78da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -153,6 +153,8 @@ ### Unreleased +- Add retries to the pending transaction future + [1221](https://github.com/gakonst/ethers-rs/pull/1221) - Add support for basic and bearer authentication in http and non-wasm websockets. [829](https://github.com/gakonst/ethers-rs/pull/829) - Export `ethers_providers::IpcError` and `ethers_providers::QuorumError` diff --git a/ethers-providers/src/pending_transaction.rs b/ethers-providers/src/pending_transaction.rs index 0e1a8bef..17451b7e 100644 --- a/ethers-providers/src/pending_transaction.rs +++ b/ethers-providers/src/pending_transaction.rs @@ -62,8 +62,11 @@ pub struct PendingTransaction<'a, P> { provider: &'a Provider

, state: PendingTxState<'a>, interval: Box + Send + Unpin>, + retries_remaining: usize, } +const DEFAULT_RETRIES: usize = 3; + impl<'a, P: JsonRpcClient> PendingTransaction<'a, P> { /// Creates a new pending transaction poller from a hash and a provider pub fn new(tx_hash: TxHash, provider: &'a Provider

) -> Self { @@ -74,6 +77,7 @@ impl<'a, P: JsonRpcClient> PendingTransaction<'a, P> { provider, state: PendingTxState::InitialDelay(delay), interval: Box::new(interval(DEFAULT_POLL_INTERVAL)), + retries_remaining: DEFAULT_RETRIES, } } @@ -111,6 +115,13 @@ impl<'a, P: JsonRpcClient> PendingTransaction<'a, P> { self } + + /// Set retries + #[must_use] + pub fn retries(mut self, retries: usize) -> Self { + self.retries_remaining = retries; + self + } } impl<'a, P> PendingTransaction<'a, P> { @@ -188,9 +199,14 @@ impl<'a, P: JsonRpcClient> Future for PendingTransaction<'a, P> { let tx_opt = tx_res.unwrap(); // If the tx is no longer in the mempool, return Ok(None) if tx_opt.is_none() { - tracing::debug!("Dropped from mempool, pending tx {:?}", *this.tx_hash); - *this.state = PendingTxState::Completed; - return Poll::Ready(Ok(None)) + if *this.retries_remaining == 0 { + tracing::debug!("Dropped from mempool, pending tx {:?}", *this.tx_hash); + *this.state = PendingTxState::Completed; + return Poll::Ready(Ok(None)) + } + + *this.retries_remaining -= 1; + rewake_with_new_state!(ctx, this, PendingTxState::PausedGettingTx); } // If it hasn't confirmed yet, poll again later