V4.26.0 rc (#2198)

* v4.26.0 Release Candidate

* Fix Wownero Creation issue

* Add KES fiat currency

* Adjust backup to default node selection if null
Gracefully handle Decred failure
Minor fixes
This commit is contained in:
Omar Hatem 2025-04-15 02:50:07 +02:00 committed by GitHub
parent f574fa5e9b
commit ca564bc2e6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 76 additions and 49 deletions

View file

@ -222,7 +222,7 @@ abstract class DecredWalletBase
Future<bool> checkSync() async { Future<bool> checkSync() async {
final syncStatusJSON = await _libwallet.syncStatus(walletInfo.name); final syncStatusJSON = await _libwallet.syncStatus(walletInfo.name);
final decoded = json.decode(syncStatusJSON); final decoded = json.decode(syncStatusJSON.isEmpty ? "{}" : syncStatusJSON);
final syncStatusCode = decoded["syncstatuscode"] ?? 0; final syncStatusCode = decoded["syncstatuscode"] ?? 0;
// final syncStatusStr = decoded["syncstatus"] ?? ""; // final syncStatusStr = decoded["syncstatus"] ?? "";

9
lib/core/utilities.dart Normal file
View file

@ -0,0 +1,9 @@
extension EnhancedList<T> on Iterable<T> {
T? firstWhereOrNull(bool Function(T element) test) {
try {
return firstWhere(test);
} catch (e) {
return null;
}
}
}

View file

@ -3,10 +3,9 @@ import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/widgets/trail_button.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/utils/clipboard_util.dart'; import 'package:cake_wallet/utils/clipboard_util.dart';
import 'package:cake_wallet/utils/exception_handler.dart'; import 'package:cake_wallet/utils/exception_handler.dart';
import 'package:cake_wallet/utils/share_util.dart'; import 'package:cake_wallet/utils/share_util.dart';
@ -76,7 +75,9 @@ class BackupPage extends BasePage {
Navigator.of(context).pushNamed(Routes.editBackupPassword), Navigator.of(context).pushNamed(Routes.editBackupPassword),
text: S.of(context).change_password, text: S.of(context).change_password,
color: Theme.of(context).cardColor, color: Theme.of(context).cardColor,
textColor: Colors.white, textColor: Theme.of(context)
.extension<CakeTextTheme>()!
.buttonTextColor,
), ),
SizedBox(height: 10), SizedBox(height: 10),
Observer( Observer(

View file

@ -104,7 +104,7 @@ class LoadingPrimaryButton extends StatelessWidget {
), ),
)), )),
child: isLoading child: isLoading
? CupertinoActivityIndicator(animating: true) ? CupertinoActivityIndicator(animating: true, color: textColor)
: Text(text, : Text(text,
style: TextStyle( style: TextStyle(
fontSize: 15.0, fontSize: 15.0,

View file

@ -3,6 +3,7 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/core/utilities.dart';
import 'package:cake_wallet/decred/decred.dart'; import 'package:cake_wallet/decred/decred.dart';
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/core/secure_storage.dart';
@ -12,13 +13,13 @@ import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
import 'package:cake_wallet/entities/balance_display_mode.dart'; import 'package:cake_wallet/entities/balance_display_mode.dart';
import 'package:cake_wallet/entities/cake_2fa_preset_options.dart'; import 'package:cake_wallet/entities/cake_2fa_preset_options.dart';
import 'package:cake_wallet/entities/country.dart'; import 'package:cake_wallet/entities/country.dart';
import 'package:cake_wallet/entities/default_settings_migration.dart';
import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart';
import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/entities/fiat_currency.dart';
import 'package:cake_wallet/entities/language_service.dart'; import 'package:cake_wallet/entities/language_service.dart';
import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/entities/pin_code_required_duration.dart';
import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/entities/provider_types.dart';
import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/secret_store_key.dart';
import 'package:cake_wallet/entities/seed_phrase_length.dart'; import 'package:cake_wallet/entities/seed_phrase_length.dart';
import 'package:cake_wallet/entities/seed_type.dart'; import 'package:cake_wallet/entities/seed_type.dart';
@ -37,11 +38,8 @@ import 'package:cake_wallet/themes/theme_list.dart';
import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/device_info.dart';
import 'package:cake_wallet/utils/package_info.dart'; import 'package:cake_wallet/utils/package_info.dart';
import 'package:cake_wallet/view_model/settings/sync_mode.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart';
import 'package:cake_wallet/wallet_type_utils.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cw_core/node.dart'; import 'package:cw_core/node.dart';
import 'package:cw_core/set_app_secure_native.dart'; import 'package:cw_core/set_app_secure_native.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
@ -312,7 +310,7 @@ abstract class SettingsStoreBase with Store {
reaction((_) => disableTradeOption, reaction((_) => disableTradeOption,
(bool disableTradeOption) => sharedPreferences.setBool(PreferencesKey.disableTradeOption, disableTradeOption)); (bool disableTradeOption) => sharedPreferences.setBool(PreferencesKey.disableTradeOption, disableTradeOption));
reaction( reaction(
(_) => disableBulletin, (_) => disableBulletin,
(bool disableBulletin) => (bool disableBulletin) =>
@ -1038,7 +1036,6 @@ abstract class SettingsStoreBase with Store {
sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
final bitcoinCashElectrumServerId = final bitcoinCashElectrumServerId =
sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey);
final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey); final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
final polygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey); final polygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey);
final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
@ -1048,20 +1045,35 @@ abstract class SettingsStoreBase with Store {
final wowneroNodeId = sharedPreferences.getInt(PreferencesKey.currentWowneroNodeIdKey); final wowneroNodeId = sharedPreferences.getInt(PreferencesKey.currentWowneroNodeIdKey);
final zanoNodeId = sharedPreferences.getInt(PreferencesKey.currentZanoNodeIdKey); final zanoNodeId = sharedPreferences.getInt(PreferencesKey.currentZanoNodeIdKey);
final decredNodeId = sharedPreferences.getInt(PreferencesKey.currentDecredNodeIdKey); final decredNodeId = sharedPreferences.getInt(PreferencesKey.currentDecredNodeIdKey);
final moneroNode = nodeSource.get(nodeId);
final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId); /// get the selected node, if null, then use the default
final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId); final moneroNode = nodeSource.get(nodeId) ??
final havenNode = nodeSource.get(havenNodeId); nodeSource.values.firstWhereOrNull((e) => e.uriRaw == newCakeWalletMoneroUri);
final ethereumNode = nodeSource.get(ethereumNodeId); final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId) ??
final polygonNode = nodeSource.get(polygonNodeId); nodeSource.values.firstWhereOrNull((e) => e.uriRaw == newCakeWalletBitcoinUri);
final bitcoinCashElectrumServer = nodeSource.get(bitcoinCashElectrumServerId); final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId) ??
final nanoNode = nodeSource.get(nanoNodeId); nodeSource.values.firstWhereOrNull((e) => e.uriRaw == cakeWalletLitecoinElectrumUri);
final decredNode = nodeSource.get(decredNodeId); final ethereumNode = nodeSource.get(ethereumNodeId) ??
final nanoPowNode = powNodeSource.get(nanoPowNodeId); nodeSource.values.firstWhereOrNull((e) => e.uriRaw == ethereumDefaultNodeUri);
final solanaNode = nodeSource.get(solanaNodeId); final polygonNode = nodeSource.get(polygonNodeId) ??
final tronNode = nodeSource.get(tronNodeId); nodeSource.values.firstWhereOrNull((e) => e.uriRaw == polygonDefaultNodeUri);
final wowneroNode = nodeSource.get(wowneroNodeId); final bitcoinCashElectrumServer = nodeSource.get(bitcoinCashElectrumServerId) ??
final zanoNode = nodeSource.get(zanoNodeId); nodeSource.values.firstWhereOrNull((e) => e.uriRaw == cakeWalletBitcoinCashDefaultNodeUri);
final nanoNode = nodeSource.get(nanoNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == nanoDefaultNodeUri);
final decredNode = nodeSource.get(decredNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == decredDefaultUri);
final nanoPowNode = powNodeSource.get(nanoPowNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == nanoDefaultPowNodeUri);
final solanaNode = nodeSource.get(solanaNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == solanaDefaultNodeUri);
final tronNode = nodeSource.get(tronNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == tronDefaultNodeUri);
final wowneroNode = nodeSource.get(wowneroNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == wowneroDefaultNodeUri);
final zanoNode = nodeSource.get(zanoNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == zanoDefaultNodeUri);
final packageInfo = await PackageInfo.fromPlatform(); final packageInfo = await PackageInfo.fromPlatform();
final deviceName = await _getDeviceName() ?? ''; final deviceName = await _getDeviceName() ?? '';
final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true; final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true;
@ -1107,10 +1119,6 @@ abstract class SettingsStoreBase with Store {
nodes[WalletType.litecoin] = litecoinElectrumServer; nodes[WalletType.litecoin] = litecoinElectrumServer;
} }
if (havenNode != null) {
nodes[WalletType.haven] = havenNode;
}
if (ethereumNode != null) { if (ethereumNode != null) {
nodes[WalletType.ethereum] = ethereumNode; nodes[WalletType.ethereum] = ethereumNode;
} }

View file

@ -107,20 +107,24 @@ abstract class AnonInvoicePageViewModelBase with Store {
return; return;
} }
} }
final result = await anonPayApi.createInvoice(AnonPayRequest( try {
cryptoCurrency: cryptoCurrency, final result = await anonPayApi.createInvoice(AnonPayRequest(
address: address, cryptoCurrency: cryptoCurrency,
amount: amount.isEmpty ? null : amount, address: address,
description: description, amount: amount.isEmpty ? null : amount,
email: receipientEmail, description: description,
name: receipientName, email: receipientEmail,
fiatEquivalent: name: receipientName,
selectedCurrency is FiatCurrency ? (selectedCurrency as FiatCurrency).raw : null, fiatEquivalent:
)); selectedCurrency is FiatCurrency ? (selectedCurrency as FiatCurrency).raw : null,
));
_anonpayInvoiceInfoSource.add(result); _anonpayInvoiceInfoSource.add(result);
state = ExecutedSuccessfullyState(payload: result); state = ExecutedSuccessfullyState(payload: result);
} catch (e) {
state = FailureState(e.toString());
}
} }
@action @action
@ -156,12 +160,16 @@ abstract class AnonInvoicePageViewModelBase with Store {
} }
Future<void> _fetchLimits() async { Future<void> _fetchLimits() async {
final limit = await anonPayApi.fetchLimits( try {
cryptoCurrency: cryptoCurrency, final limit = await anonPayApi.fetchLimits(
fiatCurrency: selectedCurrency is FiatCurrency ? selectedCurrency as FiatCurrency : null, cryptoCurrency: cryptoCurrency,
); fiatCurrency: selectedCurrency is FiatCurrency ? selectedCurrency as FiatCurrency : null,
minimum = limit.min; );
maximum = limit.max != null ? limit.max! / 4 : null; minimum = limit.min;
maximum = limit.max != null ? limit.max! / 4 : null;
} catch (e) {
state = FailureState(e.toString());
}
} }
@computed @computed

View file

@ -137,7 +137,9 @@ abstract class LedgerViewModelBase with Store {
allowChangeWallet: true, allowChangeWallet: true,
isReconnect: true, isReconnect: true,
onConnectDevice: (context, ledgerVM) async { onConnectDevice: (context, ledgerVM) async {
Navigator.of(context).pop(); if (context.mounted) {
Navigator.of(context).pop();
}
}, },
), ),
); );

View file

@ -216,7 +216,6 @@ abstract class WalletListViewModelBase with Store {
await sortGroupByType(); await sortGroupByType();
break; break;
case FilterListOrderType.Custom: case FilterListOrderType.Custom:
default:
await reorderAccordingToWalletList(); await reorderAccordingToWalletList();
break; break;
} }