fix(swap): Add retry logic for Bitcoin wallet sync (#333)

This commit is contained in:
Mohan 2025-05-20 14:21:39 +02:00 committed by GitHub
parent 2e2759a318
commit 0e25cb86f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 3 deletions

View file

@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
- CLI + GUI + ASB: Retry the Bitcoin wallet sync up to 15 seconds to work around transient errors.
## [1.1.0] - 2025-05-19 ## [1.1.0] - 2025-05-19
- GUI: Discourage swapping with makers running `< 1.1.0-rc.3` because the bdk upgrade introduced a breaking change. - GUI: Discourage swapping with makers running `< 1.1.0-rc.3` because the bdk upgrade introduced a breaking change.

View file

@ -290,6 +290,9 @@ impl Wallet {
/// The number of maximum chunks to use when syncing /// The number of maximum chunks to use when syncing
const SCAN_CHUNKS: u32 = 5; const SCAN_CHUNKS: u32 = 5;
/// Maximum time we are willing to spend retrying a wallet sync
const SYNC_MAX_ELAPSED_TIME: Duration = Duration::from_secs(15);
const WALLET_PARENT_DIR_NAME: &str = "wallet"; const WALLET_PARENT_DIR_NAME: &str = "wallet";
const WALLET_DIR_NAME: &str = "wallet-post-bdk-1.0"; const WALLET_DIR_NAME: &str = "wallet-post-bdk-1.0";
const WALLET_FILE_NAME: &str = "wallet-db.sqlite"; const WALLET_FILE_NAME: &str = "wallet-db.sqlite";
@ -863,9 +866,9 @@ impl Wallet {
Ok(()) Ok(())
} }
/// Sync the wallet with the blockchain /// Perform a single sync of the wallet with the blockchain
/// and emit progress events to the UI /// and emit progress events to the UI.
pub async fn sync(&self) -> Result<()> { async fn sync_once(&self) -> Result<()> {
let background_process_handle = self let background_process_handle = self
.tauri_handle .tauri_handle
.new_background_process_with_initial_progress( .new_background_process_with_initial_progress(
@ -896,6 +899,29 @@ impl Wallet {
Ok(()) Ok(())
} }
/// Sync the wallet with the blockchain and emit progress events to the UI.
/// Retries the sync if it fails using an exponential backoff.
pub async fn sync(&self) -> Result<()> {
let backoff = backoff::ExponentialBackoffBuilder::new()
.with_max_elapsed_time(Some(Self::SYNC_MAX_ELAPSED_TIME))
.with_max_interval(Duration::from_secs(1))
.build();
backoff::future::retry_notify(
backoff,
|| async { self.sync_once().await.map_err(backoff::Error::transient) },
|err, wait_time: Duration| {
tracing::warn!(
?err,
"Failed to sync Bitcoin wallet. We will retry in {} seconds",
wait_time.as_secs()
);
},
)
.await
.context("Failed to sync Bitcoin wallet after retries")
}
/// Calculate the fee for a given transaction. /// Calculate the fee for a given transaction.
/// ///
/// Will fail if the transaction inputs are not owned by this wallet. /// Will fail if the transaction inputs are not owned by this wallet.