From 7435db03a824bdb0ebb05d1d676a39fa7cb7a17b Mon Sep 17 00:00:00 2001 From: fossephate <matt.cfosse@gmail.com> Date: Mon, 23 Sep 2024 16:18:38 -0700 Subject: [PATCH] silent payments eta fixes and updates --- cw_bitcoin/lib/electrum_wallet.dart | 8 +++- cw_bitcoin/lib/litecoin_wallet.dart | 6 +-- cw_core/lib/sync_status.dart | 58 ++++++++++++++++++++--------- cw_mweb/lib/cw_mweb.dart | 2 +- 4 files changed, 52 insertions(+), 22 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index c31a4d5cb..d726d1c05 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -398,7 +398,13 @@ abstract class ElectrumWalletBase nodeSupportsSilentPayments = false; } - syncStatus = message.syncStatus; + if (message.syncStatus is SyncingSyncStatus) { + var status = message.syncStatus as SyncingSyncStatus; + syncStatus = SyncingSyncStatus(status.blocksLeft, status.ptc); + } else { + syncStatus = message.syncStatus; + } + await walletInfo.updateRestoreHeight(message.height); } }); diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 26e286a66..04b500b43 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -943,12 +943,12 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { @override Future<void> close() async { - await super.close(); - await stopSync(); + _utxoStream?.cancel(); _stuckSyncTimer?.cancel(); _feeRatesTimer?.cancel(); _syncTimer?.cancel(); - _utxoStream?.cancel(); + await stopSync(); + await super.close(); } Future<void> setMwebEnabled(bool enabled) async { diff --git a/cw_core/lib/sync_status.dart b/cw_core/lib/sync_status.dart index c59bff820..fb9ec3002 100644 --- a/cw_core/lib/sync_status.dart +++ b/cw_core/lib/sync_status.dart @@ -34,30 +34,27 @@ class SyncingSyncStatus extends SyncStatus { final diff = track - (chainTip - syncHeight); final ptc = diff <= 0 ? 0.0 : diff / track; final left = chainTip - syncHeight; + updateEtaHistory(left + 1); // sum 1 because if at the chain tip, will say "0 blocks left" return SyncingSyncStatus(left + 1, ptc); } - void updateEtaHistory(int blocksLeft) { + static void updateEtaHistory(int blocksLeft) { blockHistory[DateTime.now()] = blocksLeft; - // keep only the last 10 entries - if (blockHistory.length > 10) { - var oldestKey = blockHistory.keys.reduce((a, b) => a.isBefore(b) ? a : b); - blockHistory.remove(oldestKey); + // keep only the last 25 entries + while (blockHistory.length > 25) { + blockHistory.remove(blockHistory.keys.first); } } static Map<DateTime, int> blockHistory = {}; - - DateTime? estimatedCompletionTime; - Duration? estimatedCompletionDuration; - + static Duration? lastEtaDuration; DateTime calculateEta() { double rate = _calculateBlockRate(); - if (rate < 0.01) { - return DateTime.now().add(const Duration(days: 99)); + if (rate == 0) { + return DateTime.now().add(const Duration(days: 2)); } int remainingBlocks = this.blocksLeft; double timeRemainingSeconds = remainingBlocks / rate; @@ -75,13 +72,40 @@ class SyncingSyncStatus extends SyncStatus { blockHistory.removeWhere( (key, value) => key.isBefore(DateTime.now().subtract(const Duration(minutes: 1)))); - if (blockHistory.length < 2) return null; + // don't show eta if we don't have enough data: + if (blockHistory.length < 3) { + return null; + } + Duration? duration = getEtaDuration(); + // just show the block count if it's really long: if (duration.inDays > 0) { return null; } + // show the blocks count if the eta is less than a minute or we only have a few blocks left: + if (duration.inMinutes < 1 || blocksLeft < 1000) { + return null; + } + + // if our new eta is more than a minute off from the last one, only update the by 1 minute so it doesn't jump all over the place + if (lastEtaDuration != null) { + bool isIncreasing = duration.inSeconds > lastEtaDuration!.inSeconds; + bool diffMoreThanOneMinute = (duration.inSeconds - lastEtaDuration!.inSeconds).abs() > 60; + bool diffMoreThanOneHour = (duration.inSeconds - lastEtaDuration!.inSeconds).abs() > 3600; + if (diffMoreThanOneHour) { + duration = Duration(minutes: lastEtaDuration!.inMinutes + (isIncreasing ? 1 : -1)); + } else if (diffMoreThanOneMinute) { + duration = Duration(seconds: lastEtaDuration!.inSeconds + (isIncreasing ? 1 : -1)); + } else { + // if the diff is less than a minute don't change it: + duration = lastEtaDuration!; + } + } + + lastEtaDuration = duration; + String twoDigits(int n) => n.toString().padLeft(2, '0'); final hours = twoDigits(duration.inHours); @@ -98,21 +122,21 @@ class SyncingSyncStatus extends SyncStatus { List<DateTime> timestamps = blockHistory.keys.toList(); List<int> blockCounts = blockHistory.values.toList(); - double totalSeconds = 0; + double totalTime = 0; int totalBlocksProcessed = 0; for (int i = 0; i < blockCounts.length - 1; i++) { int blocksProcessed = blockCounts[i] - blockCounts[i + 1]; Duration timeDifference = timestamps[i + 1].difference(timestamps[i]); - totalSeconds += timeDifference.inSeconds; + totalTime += timeDifference.inMicroseconds; totalBlocksProcessed += blocksProcessed; } - if (totalSeconds == 0 || totalBlocksProcessed == 0) { + if (totalTime == 0 || totalBlocksProcessed == 0) { return 0; } - - double blocksPerSecond = totalBlocksProcessed / totalSeconds; + + double blocksPerSecond = totalBlocksProcessed / (totalTime / 1000000); return blocksPerSecond; } } diff --git a/cw_mweb/lib/cw_mweb.dart b/cw_mweb/lib/cw_mweb.dart index 293210c2b..63ff1bf97 100644 --- a/cw_mweb/lib/cw_mweb.dart +++ b/cw_mweb/lib/cw_mweb.dart @@ -27,7 +27,7 @@ class CwMweb { await Future.delayed(const Duration(seconds: 5)); _clientChannel = ClientChannel('127.0.0.1', port: _port!, channelShutdownHandler: () { - print("Channel shutdown!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + print("Channel is shutting down!"); }, options: const ChannelOptions( credentials: ChannelCredentials.insecure(),