Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions cw_bitcoin/lib/electrum_wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2657,9 +2657,8 @@ abstract class ElectrumWalletBase

break;
case electrum.ConnectionStatus.disconnected:
if (syncStatus is! NotConnectedSyncStatus &&
syncStatus is! ConnectingSyncStatus &&
syncStatus is! SyncronizingSyncStatus) {
// Always show disconnected status when connection is lost, regardless of current sync state
if (syncStatus is! NotConnectedSyncStatus) {
syncStatus = NotConnectedSyncStatus();
}
break;
Expand Down
28 changes: 15 additions & 13 deletions cw_core/lib/sync_status.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class StartingScanSyncStatus extends SyncStatus {
class SyncingSyncStatus extends SyncStatus {
SyncingSyncStatus(this.blocksLeft, this.ptc) {
updateEtaHistory(blocksLeft);
_globalSyncStartTime ??= DateTime.now();
}

double ptc;
Expand All @@ -32,6 +33,19 @@ class SyncingSyncStatus extends SyncStatus {
@override
String toString() => '$blocksLeft';

/// Returns true if we should show blocks remaining instead of percentage
/// Shows blocks remaining for the first 15 seconds of syncing
bool shouldShowBlocksRemaining() {
if (_globalSyncStartTime == null) return true;
final elapsed = DateTime.now().difference(_globalSyncStartTime!);
return elapsed.inSeconds < 15;
}

/// Reset the global sync start time (call when sync completes or fails)
static void resetSyncStartTime() {
_globalSyncStartTime = null;
}

factory SyncingSyncStatus.fromHeightValues(int chainTip, int initialSyncHeight, int syncHeight) {
final track = chainTip - initialSyncHeight;
final diff = track - (chainTip - syncHeight);
Expand All @@ -45,21 +59,14 @@ class SyncingSyncStatus extends SyncStatus {

static void updateEtaHistory(int blocksLeft) {
blockHistory[DateTime.now()] = blocksLeft;

// keep only the last 30 entries (gives us better statistical accuracy)
while (blockHistory.length > 30) {
blockHistory.remove(blockHistory.keys.first);
}
}

static Map<DateTime, int> blockHistory = {};
static Duration? lastEtaDuration;
static const int _minDataPoints = 3;
static const int _maxDataAgeMinutes = 2;
static DateTime? _globalSyncStartTime;

String? getFormattedEtaWithPlaceholder() {
_cleanOldEntries();

// If we have enough data, show actual ETA
if (blockHistory.length >= _minDataPoints) {
final eta = getFormattedEta();
Expand All @@ -70,11 +77,6 @@ class SyncingSyncStatus extends SyncStatus {
return '--:--';
}

void _cleanOldEntries() {
final cutoffTime = DateTime.now().subtract(Duration(minutes: _maxDataAgeMinutes));
blockHistory.removeWhere((key, value) => key.isBefore(cutoffTime));
}

String? getFormattedEta() {
Duration? duration = getEtaDuration();

Expand Down
14 changes: 14 additions & 0 deletions lib/core/sync_status_title.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ import 'package:cw_core/sync_status.dart';

String syncStatusTitle(SyncStatus syncStatus, SyncStatusDisplayMode syncStatusDisplayMode) {
if (syncStatus is SyncingSyncStatus) {
// Show blocks remaining for the first 3 seconds, then switch to percentage
if (syncStatus.shouldShowBlocksRemaining()) {
if (syncStatus.blocksLeft == 1) {
return S.current.block_remaining;
}
return S.current.Blocks_remaining('${syncStatus.blocksLeft}');
}

// After 3 seconds, show percentage-based display
// Don't show ETA for very few blocks (less than 100) to avoid inconsistency
if (syncStatus.blocksLeft < 100) {
return S.current.Blocks_remaining('${syncStatus.blocksLeft}');
}

if (syncStatus.blocksLeft == 1) {
return S.current.block_remaining;
}
Expand Down
5 changes: 1 addition & 4 deletions lib/reactions/check_connection.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import 'dart:async';

import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/utils/tor.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/sync_status.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';

Timer? _checkConnectionTimer;

Expand All @@ -29,7 +26,7 @@ void startCheckConnectionReaction(WalletBase wallet, SettingsStore settingsStore
try {
final connectivityResult = await (Connectivity().checkConnectivity());

if (connectivityResult == ConnectivityResult.none) {
if (connectivityResult.contains(ConnectivityResult.none)) {
wallet.syncStatus = FailedSyncStatus();
return;
}
Expand Down
2 changes: 2 additions & 0 deletions lib/reactions/on_current_wallet_change.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:cake_wallet/solana/solana.dart';
import 'package:cake_wallet/tron/tron.dart';
import 'package:cake_wallet/utils/tor.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/sync_status.dart';
import 'package:cw_core/transaction_history.dart';
import 'package:cw_core/balance.dart';
import 'package:cw_core/transaction_info.dart';
Expand Down Expand Up @@ -92,6 +93,7 @@ void startCurrentWalletChangeReaction(
}

await wallet.connectToNode(node: node);
SyncingSyncStatus.blockHistory.clear();
if (wallet.type == WalletType.nano || wallet.type == WalletType.banano) {
final powNode = settingsStore.getCurrentPowNode(wallet.type);
await wallet.connectToPowNode(node: powNode);
Expand Down
12 changes: 11 additions & 1 deletion lib/reactions/on_wallet_sync_status_change.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,23 @@ void startWalletSyncStatusChangeReaction(
_onWalletSyncStatusChangeReaction = reaction((_) => wallet.syncStatus, (SyncStatus status) async {
try {
if (status is ConnectedSyncStatus) {
SyncingSyncStatus.resetSyncStartTime();
await wallet.startSync();
}

if (status is SyncingSyncStatus || status is ProcessingSyncStatus) {
await WakelockPlus.enable();
}
if (status is SyncedSyncStatus || status is FailedSyncStatus) {

if (status is SyncedSyncStatus) {
await WakelockPlus.disable();
SyncingSyncStatus.resetSyncStartTime();
SyncingSyncStatus.blockHistory.clear();
}

if (status is FailedSyncStatus) {
await WakelockPlus.disable();
SyncingSyncStatus.resetSyncStartTime();
}

if (status is SyncedSyncStatus &&
Expand Down
Loading