diff --git a/payjoin-cli/src/app/v2/mod.rs b/payjoin-cli/src/app/v2/mod.rs index b1babe65c..05d0e3f22 100644 --- a/payjoin-cli/src/app/v2/mod.rs +++ b/payjoin-cli/src/app/v2/mod.rs @@ -999,7 +999,7 @@ impl App { async fn monitor_payjoin_proposal( &self, - proposal: Receiver, + mut proposal: Receiver, persister: &ReceiverPersister, ) -> Result<()> { // On a session resumption, the receiver will resume again in this state. @@ -1027,8 +1027,17 @@ impl App { println!("Payjoin transaction detected in the mempool!"); return Ok(()); } - Ok(OptionalTransitionOutcome::Stasis(_)) => continue, - Err(_) => continue, + Ok(OptionalTransitionOutcome::Stasis(current_state)) => { + proposal = current_state; + } + Err(e) if e.is_transient() => { + tracing::debug!( + "Transient error checking for transaction, retrying: {e:?}" + ); + proposal = + e.transient_state().expect("transient error carries current state"); + } + Err(e) => return Err(e.into()), } } }) diff --git a/payjoin/src/core/receive/v2/mod.rs b/payjoin/src/core/receive/v2/mod.rs index 1bec60330..fa02402f7 100644 --- a/payjoin/src/core/receive/v2/mod.rs +++ b/payjoin/src/core/receive/v2/mod.rs @@ -1536,7 +1536,7 @@ impl Receiver { /// search for the transaction in the network. Since a non-SegWit input signature is going to /// change the TXID of the Payjoin proposal, it cannot be monitored. pub fn check_for_transaction( - &self, + self, find_transaction: impl Fn(Txid) -> Result, ImplementationError>, ) -> MaybeFatalOrSuccessTransition { let fallback_tx = self.state.fallback_tx(); @@ -1563,7 +1563,7 @@ impl Receiver { Error::Implementation(ImplementationError::from( format!("Payjoin transaction ID mismatch. Expected: {payjoin_txid}, Got: {tx_id}").as_str(), )), - self.clone(), + self, ); } // TODO: should we check for witness and scriptsig on the tx? @@ -1581,10 +1581,7 @@ impl Receiver { } Ok(None) => {} Err(e) => - return MaybeFatalOrSuccessTransition::transient( - Error::Implementation(e), - self.clone(), - ), + return MaybeFatalOrSuccessTransition::transient(Error::Implementation(e), self), } // If the Payjoin proposal was not found, check the fallback transaction, as it is @@ -1596,13 +1593,10 @@ impl Receiver { )), Ok(None) => {} Err(e) => - return MaybeFatalOrSuccessTransition::transient( - Error::Implementation(e), - self.clone(), - ), + return MaybeFatalOrSuccessTransition::transient(Error::Implementation(e), self), } - MaybeFatalOrSuccessTransition::no_results(self.clone()) + MaybeFatalOrSuccessTransition::no_results(self) } } @@ -1759,6 +1753,7 @@ pub mod test { // Nothing was spent, should be in the same state let persister = InMemoryPersister::default(); let res = monitor + .clone() .check_for_transaction(|_| Ok(None)) .save(&persister) .expect("InMemoryPersister shouldn't fail"); @@ -1769,6 +1764,7 @@ pub mod test { // Payjoin was broadcasted, should progress to success let persister = InMemoryPersister::default(); let res = monitor + .clone() .check_for_transaction(|_| Ok(Some(payjoin_tx.clone()))) .save(&persister) .expect("InMemoryPersister shouldn't fail");