fix: generic fixes after anypay (#3543)
What changed, and why it matters
This commit is a follow-up bug-fix patch after a larger 'AnyPay' feature rollout. It corrects a copy-paste error where Zcash and Decred shared the same transaction-priority storage key, adds missing Dogecoin transaction-priority support, fixes a Flutter/MobX state-management warning, and moves an object initialization out of a field declaration into the widget's initState() method. None of these changes appear to be security fixes on their own; they are stability and correctness cleanups.
Treat as a routine bug-fix/maintenance commit. Reviewers may want to verify that the corrected Zcash preference key migration does not strand existing Decred/Zcash priority values, and that Dogecoin priority defaults are sensible. No urgent security action is indicated by this diff alone.
Security signals we found
Corrected shared preference key collision between Decred and Zcash transaction priorities, which could have caused incorrect fee/priority settings to be read or written.
Added missing Dogecoin transaction priority handling, preventing potential default-fee fallback behavior for Dogecoin wallets.
Refactored MobX action usage in send view model to suppress runtime MobX warnings; no direct security impact.
Moved AnyPayFlow initialization into initState(), a lifecycle correctness change with no clear security implication.
Evidence from the diff
The diff touches five Dart files. The most notable changes are: (1) PreferencesKey.zcashTransactionPriority is corrected from ‘current_fee_priority_decred’ to ‘current_fee_priority_zcash’; (2) PreferencesKey.dogecoinTransactionPriority and corresponding SettingsStore wiring are added; (3) WalletType.dogecoin is added to isElectrumWallet(); (4) AnyPayFlow is moved from a late final field initializer to initState() in NewSendPage; and (5) a MobX @action annotation is removed from _outputCryptoCurrencyHandler and a runInAction wrapper is used instead. These are generic fixes; no vulnerability class (e.g., injection, auth bypass, memory safety) is directly evidenced in the diff.
Changed components
lib/entities/preferences_key.dartlib/new-ui/pages/send_page.dartlib/reactions/wallet_utils.dartlib/store/settings_store.dartlib/view_model/send/send_view_model.dartInspect captured patch +33 / −9
diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart
index 63c94bd..d35c010 100644
--- a/lib/entities/preferences_key.dart
+++ b/lib/entities/preferences_key.dart
@@ -63,7 +63,8 @@ class PreferencesKey {
static const zanoTransactionPriority = 'current_fee_priority_zano';
static const wowneroTransactionPriority = 'current_fee_priority_wownero';
static const decredTransactionPriority = 'current_fee_priority_decred';
- static const zcashTransactionPriority = 'current_fee_priority_decred';
+ static const zcashTransactionPriority = 'current_fee_priority_zcash';
+ static const dogecoinTransactionPriority = 'current_fee_priority_dogecoin';
static const customBitcoinFeeRate = 'custom_electrum_fee_rate';
static const silentPaymentsCardDisplay = 'silentPaymentsCardDisplay';
static const mwebCardDisplay = 'mwebCardDisplay';
diff --git a/lib/new-ui/pages/send_page.dart b/lib/new-ui/pages/send_page.dart
index 0b0c51d..0a6ea20 100644
--- a/lib/new-ui/pages/send_page.dart
+++ b/lib/new-ui/pages/send_page.dart
@@ -215,12 +215,7 @@ class _NewSendPageState extends State<NewSendPage> {
final _addressFocusNode = FocusNode();
final _disposers = <ReactionDisposer>[];
StreamSubscription<Uri>? _deepLinkSubscription;
- late final AnyPayFlow _anyPayFlow = AnyPayFlow(
- anyPayService: widget.anyPayService,
- sendViewModel: widget.sendViewModel,
- authService: widget.authService,
- walletSwitcherViewModel: widget.walletSwitcherViewModel,
- );
+ late final AnyPayFlow _anyPayFlow;
ContactRecord? newContactAddress;
bool _justHandledPasteButton = false;
@@ -228,6 +223,12 @@ class _NewSendPageState extends State<NewSendPage> {
@override
void initState() {
super.initState();
+ _anyPayFlow = AnyPayFlow(
+ anyPayService: widget.anyPayService,
+ sendViewModel: widget.sendViewModel,
+ authService: widget.authService,
+ walletSwitcherViewModel: widget.walletSwitcherViewModel,
+ );
_addInputControllers();
_disposers.add(
diff --git a/lib/reactions/wallet_utils.dart b/lib/reactions/wallet_utils.dart
index dc2ed1a..2e94fa9 100644
--- a/lib/reactions/wallet_utils.dart
+++ b/lib/reactions/wallet_utils.dart
@@ -32,6 +32,7 @@ bool isElectrumWallet(WalletType walletType) {
case WalletType.bitcoin:
case WalletType.litecoin:
case WalletType.bitcoinCash:
+ case WalletType.dogecoin:
return true;
default:
return false;
diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart
index f699640..f845cf8 100644
--- a/lib/store/settings_store.dart
+++ b/lib/store/settings_store.dart
@@ -5,6 +5,7 @@ import 'dart:io';
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/dogecoin/dogecoin.dart';
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cake_wallet/di.dart';
@@ -168,6 +169,7 @@ abstract class SettingsStoreBase with Store {
TransactionPriority? initialZanoTransactionPriority,
TransactionPriority? initialDecredTransactionPriority,
TransactionPriority? initialZcashTransactionPriority,
+ TransactionPriority? initialDogecoinTransactionPriority,
Country? initialCakePayCountry})
: nodes = ObservableMap<WalletType, Node>.of(nodes),
powNodes = ObservableMap<WalletType, Node>.of(powNodes),
@@ -273,6 +275,9 @@ abstract class SettingsStoreBase with Store {
if (initialZcashTransactionPriority != null) {
priority[WalletType.zcash] = initialZcashTransactionPriority;
}
+ if (initialDogecoinTransactionPriority != null) {
+ priority[WalletType.dogecoin] = initialDogecoinTransactionPriority;
+ }
if (initialCakePayCountry != null) {
selectedCakePayCountry = initialCakePayCountry;
@@ -345,6 +350,9 @@ abstract class SettingsStoreBase with Store {
case WalletType.zcash:
key = PreferencesKey.zcashTransactionPriority;
break;
+ case WalletType.dogecoin:
+ key = PreferencesKey.dogecoinTransactionPriority;
+ break;
default:
key = null;
}
@@ -1194,6 +1202,7 @@ abstract class SettingsStoreBase with Store {
TransactionPriority? zanoTransactionPriority;
TransactionPriority? decredTransactionPriority;
TransactionPriority? zcashTransactionPriority;
+ TransactionPriority? dogecoinTransactionPriority;
if (sharedPreferences.getInt(PreferencesKey.havenTransactionPriority) != null) {
havenTransactionPriority = monero?.deserializeMoneroTransactionPriority(
@@ -1241,6 +1250,10 @@ abstract class SettingsStoreBase with Store {
zcashTransactionPriority = zcash?.deserializeZcashTransactionPriority(
raw: sharedPreferences.getInt(PreferencesKey.zcashTransactionPriority)!);
}
+ if (sharedPreferences.getInt(PreferencesKey.dogecoinTransactionPriority) != null) {
+ dogecoinTransactionPriority = dogecoin?.deserializeDogeCoinTransactionPriority(
+ sharedPreferences.getInt(PreferencesKey.dogecoinTransactionPriority)!);
+ }
moneroTransactionPriority ??= monero?.getDefaultTransactionPriority();
bitcoinTransactionPriority ??= bitcoin?.getMediumTransactionPriority();
@@ -1256,6 +1269,7 @@ abstract class SettingsStoreBase with Store {
bscTransactionPriority ??= evm?.getDefaultTransactionPriority();
zanoTransactionPriority ??= zano?.getDefaultTransactionPriority();
zcashTransactionPriority ??= zcash?.getDefaultTransactionPriority();
+ dogecoinTransactionPriority ??= dogecoin?.getDefaultTransactionPriority();
final currentBalanceDisplayMode = BalanceDisplayMode.deserialize(
raw: sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey)!);
@@ -1744,6 +1758,7 @@ abstract class SettingsStoreBase with Store {
initialBitcoinCashTransactionPriority: bitcoinCashTransactionPriority,
initialDecredTransactionPriority: decredTransactionPriority,
initialZcashTransactionPriority: zcashTransactionPriority,
+ initialDogecoinTransactionPriority: dogecoinTransactionPriority,
initialShouldRequireTOTP2FAForAccessingWallet: shouldRequireTOTP2FAForAccessingWallet,
initialShouldRequireTOTP2FAForSendsToContact: shouldRequireTOTP2FAForSendsToContact,
initialShouldRequireTOTP2FAForSendsToNonContact: shouldRequireTOTP2FAForSendsToNonContact,
@@ -1847,6 +1862,11 @@ abstract class SettingsStoreBase with Store {
priority[WalletType.zcash] = zcash!.deserializeZcashTransactionPriority(
raw: sharedPreferences.getInt(PreferencesKey.zcashTransactionPriority)!);
}
+ if (dogecoin != null &&
+ sharedPreferences.getInt(PreferencesKey.dogecoinTransactionPriority) != null) {
+ priority[WalletType.dogecoin] = dogecoin!.deserializeDogeCoinTransactionPriority(
+ sharedPreferences.getInt(PreferencesKey.dogecoinTransactionPriority)!);
+ }
final generateSubaddresses =
sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey);
diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart
index 670bc5a..df85d0c 100644
--- a/lib/view_model/send/send_view_model.dart
+++ b/lib/view_model/send/send_view_model.dart
@@ -167,9 +167,10 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
bool get isEVMWallet => isEVMCompatibleChain(walletType);
- @action
CryptoCurrency _outputCryptoCurrencyHandler([CryptoCurrency? override]) {
- if (override != null && override != selectedCryptoCurrency) selectedCryptoCurrency = override;
+ if (override != null && override != selectedCryptoCurrency) {
+ runInAction(() => selectedCryptoCurrency = override);
+ }
return selectedCryptoCurrency;
}
Why this scored 21/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.