update sync progress based on current target height

This commit is contained in:
woodser 2025-12-21 20:53:17 -05:00
parent 2d207be0c6
commit da8261c613
No known key found for this signature in database
GPG key ID: 55A10DD48ADEE5EF
23 changed files with 118 additions and 53 deletions

View file

@ -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

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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() {

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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=آغاز پرداخت

View file

@ -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 dattendre {0} confirmations avant denvoyer le paiement.\nProcédez plus tôt à vos propres risques.
portfolio.pending.step2_buyer.startPayment=Initier le paiement

View file

@ -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

View file

@ -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=支払い開始

View file

@ -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

View file

@ -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

View file

@ -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=Сделать платеж

View file

@ -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=เริ่มการชำระเงิน

View file

@ -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

View file

@ -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

View file

@ -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=开始付款

View file

@ -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=開始付款

View file

@ -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();

View file

@ -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;
}
}