Make SP scanning, wallet-specific (#2383)

Omar Hatem committed Jul 12, 2025 at 19:58 UTC ab5849c57df2af3e8f23ba4b4502aa45c3720eee
13 files changed +34 -50
cw_bitcoin/lib/bitcoin_wallet.dart
+1 -2
@@ -168,7 +168,6 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
168 required Box<PayjoinSession> payjoinBox,
169 required String password,
170 required EncryptionFileUtils encryptionFileUtils,
171 - required bool alwaysScan,
171 }) async {
172 final network = walletInfo.network != null
173 ? BasedUtxoNetwork.fromName(walletInfo.network!)
@@ -252,7 +251,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
251 initialChangeAddressIndex: snp?.changeAddressIndex,
252 addressPageType: snp?.addressPageType,
253 networkParam: network,
255 - alwaysScan: alwaysScan,
254 + alwaysScan: snp?.alwaysScan,
255 payjoinBox: payjoinBox);
256 }
257
cw_bitcoin/lib/bitcoin_wallet_service.dart
+1 -5
@@ -23,12 +23,11 @@ class BitcoinWalletService extends WalletService<
23 BitcoinRestoreWalletFromWIFCredentials,
24 BitcoinRestoreWalletFromHardware> {
25 BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource,
26 - this.payjoinSessionSource, this.alwaysScan, this.isDirect);
26 + this.payjoinSessionSource, this.isDirect);
27
28 final Box<WalletInfo> walletInfoSource;
29 final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
30 final Box<PayjoinSession> payjoinSessionSource;
31 - final bool alwaysScan;
31 final bool isDirect;
32
33 @override
@@ -84,7 +83,6 @@ class BitcoinWalletService extends WalletService<
83 walletInfo: walletInfo,
84 unspentCoinsInfo: unspentCoinsInfoSource,
85 payjoinBox: payjoinSessionSource,
87 - alwaysScan: alwaysScan,
86 encryptionFileUtils: encryptionFileUtilsFor(isDirect),
87 );
88 await wallet.init();
@@ -98,7 +96,6 @@ class BitcoinWalletService extends WalletService<
96 walletInfo: walletInfo,
97 unspentCoinsInfo: unspentCoinsInfoSource,
98 payjoinBox: payjoinSessionSource,
101 - alwaysScan: alwaysScan,
99 encryptionFileUtils: encryptionFileUtilsFor(isDirect),
100 );
101 await wallet.init();
@@ -133,7 +130,6 @@ class BitcoinWalletService extends WalletService<
130 walletInfo: currentWalletInfo,
131 unspentCoinsInfo: unspentCoinsInfoSource,
132 payjoinBox: payjoinSessionSource,
136 - alwaysScan: alwaysScan,
133 encryptionFileUtils: encryptionFileUtilsFor(isDirect),
134 );
135
cw_bitcoin/lib/electrum_wallet.dart
+1
@@ -150,6 +150,7 @@ abstract class ElectrumWalletBase
150 }
151 }
152
153 + @observable
154 bool? alwaysScan;
155
156 final Bip32Slip10Secp256k1 accountHD;
cw_bitcoin/lib/litecoin_wallet.dart
-1
@@ -210,7 +210,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
210 required WalletInfo walletInfo,
211 required Box<UnspentCoinsInfo> unspentCoinsInfo,
212 required String password,
213 - required bool alwaysScan,
213 required EncryptionFileUtils encryptionFileUtils,
214 }) async {
215 final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
cw_bitcoin/lib/litecoin_wallet_service.dart
+1 -5
@@ -23,11 +23,10 @@ class LitecoinWalletService extends WalletService<
23 BitcoinRestoreWalletFromWIFCredentials,
24 BitcoinRestoreWalletFromHardware> {
25 LitecoinWalletService(
26 - this.walletInfoSource, this.unspentCoinsInfoSource, this.alwaysScan, this.isDirect);
26 + this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect);
27
28 final Box<WalletInfo> walletInfoSource;
29 final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
30 - final bool alwaysScan;
30 final bool isDirect;
31
32 @override
@@ -78,7 +77,6 @@ class LitecoinWalletService extends WalletService<
77 name: name,
78 walletInfo: walletInfo,
79 unspentCoinsInfo: unspentCoinsInfoSource,
81 - alwaysScan: alwaysScan,
80 encryptionFileUtils: encryptionFileUtilsFor(isDirect),
81 );
82 await wallet.init();
@@ -91,7 +89,6 @@ class LitecoinWalletService extends WalletService<
89 name: name,
90 walletInfo: walletInfo,
91 unspentCoinsInfo: unspentCoinsInfoSource,
94 - alwaysScan: alwaysScan,
92 encryptionFileUtils: encryptionFileUtilsFor(isDirect),
93 );
94 await wallet.init();
@@ -146,7 +143,6 @@ class LitecoinWalletService extends WalletService<
143 name: currentName,
144 walletInfo: currentWalletInfo,
145 unspentCoinsInfo: unspentCoinsInfoSource,
149 - alwaysScan: alwaysScan,
146 encryptionFileUtils: encryptionFileUtilsFor(isDirect),
147 );
148
lib/bitcoin/cw_bitcoin.dart
+12 -4
@@ -231,15 +231,14 @@ class CWBitcoin extends Bitcoin {
231 Box<WalletInfo> walletInfoSource,
232 Box<UnspentCoinsInfo> unspentCoinSource,
233 Box<PayjoinSession> payjoinSessionSource,
234 - bool alwaysScan,
234 bool isDirect) {
235 return BitcoinWalletService(walletInfoSource, unspentCoinSource,
237 - payjoinSessionSource, alwaysScan, isDirect);
236 + payjoinSessionSource, isDirect);
237 }
238
239 WalletService createLitecoinWalletService(Box<WalletInfo> walletInfoSource,
241 - Box<UnspentCoinsInfo> unspentCoinSource, bool alwaysScan, bool isDirect) {
242 - return LitecoinWalletService(walletInfoSource, unspentCoinSource, alwaysScan, isDirect);
240 + Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect) {
241 + return LitecoinWalletService(walletInfoSource, unspentCoinSource, isDirect);
242 }
243
244 @override
@@ -580,6 +579,15 @@ class CWBitcoin extends Bitcoin {
579 bitcoinWallet.setSilentPaymentsScanning(active);
580 }
581
582 + Future<void> setIsAlwaysScanningSP(Object wallet, bool active) async {
583 + final bitcoinWallet = wallet as ElectrumWallet;
584 + bitcoinWallet.alwaysScan = active;
585 + bitcoinWallet.save();
586 + }
587 +
588 + @computed
589 + bool getIsAlwaysScanningSP(Object wallet) => (wallet as ElectrumWallet).alwaysScan ?? false;
590 +
591 @override
592 bool isTestnet(Object wallet) {
593 final bitcoinWallet = wallet as ElectrumWallet;
lib/core/address_validator.dart
+1 -1
@@ -28,7 +28,7 @@ class AddressValidator extends TextValidator {
28 pattern: getPattern(type, isTestnet: isTestnet),
29 length: getLength(type));
30
31 - static String getPattern(CryptoCurrency type, {required bool isTestnet}) {
31 + static String getPattern(CryptoCurrency type, {bool isTestnet = false}) {
32 var pattern = "";
33 if (type is Erc20Token) {
34 pattern = '0x[0-9a-zA-Z]+';
lib/di.dart
-3
@@ -76,7 +76,6 @@ import 'package:cake_wallet/entities/qr_view_data.dart';
76 import 'package:cake_wallet/entities/template.dart';
77 import 'package:cake_wallet/entities/transaction_description.dart';
78 import 'package:cake_wallet/ethereum/ethereum.dart';
79 -import 'package:cake_wallet/cake_pay/src/models/cake_pay_card.dart';
79 import 'package:cake_wallet/exchange/exchange_template.dart';
80 import 'package:cake_wallet/exchange/trade.dart';
81 import 'package:cake_wallet/monero/monero.dart';
@@ -1119,14 +1118,12 @@ Future<void> setup({
1118 _walletInfoSource,
1119 _unspentCoinsInfoSource,
1120 _payjoinSessionSource,
1122 - getIt.get<SettingsStore>().silentPaymentsAlwaysScan,
1121 SettingsStoreBase.walletPasswordDirectInput,
1122 );
1123 case WalletType.litecoin:
1124 return bitcoin!.createLitecoinWalletService(
1125 _walletInfoSource,
1126 _unspentCoinsInfoSource,
1129 - getIt.get<SettingsStore>().mwebAlwaysScan,
1127 SettingsStoreBase.walletPasswordDirectInput,
1128 );
1129 case WalletType.ethereum:
lib/entities/preferences_key.dart
-1
@@ -54,7 +54,6 @@ class PreferencesKey {
54 static const decredTransactionPriority = 'current_fee_priority_decred';
55 static const customBitcoinFeeRate = 'custom_electrum_fee_rate';
56 static const silentPaymentsCardDisplay = 'silentPaymentsCardDisplay';
57 - static const silentPaymentsAlwaysScan = 'silentPaymentsAlwaysScan';
57 static const mwebCardDisplay = 'mwebCardDisplay';
58 static const mwebEnabled = 'mwebEnabled';
59 static const hasEnabledMwebBefore = 'hasEnabledMwebBefore';
lib/store/settings_store.dart
-14
@@ -123,7 +123,6 @@ abstract class SettingsStoreBase with Store {
123 required this.showPayjoinCard,
124 required this.customBitcoinFeeRate,
125 required this.silentPaymentsCardDisplay,
126 - required this.silentPaymentsAlwaysScan,
126 required this.mwebAlwaysScan,
127 required this.mwebCardDisplay,
128 required this.mwebEnabled,
@@ -592,11 +591,6 @@ abstract class SettingsStoreBase with Store {
591 PreferencesKey.silentPaymentsCardDisplay, silentPaymentsCardDisplay);
592 });
593
595 - reaction(
596 - (_) => silentPaymentsAlwaysScan,
597 - (bool silentPaymentsAlwaysScan) => _sharedPreferences.setBool(
598 - PreferencesKey.silentPaymentsAlwaysScan, silentPaymentsAlwaysScan));
599 -
594 reaction(
595 (_) => mwebAlwaysScan,
596 (bool mwebAlwaysScan) =>
@@ -850,9 +844,6 @@ abstract class SettingsStoreBase with Store {
844 @observable
845 bool silentPaymentsCardDisplay;
846
853 - @observable
854 - bool silentPaymentsAlwaysScan;
855 -
847 @observable
848 bool mwebAlwaysScan;
849
@@ -1036,8 +1027,6 @@ abstract class SettingsStoreBase with Store {
1027 final customBitcoinFeeRate = sharedPreferences.getInt(PreferencesKey.customBitcoinFeeRate) ?? 1;
1028 final silentPaymentsCardDisplay =
1029 sharedPreferences.getBool(PreferencesKey.silentPaymentsCardDisplay) ?? true;
1039 - final silentPaymentsAlwaysScan =
1040 - sharedPreferences.getBool(PreferencesKey.silentPaymentsAlwaysScan) ?? false;
1030 final mwebAlwaysScan = sharedPreferences.getBool(PreferencesKey.mwebAlwaysScan) ?? false;
1031 final mwebCardDisplay = sharedPreferences.getBool(PreferencesKey.mwebCardDisplay) ?? true;
1032 final mwebEnabled = sharedPreferences.getBool(PreferencesKey.mwebEnabled) ?? false;
@@ -1341,7 +1330,6 @@ abstract class SettingsStoreBase with Store {
1330 showPayjoinCard: showPayjoinCard,
1331 customBitcoinFeeRate: customBitcoinFeeRate,
1332 silentPaymentsCardDisplay: silentPaymentsCardDisplay,
1344 - silentPaymentsAlwaysScan: silentPaymentsAlwaysScan,
1333 mwebAlwaysScan: mwebAlwaysScan,
1334 mwebCardDisplay: mwebCardDisplay,
1335 mwebEnabled: mwebEnabled,
@@ -1525,8 +1513,6 @@ abstract class SettingsStoreBase with Store {
1513 customBitcoinFeeRate = sharedPreferences.getInt(PreferencesKey.customBitcoinFeeRate) ?? 1;
1514 silentPaymentsCardDisplay =
1515 sharedPreferences.getBool(PreferencesKey.silentPaymentsCardDisplay) ?? true;
1528 - silentPaymentsAlwaysScan =
1529 - sharedPreferences.getBool(PreferencesKey.silentPaymentsAlwaysScan) ?? false;
1516 mwebAlwaysScan = sharedPreferences.getBool(PreferencesKey.mwebAlwaysScan) ?? false;
1517 mwebCardDisplay = sharedPreferences.getBool(PreferencesKey.mwebCardDisplay) ?? true;
1518 mwebEnabled = sharedPreferences.getBool(PreferencesKey.mwebEnabled) ?? false;
lib/view_model/buy/buy_sell_view_model.dart
+11 -10
@@ -12,7 +12,6 @@ import 'package:cake_wallet/entities/provider_types.dart';
12 import 'package:cake_wallet/generated/i18n.dart';
13 import 'package:cake_wallet/routes.dart';
14 import 'package:cake_wallet/store/app_store.dart';
15 -import 'package:cake_wallet/themes/core/material_base_theme.dart';
15 import 'package:cw_core/crypto_currency.dart';
16 import 'package:flutter/cupertino.dart';
17 import 'package:intl/intl.dart';
@@ -89,7 +88,7 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S
88 return isBuyAction ? formattedFiatAmount : formattedCryptoAmount;
89 }
90
92 - AppStore _appStore;
91 + final AppStore _appStore;
92
93 Quote? bestRateQuote;
94
@@ -315,14 +314,16 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S
314 ...outOfLimitQuotes,
315 ]);
316
318 - await Navigator.of(context).pushNamed(
319 - Routes.buyOptionsPage,
320 - arguments: [
321 - updatedQuoteOptions,
322 - changeOption,
323 - launchTrade,
324 - ],
325 - ).then((value) => calculateBestRate());
317 + if (context.mounted) {
318 + await Navigator.of(context).pushNamed(
319 + Routes.buyOptionsPage,
320 + arguments: [
321 + updatedQuoteOptions,
322 + changeOption,
323 + launchTrade,
324 + ],
325 + ).then((value) => calculateBestRate());
326 + }
327 }
328
329 void _onPairChange() {
lib/view_model/settings/silent_payments_settings_view_model.dart
+2 -2
@@ -18,7 +18,7 @@ abstract class SilentPaymentsSettingsViewModelBase with Store {
18 bool get silentPaymentsCardDisplay => _settingsStore.silentPaymentsCardDisplay;
19
20 @computed
21 - bool get silentPaymentsAlwaysScan => _settingsStore.silentPaymentsAlwaysScan;
21 + bool get silentPaymentsAlwaysScan => bitcoin!.getIsAlwaysScanningSP(_wallet);
22
23 @action
24 void setSilentPaymentsCardDisplay(bool value) {
@@ -27,7 +27,7 @@ abstract class SilentPaymentsSettingsViewModelBase with Store {
27
28 @action
29 void setSilentPaymentsAlwaysScan(bool value) {
30 - _settingsStore.silentPaymentsAlwaysScan = value;
30 + bitcoin!.setIsAlwaysScanningSP(_wallet, value);
31 if (value) bitcoin!.setScanningActive(_wallet, true);
32 }
33 }
tool/configure.dart
+4 -2
@@ -192,8 +192,8 @@ abstract class Bitcoin {
192 List<Unspent> getUnspents(Object wallet, {UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any});
193 Future<void> updateUnspents(Object wallet);
194 WalletService createBitcoinWalletService(
195 - Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource, Box<PayjoinSession> payjoinSessionSource, bool alwaysScan, bool isDirect);
196 - WalletService createLitecoinWalletService(Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource, bool alwaysScan, bool isDirect);
195 + Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource, Box<PayjoinSession> payjoinSessionSource, bool isDirect);
196 + WalletService createLitecoinWalletService(Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect);
197 TransactionPriority getBitcoinTransactionPriorityMedium();
198 TransactionPriority getBitcoinTransactionPriorityCustom();
199 TransactionPriority getLitecoinTransactionPriorityMedium();
@@ -216,6 +216,8 @@ abstract class Bitcoin {
216 bool hasTaprootInput(PendingTransaction pendingTransaction);
217 bool getScanningActive(Object wallet);
218 Future<void> setScanningActive(Object wallet, bool active);
219 + Future<void> setIsAlwaysScanningSP(Object wallet, bool active);
220 + bool getIsAlwaysScanningSP(Object wallet);
221 bool isTestnet(Object wallet);
222
223 Future<PendingTransaction> replaceByFee(Object wallet, String transactionHash, String fee);