From da8261c613a049bccffa73b3d7bfbbc82cf3187f Mon Sep 17 00:00:00 2001 From: woodser <13068859+woodser@users.noreply.github.com> Date: Sun, 21 Dec 2025 20:53:17 -0500 Subject: [PATCH] update sync progress based on current target height --- .../haveno/core/api/XmrConnectionService.java | 4 +- .../java/haveno/core/app/WalletAppSetup.java | 2 +- .../core/xmr/setup/DownloadListener.java | 20 ++++++- .../haveno/core/xmr/wallet/XmrWalletBase.java | 53 ++++++++++++------- .../core/xmr/wallet/XmrWalletService.java | 6 +-- .../resources/i18n/displayStrings.properties | 3 +- .../i18n/displayStrings_cs.properties | 3 +- .../i18n/displayStrings_de.properties | 3 +- .../i18n/displayStrings_es.properties | 3 +- .../i18n/displayStrings_fa.properties | 3 +- .../i18n/displayStrings_fr.properties | 3 +- .../i18n/displayStrings_it.properties | 3 +- .../i18n/displayStrings_ja.properties | 3 +- .../i18n/displayStrings_pt-br.properties | 3 +- .../i18n/displayStrings_pt.properties | 3 +- .../i18n/displayStrings_ru.properties | 3 +- .../i18n/displayStrings_th.properties | 3 +- .../i18n/displayStrings_tr.properties | 3 +- .../i18n/displayStrings_vi.properties | 3 +- .../i18n/displayStrings_zh-hans.properties | 3 +- .../i18n/displayStrings_zh-hant.properties | 3 +- .../pendingtrades/steps/TradeStepView.java | 32 +++++++---- .../java/haveno/desktop/util/GUIUtil.java | 6 +++ 23 files changed, 118 insertions(+), 53 deletions(-) diff --git a/core/src/main/java/haveno/core/api/XmrConnectionService.java b/core/src/main/java/haveno/core/api/XmrConnectionService.java index 710486d093..30497020ea 100644 --- a/core/src/main/java/haveno/core/api/XmrConnectionService.java +++ b/core/src/main/java/haveno/core/api/XmrConnectionService.java @@ -895,10 +895,10 @@ public final class XmrConnectionService { if (lastInfo.isSynchronized() || isTestnet) doneDownload(); // TODO: skipping synchronized check for testnet because CI tests do not sync 3rd local node, see "Can manage Monero daemon connections" else if (lastInfo.isBusySyncing()) { long targetHeight = lastInfo.getTargetHeight(); - long blocksLeft = targetHeight - lastInfo.getHeight(); + long blocksRemaining = targetHeight - lastInfo.getHeight(); if (syncStartHeight == null) syncStartHeight = lastInfo.getHeight(); double percent = Math.min(1.0, targetHeight == syncStartHeight ? 1.0 : ((double) Math.max(1, lastInfo.getHeight() - syncStartHeight) / (double) (targetHeight - syncStartHeight))); // grant at least 1 block to show progress - downloadListener.progress(percent, blocksLeft, null); + downloadListener.progress(percent, blocksRemaining, null); } // set available connections diff --git a/core/src/main/java/haveno/core/app/WalletAppSetup.java b/core/src/main/java/haveno/core/app/WalletAppSetup.java index 6bf3b71f8b..6c4ae2bd7d 100644 --- a/core/src/main/java/haveno/core/app/WalletAppSetup.java +++ b/core/src/main/java/haveno/core/app/WalletAppSetup.java @@ -154,7 +154,7 @@ public class WalletAppSetup { xmrWalletSyncProgress.set(walletDownloadPercentageD); Long bestWalletHeight = walletHeight == null ? null : (Long) walletHeight; String walletHeightAsString = bestWalletHeight != null && bestWalletHeight > 0 ? String.valueOf(bestWalletHeight) : ""; - if (walletDownloadPercentageD == 1) { + if (walletDownloadPercentageD >= 1) { String synchronizedWith = Res.get("mainView.footer.xmrInfo.syncedWith", getXmrWalletNetworkAsString(), walletHeightAsString); String feeInfo = ""; // TODO: feeService.isFeeAvailable() returns true, disable result = Res.get("mainView.footer.xmrInfo", synchronizedWith, feeInfo); diff --git a/core/src/main/java/haveno/core/xmr/setup/DownloadListener.java b/core/src/main/java/haveno/core/xmr/setup/DownloadListener.java index 325328a6e6..1232caa619 100644 --- a/core/src/main/java/haveno/core/xmr/setup/DownloadListener.java +++ b/core/src/main/java/haveno/core/xmr/setup/DownloadListener.java @@ -2,18 +2,26 @@ package haveno.core.xmr.setup; import haveno.common.UserThread; import javafx.beans.property.DoubleProperty; +import javafx.beans.property.LongProperty; import javafx.beans.property.ReadOnlyDoubleProperty; import javafx.beans.property.SimpleDoubleProperty; +import javafx.beans.property.SimpleLongProperty; import java.util.Date; public class DownloadListener { private final DoubleProperty percentage = new SimpleDoubleProperty(-1); + private final LongProperty blocksRemaining = new SimpleLongProperty(-1); + private final LongProperty numUpdates = new SimpleLongProperty(0); // TODO: remove redundant execute? - public void progress(double percentage, long blocksLeft, Date date) { + public void progress(double percentage, long blocksRemaining, Date date) { UserThread.execute(() -> { - UserThread.await(() -> this.percentage.set(percentage)); // TODO: these awaits are jenky + UserThread.await(() -> { + this.percentage.set(percentage); + this.blocksRemaining.set(blocksRemaining); + this.numUpdates.set(this.numUpdates.get() + 1); + }); // TODO: these awaits are jenky }); } @@ -21,7 +29,15 @@ public class DownloadListener { UserThread.await(() -> this.percentage.set(1d)); } + public LongProperty numUpdates() { + return numUpdates; + } + public ReadOnlyDoubleProperty percentageProperty() { return percentage; } + + public LongProperty blocksRemainingProperty() { + return blocksRemaining; + } } diff --git a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletBase.java b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletBase.java index 81bcb8d499..15d4370fa2 100644 --- a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletBase.java +++ b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletBase.java @@ -12,6 +12,9 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.fxmisc.easybind.EasyBind; +import org.fxmisc.easybind.Subscription; + import haveno.common.ThreadUtils; import haveno.common.Timer; import haveno.common.UserThread; @@ -20,6 +23,7 @@ import haveno.core.trade.HavenoUtils; import haveno.core.xmr.setup.DownloadListener; import javafx.beans.property.LongProperty; import javafx.beans.property.ReadOnlyDoubleProperty; +import javafx.beans.property.ReadOnlyLongProperty; import javafx.beans.property.SimpleLongProperty; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -58,7 +62,8 @@ public abstract class XmrWalletBase { protected CountDownLatch syncProgressLatch; protected Exception syncProgressError; protected Timer syncProgressTimeout; - protected final DownloadListener walletSyncListener = new DownloadListener(); + @Getter + protected final DownloadListener syncProgressListener = new DownloadListener(); protected final LongProperty walletHeight = new SimpleLongProperty(0); @Getter protected boolean isShutDownStarted; @@ -115,12 +120,17 @@ public abstract class XmrWalletBase { } public void syncWithProgress() { - syncWithProgress(false); - } - - public void syncWithProgress(boolean repeatSyncToLatestHeight) { MoneroWallet sourceWallet = wallet; synchronized (walletLock) { + + // subscribe to height updates for latest sync progress + Subscription connectionUpdateSubscription; + synchronized (xmrConnectionService.numUpdatesProperty()) { // prevent subscribing concurrently + connectionUpdateSubscription = EasyBind.subscribe(xmrConnectionService.numUpdatesProperty(), newValue -> { + if (newValue != null) updateSyncProgress(null); + }); + } + try { // set initial state @@ -129,9 +139,7 @@ public abstract class XmrWalletBase { isSyncingWithProgress = true; syncStartHeight = null; syncProgressError = null; - walletSyncListener.progress(0, -1, null); // reset progress - long targetHeightAtStart = xmrConnectionService.getTargetHeight(); - updateSyncProgress(walletHeight.get(), targetHeightAtStart); + updateSyncProgress(wallet.getHeight()); // test connection changing on startup before wallet synced if (testReconnectOnStartup) { @@ -149,8 +157,7 @@ public abstract class XmrWalletBase { wallet.sync(new MoneroWalletListener() { @Override public void onSyncProgress(long height, long startHeight, long endHeight, double percentDone, String message) { - long appliedTargetHeight = repeatSyncToLatestHeight ? xmrConnectionService.getTargetHeight() : targetHeightAtStart; - updateSyncProgress(height, appliedTargetHeight); + updateSyncProgress(height); } }); onDoneSyncWithProgress(); @@ -184,9 +191,9 @@ public abstract class XmrWalletBase { } // update sync progress - long appliedTargetHeight = repeatSyncToLatestHeight ? xmrConnectionService.getTargetHeight() : targetHeightAtStart; - updateSyncProgress(height, appliedTargetHeight); - if (height >= appliedTargetHeight) { + long targetHeight = xmrConnectionService.getTargetHeight(); + updateSyncProgress(height); + if (height >= targetHeight) { syncProgressLatch.countDown(); } }); @@ -205,6 +212,7 @@ public abstract class XmrWalletBase { } finally { isSyncingWithProgress = false; if (syncProgressTimeout != null) syncProgressTimeout.stop(); + connectionUpdateSubscription.unsubscribe(); } } } @@ -239,7 +247,11 @@ public abstract class XmrWalletBase { } public ReadOnlyDoubleProperty downloadPercentageProperty() { - return walletSyncListener.percentageProperty(); + return syncProgressListener.percentageProperty(); + } + + public ReadOnlyLongProperty blocksRemainingProperty() { + return syncProgressListener.blocksRemainingProperty(); } public static boolean isSyncWithProgressTimeout(Throwable e) { @@ -254,7 +266,10 @@ public abstract class XmrWalletBase { // ------------------------------ PRIVATE HELPERS ------------------------- - private void updateSyncProgress(long height, long targetHeight) { + private void updateSyncProgress(Long height) { + + // use last height if no update + if (height == null) height = walletHeight.get(); // reset progress timeout if height advanced if (height != walletHeight.get()) { @@ -264,15 +279,13 @@ public abstract class XmrWalletBase { // set wallet height walletHeight.set(height); - // new wallet reports height 0 or 1 before synced - if (height <= 1) return; - // set progress - long blocksLeft = targetHeight - height; + long targetHeight = xmrConnectionService.getTargetHeight(); + long blocksRemaining = height <= 1 ? -1 : targetHeight - height; // unknown blocks left if height <= 1 if (syncStartHeight == null) syncStartHeight = height; double percent = Math.min(1.0, targetHeight == syncStartHeight ? 1.0 : ((double) height - syncStartHeight) / (double) (targetHeight - syncStartHeight)); if (percent >= 1.0) wasWalletSynced = true; // set synced state before announcing progress - walletSyncListener.progress(percent, blocksLeft, null); + syncProgressListener.progress(percent, blocksRemaining, null); } private synchronized void resetSyncProgressTimeout() { diff --git a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java index 01c92f3116..ccff190711 100644 --- a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java +++ b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java @@ -202,7 +202,7 @@ public class XmrWalletService extends XmrWalletBase { public void onAccountClosed() { log.info("onAccountClosed()"); wasWalletSynced = false; - walletSyncListener.progress(-1, -1, null); + syncProgressListener.progress(-1, -1, null); closeMainWallet(true); // TODO: reset more properties? } @@ -1459,7 +1459,7 @@ public class XmrWalletService extends XmrWalletBase { long time = System.currentTimeMillis(); MoneroRpcConnection sourceConnection = xmrConnectionService.getConnection(); try { - syncWithProgress(!wasWalletSynced); // repeat sync to latest target height until first sync + syncWithProgress(); } catch (Exception e) { if (wallet != null) log.warn("Error syncing wallet with progress on startup: " + e.getMessage()); forceCloseMainWallet(); @@ -1488,7 +1488,7 @@ public class XmrWalletService extends XmrWalletBase { resetIfWalletChanged(); // signal that main wallet is synced - walletSyncListener.doneDownload(); + syncProgressListener.doneDownload(); // notify setup that main wallet is initialized // TODO: app fully initializes after this is set to true, even though wallet might not be initialized if unconnected. wallet will be created when connection detected diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index b52f3b649d..c89f764f5b 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -660,7 +660,8 @@ portfolio.pending.unconfirmedTooLong=Deposit transactions on trade {0} are still confirmed in Haveno, try restarting Haveno.\n\n\ If the problem persists, contact Haveno support [HYPERLINK:https://matrix.to/#/#haveno:monero.social]. -portfolio.pending.syncing=Syncing trade wallet — {0}% ({1} blocks remaining) +portfolio.pending.syncing=Syncing trade wallet — {0}% +portfolio.pending.syncing.blocksRemaining=Syncing trade wallet — {0}% ({1} blocks remaining) portfolio.pending.step1.waitForConf=Wait for blockchain confirmations portfolio.pending.step2_buyer.additionalConf=Deposits have reached 10 confirmations.\nFor extra security, we recommend waiting {0} confirmations before sending payment.\nProceed early at your own risk. portfolio.pending.step2_buyer.startPayment=Start payment diff --git a/core/src/main/resources/i18n/displayStrings_cs.properties b/core/src/main/resources/i18n/displayStrings_cs.properties index 66727ff9aa..8aa4334d55 100644 --- a/core/src/main/resources/i18n/displayStrings_cs.properties +++ b/core/src/main/resources/i18n/displayStrings_cs.properties @@ -660,7 +660,8 @@ portfolio.pending.unconfirmedTooLong=Vkladové transakce obchodu {0} jsou stále potvrzené v Haveno, zkuste Haveno restartovat.\n\n\ Pokud problém přetrvává, kontaktujte podporu Haveno [HYPERLINK:https://matrix.to/#/#haveno:monero.social]. -portfolio.pending.syncing=Synchronizuji obchodní peněženku — {0}% ({1} bloků zbývá) +portfolio.pending.syncing=Synchronizuji obchodní peněženku — {0}% +portfolio.pending.syncing.blocksRemaining=Synchronizuji obchodní peněženku — {0}% ({1} bloků zbývá) portfolio.pending.step1.waitForConf=Počkejte na potvrzení na blockchainu portfolio.pending.step2_buyer.additionalConf=Vklady dosáhly 10 potvrzení.\nPro vyšší bezpečnost doporučujeme počkat na {0} potvrzení před odesláním platby.\nPokračujte dříve na vlastní riziko. portfolio.pending.step2_buyer.startPayment=Zahajte platbu diff --git a/core/src/main/resources/i18n/displayStrings_de.properties b/core/src/main/resources/i18n/displayStrings_de.properties index 1031956088..27a5863a25 100644 --- a/core/src/main/resources/i18n/displayStrings_de.properties +++ b/core/src/main/resources/i18n/displayStrings_de.properties @@ -577,7 +577,8 @@ portfolio.closedTrades.deviation.help=Prozentuale Preisabweichung vom Markt portfolio.pending.invalidTx=There is an issue with a missing or invalid transaction.\n\nPlease do NOT send the traditional or crypto payment.\n\nOpen a support ticket to get assistance from a Mediator.\n\nError message: {0} -portfolio.pending.syncing=Handelwallet wird synchronisiert — {0}% ({1} Blöcke verbleibend) +portfolio.pending.syncing=Handelwallet wird synchronisiert — {0}% +portfolio.pending.syncing.blocksRemaining=Handelwallet wird synchronisiert — {0}% ({1} Blöcke verbleibend) portfolio.pending.step1.waitForConf=Auf Blockchain-Bestätigung warten portfolio.pending.step2_buyer.additionalConf=Einzahlungen haben 10 Bestätigungen erreicht.\nFür zusätzliche Sicherheit empfehlen wir, {0} Bestätigungen abzuwarten, bevor Sie die Zahlung senden.\nEin früheres Vorgehen erfolgt auf eigenes Risiko. portfolio.pending.step2_buyer.startPayment=Zahlung beginnen diff --git a/core/src/main/resources/i18n/displayStrings_es.properties b/core/src/main/resources/i18n/displayStrings_es.properties index 97a8cb9cbf..4cc0d5b2e2 100644 --- a/core/src/main/resources/i18n/displayStrings_es.properties +++ b/core/src/main/resources/i18n/displayStrings_es.properties @@ -577,7 +577,8 @@ portfolio.closedTrades.deviation.help=Desviación porcentual de precio de mercad portfolio.pending.invalidTx=Hay un problema con una transacción inválida o no encontrada.\n\nPor faovr NO envíe el pago de traditional o cryptos.\n\nAbra un ticket de soporte para obtener asistencia de un mediador.\n\nMensaje de error: {0} -portfolio.pending.syncing=Sincronizando la billetera de comercio — {0}% ({1} bloques restantes) +portfolio.pending.syncing=Sincronizando la billetera de comercio — {0}% +portfolio.pending.syncing.blocksRemaining=Sincronizando la billetera de comercio — {0}% ({1} bloques restantes) portfolio.pending.step1.waitForConf=Esperar a la confirmación en la cadena de bloques portfolio.pending.step2_buyer.additionalConf=Los depósitos han alcanzado 10 confirmaciones.\nPara mayor seguridad, recomendamos esperar {0} confirmaciones antes de enviar el pago.\nProceda antes bajo su propio riesgo. portfolio.pending.step2_buyer.startPayment=Comenzar pago diff --git a/core/src/main/resources/i18n/displayStrings_fa.properties b/core/src/main/resources/i18n/displayStrings_fa.properties index 9f93bcf539..35f6053223 100644 --- a/core/src/main/resources/i18n/displayStrings_fa.properties +++ b/core/src/main/resources/i18n/displayStrings_fa.properties @@ -576,7 +576,8 @@ portfolio.closedTrades.deviation.help=Percentage price deviation from market portfolio.pending.invalidTx=There is an issue with a missing or invalid transaction.\n\nPlease do NOT send the traditional or crypto payment.\n\nOpen a support ticket to get assistance from a Mediator.\n\nError message: {0} -portfolio.pending.syncing=همگام‌سازی کیف‌پول معامله — {0}% ({1} بلاک باقی‌مانده) +portfolio.pending.syncing=همگام‌سازی کیف پول معامله — {0}% +portfolio.pending.syncing.blocksRemaining=همگام‌سازی کیف‌پول معامله — {0}% ({1} بلاک باقی‌مانده) portfolio.pending.step1.waitForConf=برای تأییدیه بلاک چین منتظر باشید portfolio.pending.step2_buyer.additionalConf=واریزها به ۱۰ تأیید رسیده‌اند.\nبرای امنیت بیشتر، توصیه می‌کنیم قبل از ارسال پرداخت، {0} تأیید صبر کنید.\nاقدام زودهنگام با مسئولیت خودتان است. portfolio.pending.step2_buyer.startPayment=آغاز پرداخت diff --git a/core/src/main/resources/i18n/displayStrings_fr.properties b/core/src/main/resources/i18n/displayStrings_fr.properties index ae3bd243ae..4952f7a945 100644 --- a/core/src/main/resources/i18n/displayStrings_fr.properties +++ b/core/src/main/resources/i18n/displayStrings_fr.properties @@ -577,7 +577,8 @@ portfolio.closedTrades.deviation.help=Pourcentage de déviation du prix par rapp portfolio.pending.invalidTx=Il y'a un problème avec une transaction manquante ou invalide.\n\nVeuillez NE PAS envoyer le payement Traditional ou crypto.\n\nOuvrez un ticket de support pour avoir l'aide d'un médiateur.\n\nMessage d'erreur: {0} -portfolio.pending.syncing=Synchronisation du portefeuille de trading — {0}% ({1} blocs restants) +portfolio.pending.syncing=Synchronisation du portefeuille de trading — {0}% +portfolio.pending.syncing.blocksRemaining=Synchronisation du portefeuille de trading — {0}% ({1} blocs restants) portfolio.pending.step1.waitForConf=Attendre la confirmation de la blockchain portfolio.pending.step2_buyer.additionalConf=Les dépôts ont atteint 10 confirmations.\nPour plus de sécurité, nous recommandons d’attendre {0} confirmations avant d’envoyer le paiement.\nProcédez plus tôt à vos propres risques. portfolio.pending.step2_buyer.startPayment=Initier le paiement diff --git a/core/src/main/resources/i18n/displayStrings_it.properties b/core/src/main/resources/i18n/displayStrings_it.properties index 7504045341..fd786e3b8f 100644 --- a/core/src/main/resources/i18n/displayStrings_it.properties +++ b/core/src/main/resources/i18n/displayStrings_it.properties @@ -576,7 +576,8 @@ portfolio.closedTrades.deviation.help=Percentage price deviation from market portfolio.pending.invalidTx=There is an issue with a missing or invalid transaction.\n\nPlease do NOT send the traditional or crypto payment.\n\nOpen a support ticket to get assistance from a Mediator.\n\nError message: {0} -portfolio.pending.syncing=Sincronizzazione del portafoglio trade — {0}% ({1} blocchi rimanenti) +portfolio.pending.syncing=Sincronizzazione del portafoglio di trading — {0}% +portfolio.pending.syncing.blocksRemaining=Sincronizzazione del portafoglio trade — {0}% ({1} blocchi rimanenti) portfolio.pending.step1.waitForConf=Attendi la conferma della blockchain portfolio.pending.step2_buyer.additionalConf=I depositi hanno raggiunto 10 conferme.\nPer maggiore sicurezza, consigliamo di attendere {0} conferme prima di inviare il pagamento.\nProcedi in anticipo a tuo rischio. portfolio.pending.step2_buyer.startPayment=Inizia il pagamento diff --git a/core/src/main/resources/i18n/displayStrings_ja.properties b/core/src/main/resources/i18n/displayStrings_ja.properties index e564e642cc..c8287b25cf 100644 --- a/core/src/main/resources/i18n/displayStrings_ja.properties +++ b/core/src/main/resources/i18n/displayStrings_ja.properties @@ -577,7 +577,8 @@ portfolio.closedTrades.deviation.help=市場からの割合価格偏差 portfolio.pending.invalidTx=There is an issue with a missing or invalid transaction.\n\nPlease do NOT send the traditional or crypto payment.\n\nOpen a support ticket to get assistance from a Mediator.\n\nError message: {0} -portfolio.pending.syncing=取引ウォレットを同期中 — {0}%(残り {1} ブロック) +portfolio.pending.syncing=取引ウォレットを同期中 — {0}% +portfolio.pending.syncing.blocksRemaining=取引ウォレットを同期中 — {0}%(残り {1} ブロック) portfolio.pending.step1.waitForConf=ブロックチェーンの承認をお待ち下さい portfolio.pending.step2_buyer.additionalConf=入金は10承認に達しました。\n追加の安全のため、支払いを送信する前に{0}承認を待つことをお勧めします。\n早めに進める場合は自己責任となります。 portfolio.pending.step2_buyer.startPayment=支払い開始 diff --git a/core/src/main/resources/i18n/displayStrings_pt-br.properties b/core/src/main/resources/i18n/displayStrings_pt-br.properties index 7912f8331d..a1e40d87f2 100644 --- a/core/src/main/resources/i18n/displayStrings_pt-br.properties +++ b/core/src/main/resources/i18n/displayStrings_pt-br.properties @@ -579,7 +579,8 @@ portfolio.closedTrades.deviation.help=Percentage price deviation from market portfolio.pending.invalidTx=There is an issue with a missing or invalid transaction.\n\nPlease do NOT send the traditional or crypto payment.\n\nOpen a support ticket to get assistance from a Mediator.\n\nError message: {0} -portfolio.pending.syncing=Sincronizando a carteira de negociação — {0}% ({1} blocos restantes) +portfolio.pending.syncing=Sincronizando a carteira da negociação — {0}% +portfolio.pending.syncing.blocksRemaining=Sincronizando a carteira de negociação — {0}% ({1} blocos restantes) portfolio.pending.step1.waitForConf=Aguardar confirmação da blockchain portfolio.pending.step2_buyer.additionalConf=Depósitos alcançaram 10 confirmações.\nPara maior segurança, recomendamos aguardar {0} confirmações antes de enviar o pagamento.\nProssiga antecipadamente por sua própria conta e risco. portfolio.pending.step2_buyer.startPayment=Iniciar pagamento diff --git a/core/src/main/resources/i18n/displayStrings_pt.properties b/core/src/main/resources/i18n/displayStrings_pt.properties index 7515d3b80e..79ae6072b4 100644 --- a/core/src/main/resources/i18n/displayStrings_pt.properties +++ b/core/src/main/resources/i18n/displayStrings_pt.properties @@ -576,7 +576,8 @@ portfolio.closedTrades.deviation.help=Percentage price deviation from market portfolio.pending.invalidTx=There is an issue with a missing or invalid transaction.\n\nPlease do NOT send the traditional or crypto payment.\n\nOpen a support ticket to get assistance from a Mediator.\n\nError message: {0} -portfolio.pending.syncing=Sincronizando a carteira de negociação — {0}% ({1} blocos restantes) +portfolio.pending.syncing=Sincronizando a carteira da negociação — {0}% +portfolio.pending.syncing.blocksRemaining=Sincronizando a carteira de negociação — {0}% ({1} blocos restantes) portfolio.pending.step1.waitForConf=Esperando confirmação da blockchain portfolio.pending.step2_buyer.additionalConf=Os depósitos alcançaram 10 confirmações.\nPara maior segurança, recomendamos aguardar {0} confirmações antes de enviar o pagamento.\nProceda antecipadamente por sua própria conta e risco. portfolio.pending.step2_buyer.startPayment=Iniciar pagamento diff --git a/core/src/main/resources/i18n/displayStrings_ru.properties b/core/src/main/resources/i18n/displayStrings_ru.properties index 7e1c54b7e0..5c6e2a6fac 100644 --- a/core/src/main/resources/i18n/displayStrings_ru.properties +++ b/core/src/main/resources/i18n/displayStrings_ru.properties @@ -576,7 +576,8 @@ portfolio.closedTrades.deviation.help=Percentage price deviation from market portfolio.pending.invalidTx=There is an issue with a missing or invalid transaction.\n\nPlease do NOT send the traditional or crypto payment.\n\nOpen a support ticket to get assistance from a Mediator.\n\nError message: {0} -portfolio.pending.syncing=Синхронизация торгового кошелька — {0}% (осталось блоков: {1}) +portfolio.pending.syncing=Синхронизация торгового кошелька — {0}% +portfolio.pending.syncing.blocksRemaining=Синхронизация торгового кошелька — {0}% (осталось блоков: {1}) portfolio.pending.step1.waitForConf=Ожидание подтверждения в блокчейне portfolio.pending.step2_buyer.additionalConf=Депозиты достигли 10 подтверждений.\nДля дополнительной безопасности мы рекомендуем дождаться {0} подтверждений перед отправкой платежа.\nРанее действия осуществляются на ваш страх и риск. portfolio.pending.step2_buyer.startPayment=Сделать платеж diff --git a/core/src/main/resources/i18n/displayStrings_th.properties b/core/src/main/resources/i18n/displayStrings_th.properties index 5f0c96edfe..37baab8900 100644 --- a/core/src/main/resources/i18n/displayStrings_th.properties +++ b/core/src/main/resources/i18n/displayStrings_th.properties @@ -576,7 +576,8 @@ portfolio.closedTrades.deviation.help=Percentage price deviation from market portfolio.pending.invalidTx=There is an issue with a missing or invalid transaction.\n\nPlease do NOT send the traditional or crypto payment.\n\nOpen a support ticket to get assistance from a Mediator.\n\nError message: {0} -portfolio.pending.syncing=กำลังซิงค์กระเป๋าเงินสำหรับการซื้อขาย — {0}% (เหลืออีก {1} บล็อก) +portfolio.pending.syncing=กำลังซิงค์กระเป๋าเงินสำหรับการซื้อขาย — {0}% +portfolio.pending.syncing.blocksRemaining=กำลังซิงค์กระเป๋าเงินสำหรับการซื้อขาย — {0}% (เหลืออีก {1} บล็อก) portfolio.pending.step1.waitForConf=รอการยืนยันของบล็อกเชน portfolio.pending.step2_buyer.additionalConf=ยอดฝากถึง 10 การยืนยันแล้ว\nเพื่อความปลอดภัยเพิ่มเติม เราแนะนำให้รอ {0} การยืนยันก่อนทำการชำระเงิน\nดำเนินการล่วงหน้าตามความเสี่ยงของคุณเอง portfolio.pending.step2_buyer.startPayment=เริ่มการชำระเงิน diff --git a/core/src/main/resources/i18n/displayStrings_tr.properties b/core/src/main/resources/i18n/displayStrings_tr.properties index 7857e60ca7..c7cfdeb9cd 100644 --- a/core/src/main/resources/i18n/displayStrings_tr.properties +++ b/core/src/main/resources/i18n/displayStrings_tr.properties @@ -623,7 +623,8 @@ portfolio.pending.unconfirmedTooLong=İşlem {0} üzerindeki güvence işlemleri onaylanmış olarak gösterilmiyorlarsa, Haveno'yu yeniden başlatmayı deneyin.\n\n\ Sorun devam ederse, Haveno desteğiyle iletişime geçin [HYPERLINK:https://matrix.to/#/#haveno:monero.social]. -portfolio.pending.syncing=Ticaret cüzdanı senkronize ediliyor — %{0} ({1} blok kaldı) +portfolio.pending.syncing=Ticaret cüzdanı senkronize ediliyor — %{0} +portfolio.pending.syncing.blocksRemaining=Ticaret cüzdanı senkronize ediliyor — %{0} ({1} blok kaldı) portfolio.pending.step1.waitForConf=Blok zinciri onaylarını bekleyin portfolio.pending.step2_buyer.additionalConf=Mevduatlar 10 onayı ulaştı.\nEkstra güvenlik için, ödeme göndermeden önce {0} onayı beklemenizi öneririz.\nErken ilerlemek kendi riskinizdedir. portfolio.pending.step2_buyer.startPayment=Ödemeyi başlat diff --git a/core/src/main/resources/i18n/displayStrings_vi.properties b/core/src/main/resources/i18n/displayStrings_vi.properties index 901fbeff72..68c9e4921d 100644 --- a/core/src/main/resources/i18n/displayStrings_vi.properties +++ b/core/src/main/resources/i18n/displayStrings_vi.properties @@ -576,7 +576,8 @@ portfolio.closedTrades.deviation.help=Percentage price deviation from market portfolio.pending.invalidTx=There is an issue with a missing or invalid transaction.\n\nPlease do NOT send the traditional or crypto payment.\n\nOpen a support ticket to get assistance from a Mediator.\n\nError message: {0} -portfolio.pending.syncing=Đang đồng bộ ví giao dịch — {0}% (còn lại {1} khối) +portfolio.pending.syncing=Đang đồng bộ ví giao dịch — {0}% +portfolio.pending.syncing.blocksRemaining=Đang đồng bộ ví giao dịch — {0}% (còn lại {1} khối) portfolio.pending.step1.waitForConf=Đợi xác nhận blockchain portfolio.pending.step2_buyer.additionalConf=Tiền gửi đã đạt 10 xác nhận.\nĐể tăng cường bảo mật, chúng tôi khuyên bạn chờ {0} xác nhận trước khi gửi thanh toán.\nTiến hành sớm là rủi ro của bạn. portfolio.pending.step2_buyer.startPayment=Bắt đầu thanh toán diff --git a/core/src/main/resources/i18n/displayStrings_zh-hans.properties b/core/src/main/resources/i18n/displayStrings_zh-hans.properties index 4560546453..d74581ef58 100644 --- a/core/src/main/resources/i18n/displayStrings_zh-hans.properties +++ b/core/src/main/resources/i18n/displayStrings_zh-hans.properties @@ -577,7 +577,8 @@ portfolio.closedTrades.deviation.help=与市场价格偏差百分比 portfolio.pending.invalidTx=There is an issue with a missing or invalid transaction.\n\nPlease do NOT send the traditional or crypto payment.\n\nOpen a support ticket to get assistance from a Mediator.\n\nError message: {0} -portfolio.pending.syncing=正在同步交易钱包 — {0}%(剩余 {1} 个区块) +portfolio.pending.syncing=正在同步交易钱包 — {0}% +portfolio.pending.syncing.blocksRemaining=正在同步交易钱包 — {0}%(剩余 {1} 个区块) portfolio.pending.step1.waitForConf=等待区块链确认 portfolio.pending.step2_buyer.additionalConf=存款已达到 10 个确认。\n为了额外安全,我们建议在发送付款前等待 {0} 个确认。\n提前操作风险自负。 portfolio.pending.step2_buyer.startPayment=开始付款 diff --git a/core/src/main/resources/i18n/displayStrings_zh-hant.properties b/core/src/main/resources/i18n/displayStrings_zh-hant.properties index 33308fe47e..686a573d95 100644 --- a/core/src/main/resources/i18n/displayStrings_zh-hant.properties +++ b/core/src/main/resources/i18n/displayStrings_zh-hant.properties @@ -577,7 +577,8 @@ portfolio.closedTrades.deviation.help=Percentage price deviation from market portfolio.pending.invalidTx=There is an issue with a missing or invalid transaction.\n\nPlease do NOT send the traditional or crypto payment.\n\nOpen a support ticket to get assistance from a Mediator.\n\nError message: {0} -portfolio.pending.syncing=正在同步交易錢包 — {0}%(剩餘 {1} 個區塊) +portfolio.pending.syncing=正在同步交易錢包 — {0}% +portfolio.pending.syncing.blocksRemaining=正在同步交易錢包 — {0}%(剩餘 {1} 個區塊) portfolio.pending.step1.waitForConf=等待區塊鏈確認 portfolio.pending.step2_buyer.additionalConf=存款已達 10 次確認。\n為了額外安全,我們建議在發送付款前等待 {0} 次確認。\n提前操作風險自負。 portfolio.pending.step2_buyer.startPayment=開始付款 diff --git a/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java b/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java index dc02b2c332..7886dd66c7 100644 --- a/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java +++ b/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java @@ -47,6 +47,8 @@ import static haveno.desktop.util.FormBuilder.addCompactTopLabelTextField; import static haveno.desktop.util.FormBuilder.addMultilineLabel; import static haveno.desktop.util.FormBuilder.addTitledGroupBg; import static haveno.desktop.util.FormBuilder.addTopLabelTxIdTextField; + +import haveno.desktop.util.GUIUtil; import haveno.desktop.util.Layout; import haveno.network.p2p.BootstrapListener; import java.util.Optional; @@ -77,7 +79,7 @@ public abstract class TradeStepView extends AnchorPane { protected final Preferences preferences; protected final GridPane gridPane; - private Subscription tradePeriodStateSubscription, tradeStateSubscription, disputeStateSubscription, mediationResultStateSubscription, syncProgressSubscription; + private Subscription tradePeriodStateSubscription, tradeStateSubscription, disputeStateSubscription, mediationResultStateSubscription, syncUpdateSubscription; protected int gridRow = 0; private TextField timeLeftTextField; private ProgressBar timeLeftProgressBar; @@ -261,18 +263,30 @@ public abstract class TradeStepView extends AnchorPane { if (newValue) addTradeStateSubscription(); }); - syncProgressSubscription = EasyBind.subscribe(trade.downloadPercentageProperty(), newValue -> { - if (newValue != null) onSyncProgress((double) newValue); + syncUpdateSubscription = EasyBind.subscribe(trade.getSyncProgressListener().numUpdates(), newValue -> { + if (newValue != null) updateSyncProgress(); }); - UserThread.execute(() -> model.p2PService.removeP2PServiceListener(bootstrapListener)); } - protected void onSyncProgress(double percent) { + protected void updateSyncProgress() { + + // TODO: don't set sync status when 2 blocks behind or less after synced? + long blocksRemaining = trade.blocksRemainingProperty().get(); + // if (trade.wasWalletSynced() && blocksRemaining <= 2) { + // setSyncStatus(""); + // return; + // } + + // set status with percentage and blocks remaining if available + double percent = trade.downloadPercentageProperty().get(); if (percent < 0.0 || percent >= 1.0) setSyncStatus(""); else { - long blocksRemaining = HavenoUtils.xmrConnectionService.getTargetHeight() - trade.getHeight(); - setSyncStatus(Res.get("portfolio.pending.syncing", ((int) Math.round(percent * 100)), blocksRemaining)); + if (trade.blocksRemainingProperty().get() < 0) { + setSyncStatus(Res.get("portfolio.pending.syncing", GUIUtil.getRoundedClampedPercent(percent))); + } else { + setSyncStatus(Res.get("portfolio.pending.syncing.blocksRemaining", GUIUtil.getRoundedClampedPercent(percent), blocksRemaining)); + } } } @@ -316,8 +330,8 @@ public abstract class TradeStepView extends AnchorPane { if (mediationResultStateSubscription != null) mediationResultStateSubscription.unsubscribe(); - if (syncProgressSubscription != null) - syncProgressSubscription.unsubscribe(); + if (syncUpdateSubscription != null) + syncUpdateSubscription.unsubscribe(); if (tradePeriodStateSubscription != null) tradePeriodStateSubscription.unsubscribe(); diff --git a/desktop/src/main/java/haveno/desktop/util/GUIUtil.java b/desktop/src/main/java/haveno/desktop/util/GUIUtil.java index cb8111af33..f183f5b206 100644 --- a/desktop/src/main/java/haveno/desktop/util/GUIUtil.java +++ b/desktop/src/main/java/haveno/desktop/util/GUIUtil.java @@ -1401,4 +1401,10 @@ public class GUIUtil { return new Tuple2<>(qrCodePane, qrCodeImageView); } + + public static int getRoundedClampedPercent(double percent) { + int rounded = (int) Math.round(percent * 100); + if (rounded >= 100 && percent < 1) return 99; + return rounded; + } }