mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-28 20:39:51 +00:00
Merge 26267ad200
into 1a5601f755
This commit is contained in:
commit
e796bac9fd
2 changed files with 121 additions and 6 deletions
|
@ -1,6 +1,10 @@
|
||||||
abstract class SyncStatus {
|
abstract class SyncStatus {
|
||||||
const SyncStatus();
|
const SyncStatus();
|
||||||
double progress();
|
double progress();
|
||||||
|
|
||||||
|
String formattedProgress() {
|
||||||
|
return "${(progress() * 100).toStringAsFixed(2)}%";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StartingScanSyncStatus extends SyncStatus {
|
class StartingScanSyncStatus extends SyncStatus {
|
||||||
|
@ -12,10 +16,12 @@ class StartingScanSyncStatus extends SyncStatus {
|
||||||
}
|
}
|
||||||
|
|
||||||
class SyncingSyncStatus extends SyncStatus {
|
class SyncingSyncStatus extends SyncStatus {
|
||||||
SyncingSyncStatus(this.blocksLeft, this.ptc);
|
SyncingSyncStatus(this.blocksLeft, this.ptc) {
|
||||||
|
updateEtaHistory(blocksLeft);
|
||||||
|
}
|
||||||
|
|
||||||
final double ptc;
|
double ptc;
|
||||||
final int blocksLeft;
|
int blocksLeft;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
double progress() => ptc;
|
double progress() => ptc;
|
||||||
|
@ -28,10 +34,111 @@ class SyncingSyncStatus extends SyncStatus {
|
||||||
final diff = track - (chainTip - syncHeight);
|
final diff = track - (chainTip - syncHeight);
|
||||||
final ptc = diff <= 0 ? 0.0 : diff / track;
|
final ptc = diff <= 0 ? 0.0 : diff / track;
|
||||||
final left = chainTip - syncHeight;
|
final left = chainTip - syncHeight;
|
||||||
|
updateEtaHistory(left + 1);
|
||||||
|
|
||||||
// sum 1 because if at the chain tip, will say "0 blocks left"
|
// sum 1 because if at the chain tip, will say "0 blocks left"
|
||||||
return SyncingSyncStatus(left + 1, ptc);
|
return SyncingSyncStatus(left + 1, ptc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void updateEtaHistory(int blocksLeft) {
|
||||||
|
blockHistory[DateTime.now()] = blocksLeft;
|
||||||
|
// keep only the last 25 entries
|
||||||
|
while (blockHistory.length > 25) {
|
||||||
|
blockHistory.remove(blockHistory.keys.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<DateTime, int> blockHistory = {};
|
||||||
|
static Duration? lastEtaDuration;
|
||||||
|
|
||||||
|
DateTime calculateEta() {
|
||||||
|
double rate = _calculateBlockRate();
|
||||||
|
if (rate == 0) {
|
||||||
|
return DateTime.now().add(const Duration(days: 2));
|
||||||
|
}
|
||||||
|
int remainingBlocks = this.blocksLeft;
|
||||||
|
double timeRemainingSeconds = remainingBlocks / rate;
|
||||||
|
return DateTime.now().add(Duration(seconds: timeRemainingSeconds.round()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Duration getEtaDuration() {
|
||||||
|
DateTime now = DateTime.now();
|
||||||
|
DateTime? completionTime = calculateEta();
|
||||||
|
return completionTime.difference(now);
|
||||||
|
}
|
||||||
|
|
||||||
|
String? getFormattedEta() {
|
||||||
|
// throw out any entries that are more than a minute old:
|
||||||
|
blockHistory.removeWhere(
|
||||||
|
(key, value) => key.isBefore(DateTime.now().subtract(const Duration(minutes: 1))));
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
final minutes = twoDigits(duration.inMinutes.remainder(60));
|
||||||
|
final seconds = twoDigits(duration.inSeconds.remainder(60));
|
||||||
|
if (hours == '00') {
|
||||||
|
return '${minutes}m${seconds}s';
|
||||||
|
}
|
||||||
|
return '${hours}h${minutes}m${seconds}s';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the rate of block processing (blocks per second)
|
||||||
|
double _calculateBlockRate() {
|
||||||
|
List<DateTime> timestamps = blockHistory.keys.toList();
|
||||||
|
List<int> blockCounts = blockHistory.values.toList();
|
||||||
|
|
||||||
|
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]);
|
||||||
|
totalTime += timeDifference.inMicroseconds;
|
||||||
|
totalBlocksProcessed += blocksProcessed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalTime == 0 || totalBlocksProcessed == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double blocksPerSecond = totalBlocksProcessed / (totalTime / 1000000);
|
||||||
|
return blocksPerSecond;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProcessingSyncStatus extends SyncStatus {
|
class ProcessingSyncStatus extends SyncStatus {
|
||||||
|
|
|
@ -3,9 +3,17 @@ import 'package:cw_core/sync_status.dart';
|
||||||
|
|
||||||
String syncStatusTitle(SyncStatus syncStatus) {
|
String syncStatusTitle(SyncStatus syncStatus) {
|
||||||
if (syncStatus is SyncingSyncStatus) {
|
if (syncStatus is SyncingSyncStatus) {
|
||||||
return syncStatus.blocksLeft == 1
|
if (syncStatus.blocksLeft == 1) {
|
||||||
? S.current.block_remaining
|
return S.current.block_remaining;
|
||||||
: S.current.Blocks_remaining('${syncStatus.blocksLeft}');
|
}
|
||||||
|
|
||||||
|
String eta = syncStatus.getFormattedEta() ?? '';
|
||||||
|
|
||||||
|
if (eta.isEmpty) {
|
||||||
|
return S.current.Blocks_remaining('${syncStatus.blocksLeft}');
|
||||||
|
} else {
|
||||||
|
return "${syncStatus.formattedProgress()} - $eta";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (syncStatus is SyncedTipSyncStatus) {
|
if (syncStatus is SyncedTipSyncStatus) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue