From 17de9f16b87425885c39b52f392abe45ba9ff3a2 Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 23 Sep 2024 19:17:07 +0300 Subject: [PATCH 01/14] fix polygon name (#1697) --- lib/exchange/provider/stealth_ex_exchange_provider.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/exchange/provider/stealth_ex_exchange_provider.dart b/lib/exchange/provider/stealth_ex_exchange_provider.dart index 601735595..8fa72aeaa 100644 --- a/lib/exchange/provider/stealth_ex_exchange_provider.dart +++ b/lib/exchange/provider/stealth_ex_exchange_provider.dart @@ -284,6 +284,7 @@ class StealthExExchangeProvider extends ExchangeProvider { String _getName(CryptoCurrency currency) { if (currency == CryptoCurrency.usdcEPoly) return 'usdce'; + if (currency == CryptoCurrency.maticpoly) return 'matic'; return currency.title.toLowerCase(); } From bab45a9e36b2e017f9649fc98a7f8d7fe278c764 Mon Sep 17 00:00:00 2001 From: cyan Date: Mon, 23 Sep 2024 18:18:21 +0200 Subject: [PATCH 02/14] add missing error messages (#1696) --- cw_bitcoin/lib/exceptions.dart | 15 +++++++++++++++ cw_core/lib/exceptions.dart | 5 +++++ .../api/exceptions/setup_wallet_exception.dart | 5 +++++ .../api/exceptions/setup_wallet_exception.dart | 3 +++ .../wallet_restore_from_keys_exception.dart | 3 +++ .../wallet_restore_from_seed_exception.dart | 3 +++ .../api/exceptions/setup_wallet_exception.dart | 3 +++ .../wallet_restore_from_keys_exception.dart | 2 ++ 8 files changed, 39 insertions(+) diff --git a/cw_bitcoin/lib/exceptions.dart b/cw_bitcoin/lib/exceptions.dart index 575a61b0b..f7c593135 100644 --- a/cw_bitcoin/lib/exceptions.dart +++ b/cw_bitcoin/lib/exceptions.dart @@ -3,6 +3,11 @@ import 'package:cw_core/exceptions.dart'; class BitcoinTransactionWrongBalanceException extends TransactionWrongBalanceException { BitcoinTransactionWrongBalanceException({super.amount}) : super(CryptoCurrency.btc); + + @override + String toString() { + return "BitcoinTransactionWrongBalanceException: $amount, $currency"; + } } class BitcoinTransactionNoInputsException extends TransactionNoInputsException {} @@ -13,10 +18,20 @@ class BitcoinTransactionNoDustException extends TransactionNoDustException {} class BitcoinTransactionNoDustOnChangeException extends TransactionNoDustOnChangeException { BitcoinTransactionNoDustOnChangeException(super.max, super.min); + + @override + String toString() { + return "BitcoinTransactionNoDustOnChangeException: max: $max, min: $min"; + } } class BitcoinTransactionCommitFailed extends TransactionCommitFailed { BitcoinTransactionCommitFailed({super.errorMessage}); + + @override + String toString() { + return errorMessage??"unknown error"; + } } class BitcoinTransactionCommitFailedDustChange extends TransactionCommitFailedDustChange {} diff --git a/cw_core/lib/exceptions.dart b/cw_core/lib/exceptions.dart index c13861698..80bdd2886 100644 --- a/cw_core/lib/exceptions.dart +++ b/cw_core/lib/exceptions.dart @@ -24,6 +24,11 @@ class TransactionCommitFailed implements Exception { final String? errorMessage; TransactionCommitFailed({this.errorMessage}); + + @override + String toString() { + return errorMessage??"unknown error"; + } } class TransactionCommitFailedDustChange implements Exception {} diff --git a/cw_haven/lib/api/exceptions/setup_wallet_exception.dart b/cw_haven/lib/api/exceptions/setup_wallet_exception.dart index b6e0c1f18..9d985665b 100644 --- a/cw_haven/lib/api/exceptions/setup_wallet_exception.dart +++ b/cw_haven/lib/api/exceptions/setup_wallet_exception.dart @@ -2,4 +2,9 @@ class SetupWalletException implements Exception { SetupWalletException({required this.message}); final String message; + + @override + String toString() { + return message; + } } \ No newline at end of file diff --git a/cw_monero/lib/api/exceptions/setup_wallet_exception.dart b/cw_monero/lib/api/exceptions/setup_wallet_exception.dart index b6e0c1f18..c0d25c62f 100644 --- a/cw_monero/lib/api/exceptions/setup_wallet_exception.dart +++ b/cw_monero/lib/api/exceptions/setup_wallet_exception.dart @@ -2,4 +2,7 @@ class SetupWalletException implements Exception { SetupWalletException({required this.message}); final String message; + + @override + String toString() => message; } \ No newline at end of file diff --git a/cw_monero/lib/api/exceptions/wallet_restore_from_keys_exception.dart b/cw_monero/lib/api/exceptions/wallet_restore_from_keys_exception.dart index c6b6c6ef7..6c461ee4c 100644 --- a/cw_monero/lib/api/exceptions/wallet_restore_from_keys_exception.dart +++ b/cw_monero/lib/api/exceptions/wallet_restore_from_keys_exception.dart @@ -2,4 +2,7 @@ class WalletRestoreFromKeysException implements Exception { WalletRestoreFromKeysException({required this.message}); final String message; + + @override + String toString() => message; } \ No newline at end of file diff --git a/cw_monero/lib/api/exceptions/wallet_restore_from_seed_exception.dart b/cw_monero/lib/api/exceptions/wallet_restore_from_seed_exception.dart index 004cd7958..904a7e767 100644 --- a/cw_monero/lib/api/exceptions/wallet_restore_from_seed_exception.dart +++ b/cw_monero/lib/api/exceptions/wallet_restore_from_seed_exception.dart @@ -2,4 +2,7 @@ class WalletRestoreFromSeedException implements Exception { WalletRestoreFromSeedException({required this.message}); final String message; + + @override + String toString() => message; } \ No newline at end of file diff --git a/cw_wownero/lib/api/exceptions/setup_wallet_exception.dart b/cw_wownero/lib/api/exceptions/setup_wallet_exception.dart index b6e0c1f18..c0d25c62f 100644 --- a/cw_wownero/lib/api/exceptions/setup_wallet_exception.dart +++ b/cw_wownero/lib/api/exceptions/setup_wallet_exception.dart @@ -2,4 +2,7 @@ class SetupWalletException implements Exception { SetupWalletException({required this.message}); final String message; + + @override + String toString() => message; } \ No newline at end of file diff --git a/cw_wownero/lib/api/exceptions/wallet_restore_from_keys_exception.dart b/cw_wownero/lib/api/exceptions/wallet_restore_from_keys_exception.dart index c6b6c6ef7..ad576faa2 100644 --- a/cw_wownero/lib/api/exceptions/wallet_restore_from_keys_exception.dart +++ b/cw_wownero/lib/api/exceptions/wallet_restore_from_keys_exception.dart @@ -2,4 +2,6 @@ class WalletRestoreFromKeysException implements Exception { WalletRestoreFromKeysException({required this.message}); final String message; + + String toString() => message; } \ No newline at end of file From 094b5ec82e2ca748788f4897794b685626e35872 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Mon, 23 Sep 2024 20:13:40 +0300 Subject: [PATCH 03/14] Revert "fix polygon name (#1697)" (#1699) This reverts commit 17de9f16b87425885c39b52f392abe45ba9ff3a2. --- lib/exchange/provider/stealth_ex_exchange_provider.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/exchange/provider/stealth_ex_exchange_provider.dart b/lib/exchange/provider/stealth_ex_exchange_provider.dart index 8fa72aeaa..601735595 100644 --- a/lib/exchange/provider/stealth_ex_exchange_provider.dart +++ b/lib/exchange/provider/stealth_ex_exchange_provider.dart @@ -284,7 +284,6 @@ class StealthExExchangeProvider extends ExchangeProvider { String _getName(CryptoCurrency currency) { if (currency == CryptoCurrency.usdcEPoly) return 'usdce'; - if (currency == CryptoCurrency.maticpoly) return 'matic'; return currency.title.toLowerCase(); } From e48cd0df413b49603fd68da59184930eedb1034b Mon Sep 17 00:00:00 2001 From: fossephate Date: Mon, 23 Sep 2024 14:26:56 -0700 Subject: [PATCH 04/14] fix mweb crash on non-fully deleted mweb cache, sync status ETA, other connection fixes --- cw_bitcoin/lib/litecoin_wallet.dart | 25 +++--- cw_bitcoin/lib/litecoin_wallet_service.dart | 18 +++- cw_core/lib/sync_status.dart | 89 ++++++++++++++++++- lib/core/sync_status_title.dart | 15 +++- .../dashboard/dashboard_view_model.dart | 1 + 5 files changed, 126 insertions(+), 22 deletions(-) diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 533fb346b..405c1bc89 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -97,6 +97,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { late final Bip32Slip10Secp256k1 mwebHd; late final Box mwebUtxosBox; Timer? _syncTimer; + Timer? _stuckSyncTimer; Timer? _feeRatesTimer; StreamSubscription? _utxoStream; late RpcClient _stub; @@ -314,26 +315,27 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { } await transactionHistory.save(); } + return; } }); // setup a watch dog to restart the sync process if it gets stuck: List lastFewProgresses = []; - Timer.periodic(const Duration(seconds: 10), (timer) async { + _stuckSyncTimer?.cancel(); + _stuckSyncTimer = Timer.periodic(const Duration(seconds: 10), (timer) async { if (syncStatus is! SyncingSyncStatus) return; - if (syncStatus.progress() > 0.98) return; + if (syncStatus.progress() > 0.98) return; // don't check if we're close to synced lastFewProgresses.add(syncStatus.progress()); - if (lastFewProgresses.length < 4) return; - // limit list size to 4: - while (lastFewProgresses.length > 4) { + if (lastFewProgresses.length < 10) return; + // limit list size to 10: + while (lastFewProgresses.length > 10) { lastFewProgresses.removeAt(0); } - // if the progress is the same over the last 40 seconds, restart the sync: + // if the progress is the same over the last 100 seconds, restart the sync: if (lastFewProgresses.every((p) => p == lastFewProgresses.first)) { print("mweb syncing is stuck, restarting..."); + syncStatus = LostConnectionSyncStatus(); await stopSync(); - startSync(); - timer.cancel(); } }); } @@ -870,10 +872,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { final utxo = unspentCoins .firstWhere((utxo) => utxo.hash == txInput.txId && utxo.vout == txInput.txIndex); - if (txInput.sequence.isEmpty) { - isHogEx = false; - } - // TODO: detect actual hog-ex inputs // print(txInput.sequence); // print(txInput.txIndex); @@ -949,6 +947,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { @override Future close() async { await super.close(); + await stopSync(); + _stuckSyncTimer?.cancel(); + _feeRatesTimer?.cancel(); _syncTimer?.cancel(); _utxoStream?.cancel(); } diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index 67a503de7..c659dd658 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -21,7 +21,8 @@ class LitecoinWalletService extends WalletService< BitcoinRestoreWalletFromSeedCredentials, BitcoinRestoreWalletFromWIFCredentials, BitcoinNewWalletCredentials> { - LitecoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.alwaysScan, this.isDirect); + LitecoinWalletService( + this.walletInfoSource, this.unspentCoinsInfoSource, this.alwaysScan, this.isDirect); final Box walletInfoSource; final Box unspentCoinsInfoSource; @@ -66,6 +67,7 @@ class LitecoinWalletService extends WalletService< @override Future openWallet(String name, String password) async { + final walletInfo = walletInfoSource.values .firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!; @@ -103,13 +105,21 @@ class LitecoinWalletService extends WalletService< .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; await walletInfoSource.delete(walletInfo.key); - // if there are no more litecoin wallets left, delete the neutrino db: + // if there are no more litecoin wallets left, cleanup the neutrino db and other files created by mwebd: if (walletInfoSource.values.where((info) => info.type == WalletType.litecoin).isEmpty) { - final appDir = await getApplicationSupportDirectory(); - File neturinoDb = File('${appDir.path}/neutrino.db'); + final appDirPath = (await getApplicationSupportDirectory()).path; + File neturinoDb = File('$appDirPath/neutrino.db'); + File blockHeaders = File('$appDirPath/block_headers.bin'); + File regFilterHeaders = File('$appDirPath/reg_filter_headers.bin'); if (neturinoDb.existsSync()) { neturinoDb.deleteSync(); } + if (blockHeaders.existsSync()) { + blockHeaders.deleteSync(); + } + if (regFilterHeaders.existsSync()) { + regFilterHeaders.deleteSync(); + } } } diff --git a/cw_core/lib/sync_status.dart b/cw_core/lib/sync_status.dart index 788309d8c..81c4a8564 100644 --- a/cw_core/lib/sync_status.dart +++ b/cw_core/lib/sync_status.dart @@ -1,6 +1,10 @@ abstract class SyncStatus { const SyncStatus(); double progress(); + + String formattedProgress() { + return "${(progress() * 100).toStringAsFixed(2)}%"; + } } class StartingScanSyncStatus extends SyncStatus { @@ -12,10 +16,12 @@ class StartingScanSyncStatus extends SyncStatus { } class SyncingSyncStatus extends SyncStatus { - SyncingSyncStatus(this.blocksLeft, this.ptc); + SyncingSyncStatus(this.blocksLeft, this.ptc) { + updateEtaHistory(blocksLeft); + } - final double ptc; - final int blocksLeft; + double ptc; + int blocksLeft; @override double progress() => ptc; @@ -32,6 +38,83 @@ class SyncingSyncStatus extends SyncStatus { // sum 1 because if at the chain tip, will say "0 blocks left" return SyncingSyncStatus(left + 1, ptc); } + + void updateEtaHistory(int blocksLeft) { + blockHistory[DateTime.now()] = blocksLeft; + + // Keep only the last 5 entries to limit memory usage + if (blockHistory.length > 5) { + var oldestKey = blockHistory.keys.reduce((a, b) => a.isBefore(b) ? a : b); + blockHistory.remove(oldestKey); + } + } + + static Map blockHistory = {}; + + DateTime? estimatedCompletionTime; + Duration? estimatedCompletionDuration; + + 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)))); + + if (blockHistory.length < 2) return null; + Duration? duration = getEtaDuration(); + + if (duration.inDays > 0) { + return null; + } + + 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 calculateRate() { + List timestamps = blockHistory.keys.toList(); + List blockCounts = blockHistory.values.toList(); + + double totalTimeMinutes = 0; + int totalBlocksProcessed = 0; + + for (int i = 0; i < blockCounts.length - 1; i++) { + int blocksProcessed = blockCounts[i + 1] - blockCounts[i]; + Duration timeDifference = timestamps[i].difference(timestamps[i + 1]); + totalTimeMinutes += timeDifference.inSeconds; + totalBlocksProcessed += blocksProcessed; + } + + if (totalTimeMinutes == 0 || totalBlocksProcessed == 0) { + return 0; + } + + return totalBlocksProcessed / totalTimeMinutes; // Blocks per second + } + + // Calculate the ETA + DateTime calculateETA() { + double rate = calculateRate(); + if (rate < 0.01) { + return DateTime.now().add(const Duration(days: 1)); + } + int remainingBlocks = this.blocksLeft; + double timeRemainingSeconds = remainingBlocks / rate; + return DateTime.now().add(Duration(seconds: timeRemainingSeconds.round())); + } } class SyncedSyncStatus extends SyncStatus { diff --git a/lib/core/sync_status_title.dart b/lib/core/sync_status_title.dart index 4582f7b1f..53240875a 100644 --- a/lib/core/sync_status_title.dart +++ b/lib/core/sync_status_title.dart @@ -3,9 +3,18 @@ import 'package:cw_core/sync_status.dart'; String syncStatusTitle(SyncStatus syncStatus) { if (syncStatus is SyncingSyncStatus) { - return syncStatus.blocksLeft == 1 - ? S.current.block_remaining - : S.current.Blocks_remaining('${syncStatus.blocksLeft}'); + + if (syncStatus.blocksLeft == 1) { + return S.current.block_remaining; + } + + String eta = syncStatus.getFormattedEta() ?? ''; + + if (eta.isEmpty) { + return S.current.Blocks_remaining('${syncStatus.blocksLeft}'); + } else { + return "${syncStatus.formattedProgress()} - $eta"; + } } if (syncStatus is SyncedTipSyncStatus) { diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index b7a9bbbbd..21a167e2a 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -258,6 +258,7 @@ abstract class DashboardViewModelBase with Store { if (hasMweb) { mwebScanningActive = bitcoin!.getMwebEnabled(wallet); + settingsStore.mwebEnabled = mwebScanningActive; reaction((_) => settingsStore.mwebAlwaysScan, (bool alwaysScan) { if (alwaysScan) { mwebScanningActive = true; From dbc2fb3fb163095b611050cc2da65fcff31572f7 Mon Sep 17 00:00:00 2001 From: fossephate Date: Mon, 23 Sep 2024 14:29:13 -0700 Subject: [PATCH 05/14] [skip ci] minor code cleanup --- cw_bitcoin/lib/litecoin_wallet.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 405c1bc89..1ca5d928e 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -697,7 +697,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { unconfirmedMweb += utxo.value.toInt(); } }); - if (/*confirmedMweb > 0 &&*/ unconfirmedMweb > 0) { + if (unconfirmedMweb > 0) { unconfirmedMweb = -1 * (confirmedMweb - unconfirmedMweb); } } catch (_) {} From 371fb8ce86e78bd52424e43ed72b324df91a128c Mon Sep 17 00:00:00 2001 From: fossephate Date: Mon, 23 Sep 2024 14:29:33 -0700 Subject: [PATCH 06/14] [skip ci] minor code cleanup --- cw_bitcoin/lib/litecoin_wallet.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 1ca5d928e..26e286a66 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -873,9 +873,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { .firstWhere((utxo) => utxo.hash == txInput.txId && utxo.vout == txInput.txIndex); // TODO: detect actual hog-ex inputs - // print(txInput.sequence); - // print(txInput.txIndex); - // print(utxo.value); if (!isHogEx) { return; From a226a338ff6c93d93b7f8c3f420fa93ee84fcbd6 Mon Sep 17 00:00:00 2001 From: fossephate Date: Mon, 23 Sep 2024 14:41:19 -0700 Subject: [PATCH 07/14] additional cleanup --- cw_core/lib/sync_status.dart | 46 ++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/cw_core/lib/sync_status.dart b/cw_core/lib/sync_status.dart index 81c4a8564..c59bff820 100644 --- a/cw_core/lib/sync_status.dart +++ b/cw_core/lib/sync_status.dart @@ -41,9 +41,8 @@ class SyncingSyncStatus extends SyncStatus { void updateEtaHistory(int blocksLeft) { blockHistory[DateTime.now()] = blocksLeft; - - // Keep only the last 5 entries to limit memory usage - if (blockHistory.length > 5) { + // 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); } @@ -54,9 +53,20 @@ class SyncingSyncStatus extends SyncStatus { DateTime? estimatedCompletionTime; Duration? estimatedCompletionDuration; + + DateTime calculateEta() { + double rate = _calculateBlockRate(); + if (rate < 0.01) { + return DateTime.now().add(const Duration(days: 99)); + } + 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(); + DateTime? completionTime = calculateEta(); return completionTime.difference(now); } @@ -84,36 +94,26 @@ class SyncingSyncStatus extends SyncStatus { } // Calculate the rate of block processing (blocks per second) - double calculateRate() { + double _calculateBlockRate() { List timestamps = blockHistory.keys.toList(); List blockCounts = blockHistory.values.toList(); - double totalTimeMinutes = 0; + double totalSeconds = 0; int totalBlocksProcessed = 0; for (int i = 0; i < blockCounts.length - 1; i++) { - int blocksProcessed = blockCounts[i + 1] - blockCounts[i]; - Duration timeDifference = timestamps[i].difference(timestamps[i + 1]); - totalTimeMinutes += timeDifference.inSeconds; + int blocksProcessed = blockCounts[i] - blockCounts[i + 1]; + Duration timeDifference = timestamps[i + 1].difference(timestamps[i]); + totalSeconds += timeDifference.inSeconds; totalBlocksProcessed += blocksProcessed; } - if (totalTimeMinutes == 0 || totalBlocksProcessed == 0) { + if (totalSeconds == 0 || totalBlocksProcessed == 0) { return 0; } - - return totalBlocksProcessed / totalTimeMinutes; // Blocks per second - } - - // Calculate the ETA - DateTime calculateETA() { - double rate = calculateRate(); - if (rate < 0.01) { - return DateTime.now().add(const Duration(days: 1)); - } - int remainingBlocks = this.blocksLeft; - double timeRemainingSeconds = remainingBlocks / rate; - return DateTime.now().add(Duration(seconds: timeRemainingSeconds.round())); + + double blocksPerSecond = totalBlocksProcessed / totalSeconds; + return blocksPerSecond; } } From 7435db03a824bdb0ebb05d1d676a39fa7cb7a17b Mon Sep 17 00:00:00 2001 From: fossephate Date: Mon, 23 Sep 2024 16:18:38 -0700 Subject: [PATCH 08/14] 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 close() async { - await super.close(); - await stopSync(); + _utxoStream?.cancel(); _stuckSyncTimer?.cancel(); _feeRatesTimer?.cancel(); _syncTimer?.cancel(); - _utxoStream?.cancel(); + await stopSync(); + await super.close(); } Future 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 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 timestamps = blockHistory.keys.toList(); List 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(), From cb74505f5965d38cc162a1ad820e199182bb89ff Mon Sep 17 00:00:00 2001 From: fossephate Date: Mon, 23 Sep 2024 17:03:58 -0700 Subject: [PATCH 09/14] revert sync eta changes into separate pr --- cw_core/lib/sync_status.dart | 115 ++--------------------------------- 1 file changed, 4 insertions(+), 111 deletions(-) diff --git a/cw_core/lib/sync_status.dart b/cw_core/lib/sync_status.dart index fb9ec3002..627b513b2 100644 --- a/cw_core/lib/sync_status.dart +++ b/cw_core/lib/sync_status.dart @@ -1,10 +1,6 @@ abstract class SyncStatus { const SyncStatus(); double progress(); - - String formattedProgress() { - return "${(progress() * 100).toStringAsFixed(2)}%"; - } } class StartingScanSyncStatus extends SyncStatus { @@ -16,12 +12,10 @@ class StartingScanSyncStatus extends SyncStatus { } class SyncingSyncStatus extends SyncStatus { - SyncingSyncStatus(this.blocksLeft, this.ptc) { - updateEtaHistory(blocksLeft); - } + SyncingSyncStatus(this.blocksLeft, this.ptc); - double ptc; - int blocksLeft; + final double ptc; + final int blocksLeft; @override double progress() => ptc; @@ -34,111 +28,10 @@ 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); } - - 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 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 timestamps = blockHistory.keys.toList(); - List 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 SyncedSyncStatus extends SyncStatus { @@ -196,4 +89,4 @@ class TimedOutSyncStatus extends NotConnectedSyncStatus { class LostConnectionSyncStatus extends NotConnectedSyncStatus { @override String toString() => 'Reconnecting'; -} +} \ No newline at end of file From ea1d4cbb41d39ed82ed1a00c630a736b3f4d4dff Mon Sep 17 00:00:00 2001 From: fossephate Date: Mon, 23 Sep 2024 17:20:17 -0700 Subject: [PATCH 10/14] [skip ci] minor --- cw_bitcoin/lib/litecoin_wallet.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 04b500b43..13b442d8d 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -345,6 +345,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { Future stopSync() async { _syncTimer?.cancel(); _utxoStream?.cancel(); + _stuckSyncTimer?.cancel(); await CwMweb.stop(); } From 633d5242c2c09bd2afbcc5e9d1d6848a9ddb5fed Mon Sep 17 00:00:00 2001 From: fossephate Date: Mon, 23 Sep 2024 17:20:46 -0700 Subject: [PATCH 11/14] [skip ci] minor --- cw_bitcoin/lib/litecoin_wallet.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 13b442d8d..a4ac7258b 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -346,6 +346,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { _syncTimer?.cancel(); _utxoStream?.cancel(); _stuckSyncTimer?.cancel(); + _feeRatesTimer?.cancel(); await CwMweb.stop(); } From cf1e8a306c3117feb3be42c81c5abe0fd2fe7769 Mon Sep 17 00:00:00 2001 From: Serhii Date: Tue, 24 Sep 2024 06:40:33 +0300 Subject: [PATCH 12/14] Qr code passphrase restoration flow fix (#1694) * add passphrase to credentials * prevent double restoring * fix conflict, simplify restricting user from tapping restore multiple times --------- Co-authored-by: Omar Hatem --- .../screens/restore/restore_options_page.dart | 96 ++++++++++++------- .../widgets/alert_with_no_action.dart.dart | 30 ++++++ lib/src/widgets/base_alert_dialog.dart | 4 +- .../restore/restore_from_qr_vm.dart | 8 +- lib/view_model/restore/restore_wallet.dart | 4 + 5 files changed, 100 insertions(+), 42 deletions(-) create mode 100644 lib/src/widgets/alert_with_no_action.dart.dart diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index 472f311c9..d671230c4 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -31,30 +31,45 @@ class RestoreOptionsPage extends BasePage { final bool isNewInstall; + @override + Widget body(BuildContext context) { + return _RestoreOptionsBody(isNewInstall: isNewInstall, themeType: currentTheme.type); + } +} + +class _RestoreOptionsBody extends StatefulWidget { + const _RestoreOptionsBody({required this.isNewInstall, required this.themeType}); + + final bool isNewInstall; + final ThemeType themeType; + + @override + _RestoreOptionsBodyState createState() => _RestoreOptionsBodyState(); +} + +class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> { + bool isRestoring = false; + bool get _doesSupportHardwareWallets { if (!DeviceInfo.instance.isMobile) { return false; } if (isMoneroOnly) { - return DeviceConnectionType.supportedConnectionTypes(WalletType.monero, Platform.isIOS) - .isNotEmpty; + return DeviceConnectionType.supportedConnectionTypes(WalletType.monero, Platform.isIOS).isNotEmpty; } return true; } @override - Widget body(BuildContext context) { + Widget build(BuildContext context) { final mainImageColor = Theme.of(context).extension()!.pageTitleTextColor; final brightImageColor = Theme.of(context).extension()!.textColor; - final imageColor = currentTheme.type == ThemeType.bright ? brightImageColor : mainImageColor; + final imageColor = widget.themeType == ThemeType.bright ? brightImageColor : mainImageColor; final imageLedger = Image.asset('assets/images/ledger_nano.png', width: 40, color: imageColor); final imageSeedKeys = Image.asset('assets/images/restore_wallet_image.png', color: imageColor); final imageBackup = Image.asset('assets/images/backup.png', color: imageColor); - final qrCode = Image.asset('assets/images/restore_qr.png', color: imageColor); - - return Center( child: Container( @@ -66,16 +81,17 @@ class RestoreOptionsPage extends BasePage { children: [ OptionTile( key: ValueKey('restore_options_from_seeds_button_key'), - onPressed: () => Navigator.pushNamed( - context, - Routes.restoreWalletFromSeedKeys, - arguments: isNewInstall, - ), + onPressed: () => + Navigator.pushNamed( + context, + Routes.restoreWalletFromSeedKeys, + arguments: widget.isNewInstall, + ), image: imageSeedKeys, title: S.of(context).restore_title_from_seed_keys, description: S.of(context).restore_description_from_seed_keys, ), - if (isNewInstall) + if (widget.isNewInstall) Padding( padding: EdgeInsets.only(top: 24), child: OptionTile( @@ -91,9 +107,8 @@ class RestoreOptionsPage extends BasePage { padding: EdgeInsets.only(top: 24), child: OptionTile( key: ValueKey('restore_options_from_hardware_wallet_button_key'), - onPressed: () => Navigator.pushNamed( - context, Routes.restoreWalletFromHardwareWallet, - arguments: isNewInstall), + onPressed: () => Navigator.pushNamed(context, Routes.restoreWalletFromHardwareWallet, + arguments: widget.isNewInstall), image: imageLedger, title: S.of(context).restore_title_from_hardware_wallet, description: S.of(context).restore_description_from_hardware_wallet, @@ -119,36 +134,47 @@ class RestoreOptionsPage extends BasePage { } void _onWalletCreateFailure(BuildContext context, String error) { - showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: S.current.error, - alertContent: error, - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); - }); + setState(() { + isRestoring = false; + }); + + WidgetsBinding.instance.addPostFrameCallback((_) { + showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: S.current.error, + alertContent: error, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop()); + }); + }); + } Future _onScanQRCode(BuildContext context) async { - final isCameraPermissionGranted = - await PermissionHandler.checkPermission(Permission.camera, context); + final isCameraPermissionGranted = await PermissionHandler.checkPermission(Permission.camera, context); if (!isCameraPermissionGranted) return; bool isPinSet = false; - if (isNewInstall) { + if (widget.isNewInstall) { await Navigator.pushNamed(context, Routes.setupPin, arguments: (PinCodeState setupPinContext, String _) { - setupPinContext.close(); - isPinSet = true; - }); + setupPinContext.close(); + isPinSet = true; + }); } - if (!isNewInstall || isPinSet) { + if (!widget.isNewInstall || isPinSet) { try { + if (isRestoring) { + return; + } + setState(() { + isRestoring = true; + }); final restoreWallet = await WalletRestoreFromQRCode.scanQRCodeForRestoring(context); - final restoreFromQRViewModel = - getIt.get(param1: restoreWallet.type); + final restoreFromQRViewModel = getIt.get(param1: restoreWallet.type); await restoreFromQRViewModel.create(restoreWallet: restoreWallet); if (restoreFromQRViewModel.state is FailureState) { @@ -160,4 +186,4 @@ class RestoreOptionsPage extends BasePage { } } } -} +} \ No newline at end of file diff --git a/lib/src/widgets/alert_with_no_action.dart.dart b/lib/src/widgets/alert_with_no_action.dart.dart new file mode 100644 index 000000000..623656397 --- /dev/null +++ b/lib/src/widgets/alert_with_no_action.dart.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:cake_wallet/src/widgets/base_alert_dialog.dart'; + +class AlertWithNoAction extends BaseAlertDialog { + AlertWithNoAction({ + required this.alertTitle, + required this.alertContent, + this.alertBarrierDismissible = true, + Key? key, + }); + + final String alertTitle; + final String alertContent; + final bool alertBarrierDismissible; + + @override + String get titleText => alertTitle; + + @override + String get contentText => alertContent; + + @override + bool get barrierDismissible => alertBarrierDismissible; + + @override + bool get isBottomDividerExists => false; + + @override + Widget actionButtons(BuildContext context) => Container(height: 60); +} diff --git a/lib/src/widgets/base_alert_dialog.dart b/lib/src/widgets/base_alert_dialog.dart index 2e6f1571e..1b521a427 100644 --- a/lib/src/widgets/base_alert_dialog.dart +++ b/lib/src/widgets/base_alert_dialog.dart @@ -17,6 +17,8 @@ class BaseAlertDialog extends StatelessWidget { bool get isDividerExists => false; + bool get isBottomDividerExists => true; + VoidCallback get actionLeft => () {}; VoidCallback get actionRight => () {}; @@ -205,7 +207,7 @@ class BaseAlertDialog extends StatelessWidget { ) ], ), - const HorizontalSectionDivider(), + if (isBottomDividerExists) const HorizontalSectionDivider(), ClipRRect( borderRadius: BorderRadius.all(Radius.circular(30)), child: actionButtons(context)) diff --git a/lib/view_model/restore/restore_from_qr_vm.dart b/lib/view_model/restore/restore_from_qr_vm.dart index bb7d0f8d1..6701b639d 100644 --- a/lib/view_model/restore/restore_from_qr_vm.dart +++ b/lib/view_model/restore/restore_from_qr_vm.dart @@ -56,12 +56,8 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store WalletCredentials getCredentialsFromRestoredWallet( dynamic options, RestoredWallet restoreWallet) { final password = generateWalletPassword(); - String? passphrase; + DerivationInfo? derivationInfo; - if (options != null) { - derivationInfo = options["derivationInfo"] as DerivationInfo?; - passphrase = options["passphrase"] as String?; - } derivationInfo ??= getDefaultCreateDerivation(); switch (restoreWallet.restoreMode) { @@ -119,7 +115,7 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password, - passphrase: passphrase, + passphrase: restoreWallet.passphrase, derivationType: derivationInfo!.derivationType!, derivationPath: derivationInfo.derivationPath!, ); diff --git a/lib/view_model/restore/restore_wallet.dart b/lib/view_model/restore/restore_wallet.dart index d46c48092..2c2a25005 100644 --- a/lib/view_model/restore/restore_wallet.dart +++ b/lib/view_model/restore/restore_wallet.dart @@ -10,6 +10,7 @@ class RestoredWallet { this.spendKey, this.viewKey, this.mnemonicSeed, + this.passphrase, this.txAmount, this.txDescription, this.recipientName, @@ -23,6 +24,7 @@ class RestoredWallet { final String? spendKey; final String? viewKey; final String? mnemonicSeed; + final String? passphrase; final String? txAmount; final String? txDescription; final String? recipientName; @@ -46,11 +48,13 @@ class RestoredWallet { final height = json['height'] as String?; final mnemonic_seed = json['mnemonic_seed'] as String?; final seed = json['seed'] as String? ?? json['hexSeed'] as String?; + final passphrase = json['passphrase'] as String?; return RestoredWallet( restoreMode: json['mode'] as WalletRestoreMode, type: json['type'] as WalletType, address: json['address'] as String?, mnemonicSeed: mnemonic_seed ?? seed, + passphrase: passphrase, height: height != null ? int.parse(height) : 0, ); } From fc7bea683034251900d950cf8cfd6cfeb809dad4 Mon Sep 17 00:00:00 2001 From: David Adegoke <64401859+Blazebrain@users.noreply.github.com> Date: Tue, 24 Sep 2024 14:37:09 +0100 Subject: [PATCH 13/14] Fix-agressive-contract-check (#1698) * fix: Lower aggressiveness and modify parameter used when fetching * fix: Remove extra warning text when adding contract address * chore: Add some tracking logs * chore: Add some tracking logs * chore: More comprehensive logs * chore: More readable release logs --------- Co-authored-by: Omar Hatem --- .../src/pending_bitcoin_cash_transaction.dart | 4 ++- .../screens/dashboard/edit_token_page.dart | 9 ------ .../dashboard/home_settings_view_model.dart | 32 ++++++++++++------- res/values/strings_ar.arb | 1 - res/values/strings_bg.arb | 1 - res/values/strings_cs.arb | 1 - res/values/strings_de.arb | 1 - res/values/strings_en.arb | 1 - res/values/strings_es.arb | 1 - res/values/strings_fr.arb | 1 - res/values/strings_ha.arb | 1 - res/values/strings_hi.arb | 1 - res/values/strings_hr.arb | 1 - res/values/strings_hy.arb | 1 - res/values/strings_id.arb | 1 - res/values/strings_it.arb | 1 - res/values/strings_ja.arb | 1 - res/values/strings_ko.arb | 1 - res/values/strings_my.arb | 1 - res/values/strings_nl.arb | 1 - res/values/strings_pl.arb | 1 - res/values/strings_pt.arb | 1 - res/values/strings_ru.arb | 1 - res/values/strings_th.arb | 1 - res/values/strings_tl.arb | 1 - res/values/strings_tr.arb | 1 - res/values/strings_uk.arb | 1 - res/values/strings_ur.arb | 1 - res/values/strings_vi.arb | 1 - res/values/strings_yo.arb | 1 - res/values/strings_zh.arb | 1 - 31 files changed, 23 insertions(+), 50 deletions(-) diff --git a/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart b/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart index 6d2ab4696..e1fa9d6e0 100644 --- a/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart +++ b/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart @@ -82,5 +82,7 @@ class PendingBitcoinCashTransaction with PendingTransaction { date: DateTime.now(), isPending: true, confirmations: 0, - fee: fee); + fee: fee, + isReplaced: false, + ); } diff --git a/lib/src/screens/dashboard/edit_token_page.dart b/lib/src/screens/dashboard/edit_token_page.dart index 6f662e2be..a1c429ad8 100644 --- a/lib/src/screens/dashboard/edit_token_page.dart +++ b/lib/src/screens/dashboard/edit_token_page.dart @@ -170,15 +170,6 @@ class _EditTokenPageBodyState extends State { bottomSection: Column( children: [ if (_showDisclaimer) ...[ - Text( - S.current.do_not_send_funds_to_contract_address_warning, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14.0, - color: Theme.of(context).extension()!.titleColor, - ), - ), - SizedBox(height: 20), CheckboxWidget( value: _disclaimerChecked, caption: S.of(context).add_token_disclaimer_check, diff --git a/lib/view_model/dashboard/home_settings_view_model.dart b/lib/view_model/dashboard/home_settings_view_model.dart index bb21f20ef..4269078a5 100644 --- a/lib/view_model/dashboard/home_settings_view_model.dart +++ b/lib/view_model/dashboard/home_settings_view_model.dart @@ -151,24 +151,34 @@ abstract class HomeSettingsViewModelBase with Store { bool isEthereum = _balanceViewModel.wallet.type == WalletType.ethereum; + print('An extra log for now'); + bool isPotentialScamViaMoralis = await _isPotentialScamTokenViaMoralis( contractAddress, isEthereum ? 'eth' : 'polygon', ); + print('Is Potential Scam from Moralis: $isPotentialScamViaMoralis'); + bool isPotentialScamViaExplorers = await _isPotentialScamTokenViaExplorers( contractAddress, isEthereum: isEthereum, ); + print('Is Potential Scam from Explorers: $isPotentialScamViaExplorers'); + bool isUnverifiedContract = await _isContractUnverified( contractAddress, isEthereum: isEthereum, ); + print('Is Unverified Contract: $isUnverifiedContract'); + final showWarningForContractAddress = isPotentialScamViaMoralis || isUnverifiedContract || isPotentialScamViaExplorers; + print('Show Warning: $showWarningForContractAddress'); + return showWarningForContractAddress; } finally { isValidatingContractAddress = false; @@ -236,6 +246,7 @@ abstract class HomeSettingsViewModelBase with Store { return false; } catch (e) { + print('Error while checking scam via moralis: ${e.toString()}'); return true; } } @@ -261,29 +272,22 @@ abstract class HomeSettingsViewModelBase with Store { final decodedResponse = jsonDecode(response.body) as Map; if (decodedResponse['status'] != '1') { - log('${decodedResponse['result']}'); + print('${response.body}\n'); + print('${decodedResponse['result']}\n'); return true; } final tokenInfo = Erc20TokenInfoExplorers.fromJson(decodedResponse['result'][0] as Map); - // A token without an email to reach its creators is a potential red flag - if (tokenInfo.email?.isEmpty == true) { - return true; - } - // A token without a website is a potential red flag if (tokenInfo.website?.isEmpty == true) { return true; } - // if (tokenInfo.whitepaper == null) { - // return true; - // } - return false; } catch (e) { + print('Error while checking scam via explorers: ${e.toString()}'); return true; } } @@ -298,7 +302,7 @@ abstract class HomeSettingsViewModelBase with Store { { "module": "contract", "action": "getsourcecode", - "contractaddress": contractAddress, + "address": contractAddress, "apikey": isEthereum ? secrets.etherScanApiKey : secrets.polygonScanApiKey, }, ); @@ -309,17 +313,21 @@ abstract class HomeSettingsViewModelBase with Store { final decodedResponse = jsonDecode(response.body) as Map; if (decodedResponse['status'] == '0') { - log('${decodedResponse['result']}'); + print('${response.body}\n'); + print('${decodedResponse['result']}\n'); return true; } if (decodedResponse['status'] == '1' && decodedResponse['result'][0]['ABI'] == 'Contract source code not verified') { + print('Call is valid but contract is not verified'); return true; // Contract is not verified } else { + print('Call is valid and contract is verified'); return false; // Contract is verified } } catch (e) { + print('Error while checking contract verification: ${e.toString()}'); return true; } } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 12ecceed9..c9a0c1a37 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -222,7 +222,6 @@ "displayable": "قابل للعرض", "do_not_have_enough_gas_asset": "ليس لديك ما يكفي من ${currency} لإجراء معاملة وفقًا لشروط شبكة blockchain الحالية. أنت بحاجة إلى المزيد من ${currency} لدفع رسوم شبكة blockchain، حتى لو كنت ترسل أصلًا مختلفًا.", "do_not_send": "لا ترسل", - "do_not_send_funds_to_contract_address_warning": "لا ترسل أموالًا إلى هذا العنوان \n\n هذا مجرد معرف للرمز المميز ، فستضيع أي أموال تم إرسالها إلى هذا العنوان. \n\n ملاحظة: لن تطلب منك Cake إضافة عنوان عقد أبدًا", "do_not_share_warning_text": "لا تشارك هذه مع أي شخص آخر ، بما في ذلك الدعم.\n\nيمكن أن تتم سرقة أموالك!", "do_not_show_me": "لا ترني هذا مجددا", "domain_looks_up": "ﻝﺎﺠﻤﻟﺍ ﺚﺤﺑ ﺕﺎﻴﻠﻤﻋ", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index b1a1096e6..2021dd220 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -222,7 +222,6 @@ "displayable": "Възможност за показване", "do_not_have_enough_gas_asset": "Нямате достатъчно ${currency}, за да извършите транзакция с текущите условия на блокчейн мрежата. Имате нужда от повече ${currency}, за да платите таксите за блокчейн мрежа, дори ако изпращате различен актив.", "do_not_send": "Не изпращай", - "do_not_send_funds_to_contract_address_warning": "Не изпращайте средства на този адрес \n\n Това е само идентификатор за токена, всички средства, изпратени на този адрес", "do_not_share_warning_text": "Не споделяйте това с никого, дори и отдел поддръжка.\n\nПарите Ви могат и ще бъдат откраднати!", "do_not_show_me": "Не показвай повече това", "domain_looks_up": "Търсене на домейни", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 7ce797845..bc8a8903a 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -222,7 +222,6 @@ "displayable": "Zobrazitelné", "do_not_have_enough_gas_asset": "Nemáte dostatek ${currency} k provedení transakce s aktuálními podmínkami blockchainové sítě. K placení poplatků za blockchainovou síť potřebujete více ${currency}, i když posíláte jiné aktivum.", "do_not_send": "Neodesílat", - "do_not_send_funds_to_contract_address_warning": "Neposílejte finanční prostředky na tuto adresu \n\n Toto je pouze identifikátor pro token, jakékoli prostředky zaslané na tuto adresu budou ztraceny.", "do_not_share_warning_text": "Toto nesdílejte s nikým jiným, ani s podporou.\n\nJinak mohou být Vaše prostředky ukradeny!", "do_not_show_me": "Příště nezobrazovat", "domain_looks_up": "Vyhledávání domén", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index e599da769..4a7565d0c 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -222,7 +222,6 @@ "displayable": "Anzeigebar", "do_not_have_enough_gas_asset": "Sie verfügen nicht über genügend ${currency}, um eine Transaktion unter den aktuellen Bedingungen des Blockchain-Netzwerks durchzuführen. Sie benötigen mehr ${currency}, um die Gebühren für das Blockchain-Netzwerk zu bezahlen, auch wenn Sie einen anderen Vermögenswert senden.", "do_not_send": "Nicht senden", - "do_not_send_funds_to_contract_address_warning": "Senden Sie keine Mittel an diese Adresse \n\n Dies ist nur eine Kennung für das Token. Alle an diese Adresse gesendeten Mittel gehen verloren. \n\n Hinweis: Kuchen würde Sie niemals auffordern, eine Vertragsadresse hinzuzufügen", "do_not_share_warning_text": "Teilen Sie diese nicht mit anderen, einschließlich Support.\n\nIhr Geld kann und wird gestohlen werden!", "do_not_show_me": "Zeig mir das nicht noch einmal", "domain_looks_up": "Domain-Suchen", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 72e05b8b5..975667036 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -222,7 +222,6 @@ "displayable": "Displayable", "do_not_have_enough_gas_asset": "You do not have enough ${currency} to make a transaction with the current blockchain network conditions. You need more ${currency} to pay blockchain network fees, even if you are sending a different asset.", "do_not_send": "Don't send", - "do_not_send_funds_to_contract_address_warning": "Do not send funds to this address\n\n This is just an identifier for the token, any funds sent to this address will be lost.\n\n NOTE: Cake would never ask you to add a contract address", "do_not_share_warning_text": "Do not share these with anyone else, including support.\n\nYour funds can and will be stolen!", "do_not_show_me": "Do not show me this again", "domain_looks_up": "Domain lookups", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 2cdc2318a..19356fc20 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -222,7 +222,6 @@ "displayable": "Visualizable", "do_not_have_enough_gas_asset": "No tienes suficiente ${currency} para realizar una transacción con las condiciones actuales de la red blockchain. Necesita más ${currency} para pagar las tarifas de la red blockchain, incluso si envía un activo diferente.", "do_not_send": "no enviar", - "do_not_send_funds_to_contract_address_warning": "No envíe fondos a esta dirección \n\n Esto es solo un identificador para el token, se perderán los fondos enviados a esta dirección. \n\n Nota: Cake nunca le pediría que agregue una dirección de contrato", "do_not_share_warning_text": "No comparta estos con nadie más, incluido el soporte.\n\n¡Sus fondos pueden ser y serán robados!", "do_not_show_me": "no me muestres esto otra vez", "domain_looks_up": "Búsquedas de dominio", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 27109c0ae..4b57d026b 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -222,7 +222,6 @@ "displayable": "Visible", "do_not_have_enough_gas_asset": "Vous n'avez pas assez de ${currency} pour effectuer une transaction avec les conditions actuelles du réseau blockchain. Vous avez besoin de plus de ${currency} pour payer les frais du réseau blockchain, même si vous envoyez un actif différent.", "do_not_send": "Ne pas envoyer", - "do_not_send_funds_to_contract_address_warning": "N'envoyez pas de fonds à cette adresse \n\n Ceci est juste un identifiant pour le jeton, tous les fonds envoyés à cette adresse seront perdus. \n\n Remarque: Le gâteau ne vous demanderait jamais d'ajouter une adresse de contrat", "do_not_share_warning_text": "Ne les partagez avec personne, y compris avec l'assistance.\n\nVos fonds seraient inmanquablement volés !", "do_not_show_me": "Ne plus me montrer ceci à l'avenir", "domain_looks_up": "Résolution de nom", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 1c293bd54..34cbf0a69 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -222,7 +222,6 @@ "displayable": "Ana iya nunawa", "do_not_have_enough_gas_asset": "Ba ku da isassun ${currency} don yin ma'amala tare da yanayin cibiyar sadarwar blockchain na yanzu. Kuna buƙatar ƙarin ${currency} don biyan kuɗaɗen cibiyar sadarwar blockchain, koda kuwa kuna aika wata kadara daban.", "do_not_send": "Kada ka aika", - "do_not_send_funds_to_contract_address_warning": "Kada ku aika da kudade zuwa wannan adireshin \n\n Wannan kawai mai ganowa ne kawai don token, kowane asusu da aka aiko zuwa wannan adireshin za a rasa. # Lafazin ba zai taba tambayar ka ƙara adireshin kwangila", "do_not_share_warning_text": "Kada ku raba waɗannan ga kowa, gami da tallafi.\n\nZa a iya sace kuɗin ku kuma za a sace!", "do_not_show_me": "Kar ka sake nuna min wannan", "domain_looks_up": "Binciken yanki", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index a93e20ea0..e321358ee 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -222,7 +222,6 @@ "displayable": "प्रदर्शन योग्य", "do_not_have_enough_gas_asset": "वर्तमान ब्लॉकचेन नेटवर्क स्थितियों में लेनदेन करने के लिए आपके पास पर्याप्त ${currency} नहीं है। ब्लॉकचेन नेटवर्क शुल्क का भुगतान करने के लिए आपको अधिक ${currency} की आवश्यकता है, भले ही आप एक अलग संपत्ति भेज रहे हों।", "do_not_send": "मत भेजो", - "do_not_send_funds_to_contract_address_warning": "इस पते पर धन न भेजें \n\n यह सिर्फ टोकन के लिए एक पहचानकर्ता है, इस पते पर भेजे गए किसी भी धन को खो दिया जाएगा। \n\n नोट: केक आपको एक अनुबंध पता जोड़ने के लिए कभी नहीं कहेगा", "do_not_share_warning_text": "समर्थन सहित, इन्हें किसी और के साथ साझा न करें।\n\nआपके धन की चोरी हो सकती है और होगी!", "do_not_show_me": "मुझे यह फिर न दिखाएं", "domain_looks_up": "डोमेन लुकअप", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index b60a056fd..cd91d5291 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -222,7 +222,6 @@ "displayable": "Dostupno za prikaz", "do_not_have_enough_gas_asset": "Nemate dovoljno ${currency} da izvršite transakciju s trenutačnim uvjetima blockchain mreže. Trebate više ${currency} da platite naknade za blockchain mrežu, čak i ako šaljete drugu imovinu.", "do_not_send": "Ne šalji", - "do_not_send_funds_to_contract_address_warning": "Ne šaljite sredstva na ovu adresu \n\n Ovo je samo identifikator za token, izgubit će se bilo koja sredstva poslana na ovu adresu. \n\n Napomena: Torta nikad ne bi tražila da dodate adresu ugovora", "do_not_share_warning_text": "Nemojte ih dijeliti ni s kim, uključujući podršku.\n\nVaša sredstva mogu i bit će ukradena!", "do_not_show_me": "Ne pokazuj mi ovo više", "domain_looks_up": "Pretraga domena", diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index eeb1d3f99..8c65817c2 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -222,7 +222,6 @@ "displayable": "Ցուցադրվող", "do_not_have_enough_gas_asset": "Դուք չունեք բավարար ${currency} տրանզակցիան կատարելու համար ընթացիկ բլոկչեյն ցանցի պայմաններում: Դուք պետք է ունենաք ավելի շատ ${currency} blockchain ցանցի միջնորդավճարները վճարելու համար, նույնիսկ եթե դուք այլ ակտիվ եք ուղարկում:", "do_not_send": "Մի ուղարկեք", - "do_not_send_funds_to_contract_address_warning": "Այս հասցեին գումարներ մի ուղարկեք \n\n Սա պարզապես նույնականացն է նշանի համար, այս հասցեով ուղարկված ցանկացած միջոց կկորչի: \n\n Նշում. Տորթը երբեք չի խնդրի ձեզ ավելացնել պայմանագրի հասցե", "do_not_share_warning_text": "Մի կիսեք այս տեղեկատվությունը որևէ մեկի հետ, այդ թվում նաև աջակցության հետ: \n\nՁեր միջոցները կարող են գողանալ կորցնել!", "do_not_show_me": "Մի ցուցադրեք ինձ նորից", "domain_looks_up": "Դոմեյնի որոնում", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 5e48ff1d3..a888a336a 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -222,7 +222,6 @@ "displayable": "Dapat ditampilkan", "do_not_have_enough_gas_asset": "Anda tidak memiliki cukup ${currency} untuk melakukan transaksi dengan kondisi jaringan blockchain saat ini. Anda memerlukan lebih banyak ${currency} untuk membayar biaya jaringan blockchain, meskipun Anda mengirimkan aset yang berbeda.", "do_not_send": "Jangan kirim", - "do_not_send_funds_to_contract_address_warning": "Jangan mengirim dana ke alamat ini \n\n Ini hanya pengidentifikasi untuk token, dana apa pun yang dikirim ke alamat ini akan hilang. \n\n Catatan: Kue tidak akan pernah meminta Anda untuk menambahkan alamat kontrak", "do_not_share_warning_text": "Jangan berikan ini pada siapapun, termasuk dukungan.\n\nDana Anda bisa dan akan dicuri!", "do_not_show_me": "Jangan tampilkan ini lagi", "domain_looks_up": "Pencarian domain", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index d509cb256..0e307ac9f 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -223,7 +223,6 @@ "displayable": "Visualizzabile", "do_not_have_enough_gas_asset": "Non hai abbastanza ${currency} per effettuare una transazione con le attuali condizioni della rete blockchain. Hai bisogno di più ${currency} per pagare le commissioni della rete blockchain, anche se stai inviando una risorsa diversa.", "do_not_send": "Non inviare", - "do_not_send_funds_to_contract_address_warning": "Non inviare fondi a questo indirizzo \n\n Questo è solo un identificatore per il token, qualsiasi fondi inviati a questo indirizzo andrà perso. \n\n Nota: la torta non ti chiederebbe mai di aggiungere un indirizzo contrattuale", "do_not_share_warning_text": "Non condividerli con nessun altro, incluso il supporto.\n\nI tuoi fondi possono e saranno rubati!", "do_not_show_me": "Non mostrarmelo di nuovo", "domain_looks_up": "Ricerche di domini", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index f08437336..efb7bcc81 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -222,7 +222,6 @@ "displayable": "表示可能", "do_not_have_enough_gas_asset": "現在のブロックチェーン ネットワークの状況では、トランザクションを行うのに十分な ${currency} がありません。別のアセットを送信する場合でも、ブロックチェーン ネットワーク料金を支払うにはさらに ${currency} が必要です。", "do_not_send": "送信しない", - "do_not_send_funds_to_contract_address_warning": "この住所に資金を送らないでください\n\nこれはトークンの識別子であり、この住所に送られた資金は失われます。", "do_not_share_warning_text": "サポートを含め、これらを他の誰とも共有しないでください。\n\nあなたの資金は盗まれる可能性があります!", "do_not_show_me": "また僕にこれを見せないでください", "domain_looks_up": "ドメイン検索", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 60ee05da2..24b6acc8c 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -222,7 +222,6 @@ "displayable": "표시 가능", "do_not_have_enough_gas_asset": "현재 블록체인 네트워크 조건으로 거래를 하기에는 ${currency}이(가) 충분하지 않습니다. 다른 자산을 보내더라도 블록체인 네트워크 수수료를 지불하려면 ${currency}가 더 필요합니다.", "do_not_send": "보내지 마세요", - "do_not_send_funds_to_contract_address_warning": "이 주소로 자금을 보내지 마십시오 \n\n 이것은 토큰의 식별자 일뿐입니다.이 주소로 전송 된 모든 자금은 손실됩니다. \n\n 참고 : Cake는 계약서 주소를 추가하도록 요구하지 않습니다.", "do_not_share_warning_text": "지원을 포함하여 다른 사람과 이러한 정보를 공유하지 마십시오.\n\n귀하의 자금은 도난당할 수 있고 도난당할 수 있습니다!", "do_not_show_me": "나를 다시 표시하지 않음", "domain_looks_up": "도메인 조회", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index d0aae18ea..a2d783e52 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -222,7 +222,6 @@ "displayable": "ပြသနိုင်သည်။", "do_not_have_enough_gas_asset": "လက်ရှိ blockchain ကွန်ရက်အခြေအနေများနှင့် အရောင်းအဝယ်ပြုလုပ်ရန် သင့်တွင် ${currency} လုံလောက်မှုမရှိပါ။ သင်သည် မတူညီသော ပိုင်ဆိုင်မှုတစ်ခုကို ပေးပို့နေသော်လည်း blockchain ကွန်ရက်အခကြေးငွေကို ပေးဆောင်ရန် သင်သည် နောက်ထပ် ${currency} လိုအပ်ပါသည်။", "do_not_send": "မပို့ပါနှင့်", - "do_not_send_funds_to_contract_address_warning": "ဒီလိပ်စာကိုရန်ပုံငွေမပို့ပါနဲ့။ ဒီလိပ်စာကိုအမှတ်အသားမပို့ပါနဲ့, ဒီလိပ်စာကိုပို့တဲ့ရန်ပုံငွေမဆိုဆုံးရှုံးသွားမှာပါ။ \n\n မှတ်ချက်။ ။ \n\n မှတ်ချက်။ ။", "do_not_share_warning_text": "ပံ့ပိုးကူညီမှုအပါအဝင် ဤအရာများကို အခြားမည်သူနှင့်မျှ မမျှဝေပါနှင့်။\n\nသင့်ငွေများကို ခိုးယူခံရနိုင်သည်!", "do_not_show_me": "ဒါကို ထပ်မပြနဲ့", "domain_looks_up": "ဒိုမိန်းရှာဖွေမှုများ", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 273a65ae5..a7d414b1c 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -222,7 +222,6 @@ "displayable": "Weer te geven", "do_not_have_enough_gas_asset": "U heeft niet genoeg ${currency} om een transactie uit te voeren met de huidige blockchain-netwerkomstandigheden. U heeft meer ${currency} nodig om blockchain-netwerkkosten te betalen, zelfs als u een ander item verzendt.", "do_not_send": "Niet sturen", - "do_not_send_funds_to_contract_address_warning": "Stuur geen fondsen naar dit adres \n\n Dit is slechts een identificatie voor het token, alle fondsen die naar dit adres zijn verzonden, gaan verloren. \n\n Opmerking: cake zou u nooit vragen om een ​​contractadres toe te voegen", "do_not_share_warning_text": "Deel deze met niemand anders, ook niet met support.\n\nUw geld kan en zal worden gestolen!", "do_not_show_me": "laat me dit niet opnieuw zien", "domain_looks_up": "Domein opzoeken", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 046db2187..00eebbe98 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -222,7 +222,6 @@ "displayable": "Wyświetlane", "do_not_have_enough_gas_asset": "Nie masz wystarczającej ilości ${currency}, aby dokonać transakcji przy bieżących warunkach sieci blockchain. Potrzebujesz więcej ${currency}, aby uiścić opłaty za sieć blockchain, nawet jeśli wysyłasz inny zasób.", "do_not_send": "Nie wysyłaj", - "do_not_send_funds_to_contract_address_warning": "Nie wysyłaj środków na ten adres \n\n To jest tylko identyfikator tokena, wszelkie środki wysłane na ten adres zostaną utracone. \n\n", "do_not_share_warning_text": "NIE udostępniaj ich nikomu innemu, w tym pomocy technicznej.\n\nTwoje środki wtedy prawdopodobnie zostaną skradzione!", "do_not_show_me": "Nie pokazuj mi tego ponownie", "domain_looks_up": "Wyszukiwanie domen", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 164cb9530..28bea3e65 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -222,7 +222,6 @@ "displayable": "Exibível", "do_not_have_enough_gas_asset": "Você não tem ${currency} suficiente para fazer uma transação com as condições atuais da rede blockchain. Você precisa de mais ${currency} para pagar as taxas da rede blockchain, mesmo se estiver enviando um ativo diferente.", "do_not_send": "não envie", - "do_not_send_funds_to_contract_address_warning": "Não envie fundos para este endereço \n\n Este é apenas um identificador para o token, quaisquer fundos enviados para este endereço serão perdidos. \n\n NOTA: O bolo nunca solicitaria que você adicione um endereço de contrato", "do_not_share_warning_text": "Não os compartilhe com mais ninguém, incluindo suporte.\n\nSeus fundos podem e serão roubados!", "do_not_show_me": "não me mostre isso novamente", "domain_looks_up": "Pesquisas de domínio", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 28d856191..6ffa87b0f 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -222,7 +222,6 @@ "displayable": "Отображаемый", "do_not_have_enough_gas_asset": "У вас недостаточно ${currency} для совершения транзакции при текущих условиях сети блокчейн. Вам нужно больше ${currency} для оплаты комиссий за сеть блокчейна, даже если вы отправляете другой актив.", "do_not_send": "Не отправлять", - "do_not_send_funds_to_contract_address_warning": "Не отправляйте средства на этот адрес \n\n Это просто идентификатор для токена, любые средства, отправленные на этот адрес, будут потеряны. \n\n Примечание: торт никогда не попросит вас добавить адрес контракта", "do_not_share_warning_text": "Не сообщайте их никому, включая техподдержку.\n\nВаши средства могут и будут украдены!", "do_not_show_me": "Не показывай мне это больше", "domain_looks_up": "Поиск доменов", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index ee6d5b7a2..4a41989c8 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -222,7 +222,6 @@ "displayable": "สามารถแสดงได้", "do_not_have_enough_gas_asset": "คุณมี ${currency} ไม่เพียงพอที่จะทำธุรกรรมกับเงื่อนไขเครือข่ายบล็อคเชนในปัจจุบัน คุณต้องมี ${currency} เพิ่มขึ้นเพื่อชำระค่าธรรมเนียมเครือข่ายบล็อคเชน แม้ว่าคุณจะส่งสินทรัพย์อื่นก็ตาม", "do_not_send": "อย่าส่ง", - "do_not_send_funds_to_contract_address_warning": "อย่าส่งเงินไปยังที่อยู่นี้ \n\n นี่เป็นเพียงตัวระบุสำหรับโทเค็นเงินทุนใด ๆ ที่ส่งไปยังที่อยู่นี้จะหายไป \n\n หมายเหตุ: เค้กจะไม่ขอให้คุณเพิ่มที่อยู่สัญญา", "do_not_share_warning_text": "อย่าแชร์ข้อมูลนี้กับใครอื่น รวมถึงฝ่ายสนับสนุนด้วย\n\nการเงินของคุณอาจถูกขโมยโดยไม่หวังดี!", "do_not_show_me": "อย่าแสดงข้อความนี้อีก", "domain_looks_up": "การค้นหาโดเมน", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 2e7b4f4db..f2caa5fcc 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -222,7 +222,6 @@ "displayable": "Maipapakita", "do_not_have_enough_gas_asset": "Wala kang sapat na ${currency} para gumawa ng transaksyon sa kasalukuyang kundisyon ng network ng blockchain. Kailangan mo ng higit pang ${currency} upang magbayad ng mga fee sa network ng blockchain, kahit na nagpapadala ka ng ibang asset.", "do_not_send": "Huwag ipadala", - "do_not_send_funds_to_contract_address_warning": "Huwag magpadala ng pondo sa address na ito\n\n Ito ay isang identifier lamang para sa token, ang anumang pondo na ipinadala sa address na ito ay mawawala.\n\n Tandaan: Ang cake ay hindi hihilingin sa iyo na magdagdag ng isang address ng kontrata", "do_not_share_warning_text": "Huwag ibahagi ang mga ito sa sinuman kasama ang tagatustos.\n\nMaaaring manakaw ang iyong mga pondo!", "do_not_show_me": "Huwag mo itong ipakita muli", "domain_looks_up": "Mga paghahanap ng domain", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index fba4a796e..83545e261 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -222,7 +222,6 @@ "displayable": "Gösterilebilir", "do_not_have_enough_gas_asset": "Mevcut blockchain ağ koşullarıyla işlem yapmak için yeterli ${currency} paranız yok. Farklı bir varlık gönderiyor olsanız bile blockchain ağ ücretlerini ödemek için daha fazla ${currency} miktarına ihtiyacınız var.", "do_not_send": "Gönderme", - "do_not_send_funds_to_contract_address_warning": "Bu adrese fon göndermeyin \n\n Bu sadece jeton için bir tanımlayıcıdır, bu adrese gönderilen fonlar kaybolacaktır. \n\n Not: Kekten asla bir sözleşme adresi eklemenizi istemez", "do_not_share_warning_text": "Bunları destek de dahil olmak üzere başka kimseyle paylaşma.\n\nParan çalınabilir ve çalınacaktır!", "do_not_show_me": "Bana bunu bir daha gösterme", "domain_looks_up": "Etki alanı aramaları", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index ff1f2905f..dc6baad6d 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -222,7 +222,6 @@ "displayable": "Відображуваний", "do_not_have_enough_gas_asset": "У вас недостатньо ${currency}, щоб здійснити трансакцію з поточними умовами мережі блокчейн. Вам потрібно більше ${currency}, щоб сплатити комісію мережі блокчейн, навіть якщо ви надсилаєте інший актив.", "do_not_send": "Не надсилайте", - "do_not_send_funds_to_contract_address_warning": "Не надсилайте кошти на цю адресу \n\n Це лише ідентифікатор для маркера, будь -які кошти, надіслані на цю адресу", "do_not_share_warning_text": "Не діліться цим нікому, включно зі службою підтримки.\n\nВаші кошти можуть і будуть вкрадені!", "do_not_show_me": "Не показуй мені це знову", "domain_looks_up": "Пошук доменів", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 8cfe2ec9f..2140accbe 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -222,7 +222,6 @@ "displayable": "قابل نمائش", "do_not_have_enough_gas_asset": "آپ کے پاس موجودہ بلاکچین نیٹ ورک کی شرائط کے ساتھ لین دین کرنے کے لیے کافی ${currency} نہیں ہے۔ آپ کو بلاکچین نیٹ ورک کی فیس ادا کرنے کے لیے مزید ${currency} کی ضرورت ہے، چاہے آپ کوئی مختلف اثاثہ بھیج رہے ہوں۔", "do_not_send": "مت بھیجیں۔", - "do_not_send_funds_to_contract_address_warning": "اس پتے پر فنڈز نہ بھیجیں \n\n یہ ٹوکن کے لئے صرف ایک شناخت کنندہ ہے ، اس پتے پر بھیجے گئے کوئی بھی فنڈز ضائع ہوجائیں گے۔ \n\n نوٹ: کیک آپ کو کبھی بھی معاہدہ کا پتہ شامل کرنے کے لئے نہیں کہے گا۔", "do_not_share_warning_text": "سپورٹ سمیت کسی اور کے ساتھ ان کا اشتراک نہ کریں۔\\n\\nآپ کے فنڈز چوری ہو سکتے ہیں اور ہو جائیں گے!", "do_not_show_me": "مجھے یہ دوبارہ مت دکھانا", "domain_looks_up": "ڈومین تلاش کرنا", diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index 444c1d6d8..a21da9e68 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -223,7 +223,6 @@ "displayable": "Có thể hiển thị", "do_not_have_enough_gas_asset": "Bạn không có đủ ${currency} để thực hiện giao dịch với điều kiện mạng blockchain hiện tại. Bạn cần thêm ${currency} để trả phí mạng blockchain, ngay cả khi bạn đang gửi tài sản khác.", "do_not_send": "Đừng gửi", - "do_not_send_funds_to_contract_address_warning": "Không gửi tiền đến địa chỉ này\n\n Đây chỉ là một mã định danh cho mã thông báo, bất kỳ khoản tiền nào được gửi đến địa chỉ này sẽ bị mất.\n\n Lưu ý: Bánh sẽ không bao giờ yêu cầu bạn thêm địa chỉ hợp đồng", "do_not_share_warning_text": "Không chia sẻ điều này với bất kỳ ai, bao gồm cả bộ phận hỗ trợ.\n\nTài sản của bạn có thể và sẽ bị đánh cắp!", "do_not_show_me": "Không hiển thị lại cho tôi", "domain_looks_up": "Tra cứu tên miền", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 15b90b973..8a30c5e08 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -222,7 +222,6 @@ "displayable": "A lè ṣàfihàn ẹ̀", "do_not_have_enough_gas_asset": "O ko ni to ${currency} lati ṣe idunadura kan pẹlu awọn ipo nẹtiwọki blockchain lọwọlọwọ. O nilo diẹ sii ${currency} lati san awọn owo nẹtiwọọki blockchain, paapaa ti o ba nfi dukia miiran ranṣẹ.", "do_not_send": "Ẹ kò ránṣ", - "do_not_send_funds_to_contract_address_warning": "Maṣe fi owo ranṣẹ si adirẹsi yii \n\n Eyi jẹ idamọ fun àmi, eyikeyi awọn owo ti a firanṣẹ si adirẹsi yii yoo ko beere lọwọ rẹ lati ṣafikun adirẹsi adehun kan", "do_not_share_warning_text": "Ẹ kò pín wọnyìí sí ẹnikẹ́ni. Ẹ sì kò pin wọnyìí sí ìranlọ́wọ́. Ẹnikẹ́ni lè jí owó yín! Wọ́n máa jí owó yín!", "do_not_show_me": "Kò fi eléyìí hàn mi mọ́", "domain_looks_up": "Awọn wiwa agbegbe", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index ae7e15132..6a3b9d4c8 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -222,7 +222,6 @@ "displayable": "可显示", "do_not_have_enough_gas_asset": "您没有足够的 ${currency} 来在当前的区块链网络条件下进行交易。即使您发送的是不同的资产,您也需要更多的 ${currency} 来支付区块链网络费用。", "do_not_send": "不要发送", - "do_not_send_funds_to_contract_address_warning": "请勿将资金发送到此地址\n\n这只是令牌的标识符,任何发送到此地址的资金都将丢失。\n\n注意:蛋糕永远不会要求您添加合同地址", "do_not_share_warning_text": "请勿与其他任何人分享这些信息,包括支持人员。\n\n您的资金可能而且将会被盗!", "do_not_show_me": "不再提示", "domain_looks_up": "域名查找", From 6a4eaece989bd840d12b442a7c2edef31745cb92 Mon Sep 17 00:00:00 2001 From: fossephate Date: Tue, 24 Sep 2024 08:37:44 -0700 Subject: [PATCH 14/14] revert sync status title --- lib/core/sync_status_title.dart | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/core/sync_status_title.dart b/lib/core/sync_status_title.dart index 53240875a..4582f7b1f 100644 --- a/lib/core/sync_status_title.dart +++ b/lib/core/sync_status_title.dart @@ -3,18 +3,9 @@ import 'package:cw_core/sync_status.dart'; String syncStatusTitle(SyncStatus syncStatus) { if (syncStatus is SyncingSyncStatus) { - - if (syncStatus.blocksLeft == 1) { - return S.current.block_remaining; - } - - String eta = syncStatus.getFormattedEta() ?? ''; - - if (eta.isEmpty) { - return S.current.Blocks_remaining('${syncStatus.blocksLeft}'); - } else { - return "${syncStatus.formattedProgress()} - $eta"; - } + return syncStatus.blocksLeft == 1 + ? S.current.block_remaining + : S.current.Blocks_remaining('${syncStatus.blocksLeft}'); } if (syncStatus is SyncedTipSyncStatus) {