fix: monero wallet refresh

Co-Authored-By: binarybaron <86064887+binarybaron@users.noreply.github.com>
Co-Authored-By: Byron Hambly <351403+delta1@users.noreply.github.com>
This commit is contained in:
Byron Hambly 2024-03-26 15:16:03 +02:00 committed by binarybaron
parent 49a7f7eed6
commit 9f62afedd7
6 changed files with 52 additions and 5 deletions

View File

@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
- Add retry logic to monero-wallet-rpc wallet refresh
## [0.13.0] - 2024-05-29
- Minimum Supported Rust Version (MSRV) bumped to 1.74

View File

@ -162,6 +162,12 @@ pub struct BlockHeight {
pub height: u32,
}
impl fmt::Display for BlockHeight {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.height)
}
}
#[derive(Clone, Copy, Debug, Deserialize)]
#[serde(from = "CheckTxKeyResponse")]
pub struct CheckTxKey {

View File

@ -45,6 +45,7 @@ impl Wallet {
pub async fn connect(client: wallet::Client, name: String, env_config: Config) -> Result<Self> {
let main_address =
monero::Address::from_str(client.get_address(0).await?.address.as_str())?;
Ok(Self {
inner: Mutex::new(client),
network: env_config.monero_network,
@ -144,7 +145,7 @@ impl Wallet {
.await?;
// Try to send all the funds from the generated wallet to the default wallet
match wallet.refresh().await {
match self.refresh(3).await {
Ok(_) => match wallet.sweep_all(self.main_address.to_string()).await {
Ok(sweep_all) => {
for tx in sweep_all.tx_hash_list {
@ -261,8 +262,45 @@ impl Wallet {
self.main_address
}
pub async fn refresh(&self) -> Result<Refreshed> {
Ok(self.inner.lock().await.refresh().await?)
pub async fn refresh(&self, max_attempts: usize) -> Result<Refreshed> {
const RETRY_INTERVAL: Duration = Duration::from_secs(1);
for i in 1..=max_attempts {
tracing::info!(name = %self.name, attempt=i, "Syncing Monero wallet");
let result = self.inner.lock().await.refresh().await;
match result {
Ok(refreshed) => {
tracing::info!(name = %self.name, "Monero wallet synced");
return Ok(refreshed);
}
Err(error) => {
let attempts_left = max_attempts - i;
// We would not want to fail here if the height is not available
// as it is not critical for the operation of the wallet.
// We can just log the error and continue.
let height = match self.inner.lock().await.get_height().await {
Ok(height) => height.to_string(),
Err(_) => {
tracing::warn!(name = %self.name, "Failed to fetch Monero wallet height during sync");
"unknown".to_string()
}
};
if attempts_left == 0 {
tracing::error!(name = %self.name, %height, %error, "Failed to sync Monero wallet");
return Err(error.into());
} else {
tracing::warn!(attempt=i, %height, %attempts_left, name = %self.name, %error, "Failed to sync Monero wallet");
}
}
}
tokio::time::sleep(RETRY_INTERVAL).await;
}
unreachable!("Loop should have returned by now");
}
}

View File

@ -352,6 +352,7 @@ impl WalletRpc {
.arg("--disable-rpc-login")
.arg("--wallet-dir")
.arg(self.working_dir.join("monero-data"))
.arg("--no-initial-sync")
.spawn()?;
let stdout = child

View File

@ -264,7 +264,7 @@ async fn next_state(
}
// Ensure that the generated wallet is synced so we have a proper balance
monero_wallet.refresh().await?;
monero_wallet.refresh(20).await?;
// Sweep (transfer all funds) to the given address
let tx_hashes = monero_wallet.sweep_all(monero_receive_address).await?;

View File

@ -891,7 +891,7 @@ impl Wallet for monero::Wallet {
type Amount = monero::Amount;
async fn refresh(&self) -> Result<()> {
self.refresh().await?;
self.refresh(1).await?;
Ok(())
}