CW-855-Transactions-not-cleared-correctly-when-switching-wallets (#1973)

* DashboardViewModel is now a lazy Singleton * DashboardViewModel is now a lazy Singleton * Remove debug print

Konstantin Ullrich committed Jan 24, 2025 at 19:01 UTC 066eec2b26b50578be69be1c16229ac3155f3278
3 files changed +32 -146
lib/di.dart
+1 -1
@@ -494,7 +494,7 @@ Future<void> setup({
494 settingsStore: getIt.get<SettingsStore>(),
495 fiatConvertationStore: getIt.get<FiatConversionStore>()));
496
497 - getIt.registerFactory(() => DashboardViewModel(
497 + getIt.registerLazySingleton(() => DashboardViewModel(
498 balanceViewModel: getIt.get<BalanceViewModel>(),
499 appStore: getIt.get<AppStore>(),
500 tradesStore: getIt.get<TradesStore>(),
lib/store/app_store.dart
+2
@@ -3,6 +3,7 @@ import 'package:cake_wallet/di.dart';
3 import 'package:cake_wallet/entities/preferences_key.dart';
4 import 'package:cake_wallet/reactions/wallet_connect.dart';
5 import 'package:cake_wallet/utils/exception_handler.dart';
6 +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
7 import 'package:cw_core/transaction_info.dart';
8 import 'package:cw_core/wallet_type.dart';
9 import 'package:mobx/mobx.dart';
@@ -54,5 +55,6 @@ abstract class AppStoreBase with Store {
55 getIt
56 .get<SharedPreferences>()
57 .setInt(PreferencesKey.currentWalletType, serializeToInt(wallet.type));
58 + getIt.get<DashboardViewModel>().onWalletChange(wallet);
59 }
60 }
lib/view_model/dashboard/dashboard_view_model.dart
+29 -145
@@ -152,128 +152,18 @@ abstract class DashboardViewModelBase with Store {
152 type = appStore.wallet!.type,
153 transactions = ObservableList<TransactionListItem>(),
154 wallet = appStore.wallet! {
155 - name = wallet.name;
156 - type = wallet.type;
155 isShowFirstYatIntroduction = false;
156 isShowSecondYatIntroduction = false;
157 isShowThirdYatIntroduction = false;
158 updateActions();
159
162 - final _wallet = wallet;
163 -
164 - if (_wallet.type == WalletType.monero) {
165 - subname = monero!.getCurrentAccount(_wallet).label;
166 -
167 - _onMoneroAccountChangeReaction = reaction(
168 - (_) => monero!.getMoneroWalletDetails(wallet).account,
169 - (Account account) => _onMoneroAccountChange(_wallet));
170 -
171 - _onMoneroBalanceChangeReaction = reaction(
172 - (_) => monero!.getMoneroWalletDetails(wallet).balance,
173 - (MoneroBalance balance) => _onMoneroTransactionsUpdate(_wallet));
174 -
175 - final _accountTransactions = _wallet.transactionHistory.transactions.values
176 - .where((tx) =>
177 - monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
178 - .toList();
179 -
180 - final sortedTransactions = [..._accountTransactions];
181 - sortedTransactions.sort((a, b) => a.date.compareTo(b.date));
182 -
183 - transactions = ObservableList.of(
184 - sortedTransactions.map(
185 - (transaction) => TransactionListItem(
186 - transaction: transaction,
187 - balanceViewModel: balanceViewModel,
188 - settingsStore: appStore.settingsStore,
189 - key: ValueKey('monero_transaction_history_item_${transaction.id}_key'),
190 - ),
191 - ),
192 - );
193 - } else if (_wallet.type == WalletType.wownero) {
194 - subname = wow.wownero!.getCurrentAccount(_wallet).label;
195 -
196 - _onMoneroAccountChangeReaction = reaction(
197 - (_) => wow.wownero!.getWowneroWalletDetails(wallet).account,
198 - (wow.Account account) => _onMoneroAccountChange(_wallet));
199 -
200 - _onMoneroBalanceChangeReaction = reaction(
201 - (_) => wow.wownero!.getWowneroWalletDetails(wallet).balance,
202 - (wow.WowneroBalance balance) => _onMoneroTransactionsUpdate(_wallet));
203 -
204 - final _accountTransactions = _wallet.transactionHistory.transactions.values
205 - .where((tx) =>
206 - wow.wownero!.getTransactionInfoAccountId(tx) ==
207 - wow.wownero!.getCurrentAccount(wallet).id)
208 - .toList();
209 -
210 - final sortedTransactions = [..._accountTransactions];
211 - sortedTransactions.sort((a, b) => a.date.compareTo(b.date));
212 -
213 - transactions = ObservableList.of(
214 - sortedTransactions.map(
215 - (transaction) => TransactionListItem(
216 - transaction: transaction,
217 - balanceViewModel: balanceViewModel,
218 - settingsStore: appStore.settingsStore,
219 - key: ValueKey('wownero_transaction_history_item_${transaction.id}_key'),
220 - ),
221 - ),
222 - );
223 - } else {
224 - final sortedTransactions = [...wallet.transactionHistory.transactions.values];
225 - sortedTransactions.sort((a, b) => a.date.compareTo(b.date));
226 -
227 - transactions = ObservableList.of(
228 - sortedTransactions.map(
229 - (transaction) => TransactionListItem(
230 - transaction: transaction,
231 - balanceViewModel: balanceViewModel,
232 - settingsStore: appStore.settingsStore,
233 - key: ValueKey('${_wallet.type.name}_transaction_history_item_${transaction.id}_key'),
234 - ),
235 - ),
236 - );
237 - }
160 + onWalletChange(wallet);
161
162 // TODO: nano sub-account generation is disabled:
163 // if (_wallet.type == WalletType.nano || _wallet.type == WalletType.banano) {
164 // subname = nano!.getCurrentAccount(_wallet).label;
165 // }
166
244 - reaction((_) => appStore.wallet, (wallet) {
245 - _onWalletChange(wallet);
246 - _checkMweb();
247 - });
248 -
249 - connectMapToListWithTransform(
250 - appStore.wallet!.transactionHistory.transactions,
251 - transactions,
252 - (TransactionInfo? transaction) => TransactionListItem(
253 - transaction: transaction!,
254 - balanceViewModel: balanceViewModel,
255 - settingsStore: appStore.settingsStore,
256 - key: ValueKey(
257 - '${_wallet.type.name}_transaction_history_item_${transaction.id}_key',
258 - ),
259 - ), filter: (TransactionInfo? transaction) {
260 - if (transaction == null) {
261 - return false;
262 - }
263 -
264 - final wallet = _wallet;
265 - if (wallet.type == WalletType.monero) {
266 - return monero!.getTransactionInfoAccountId(transaction) ==
267 - monero!.getCurrentAccount(wallet).id;
268 - }
269 - if (wallet.type == WalletType.wownero) {
270 - return wow.wownero!.getTransactionInfoAccountId(transaction) ==
271 - wow.wownero!.getCurrentAccount(wallet).id;
272 - }
273 -
274 - return true;
275 - });
276 -
167 if (hasSilentPayments) {
168 silentPaymentsScanningActive = bitcoin!.getScanningActive(wallet);
169
@@ -283,9 +173,7 @@ abstract class DashboardViewModelBase with Store {
173 }
174
175 _checkMweb();
286 - reaction((_) => settingsStore.mwebAlwaysScan, (bool value) {
287 - _checkMweb();
288 - });
176 + reaction((_) => settingsStore.mwebAlwaysScan, (bool value) => _checkMweb());
177 }
178
179 void _checkMweb() {
@@ -383,12 +271,13 @@ abstract class DashboardViewModelBase with Store {
271 bool get isTestnet => wallet.type == WalletType.bitcoin && bitcoin!.isTestnet(wallet);
272
273 @computed
386 - bool get hasRescan =>
387 - wallet.type == WalletType.bitcoin ||
388 - wallet.type == WalletType.monero ||
389 - wallet.type == WalletType.litecoin ||
390 - wallet.type == WalletType.wownero ||
391 - wallet.type == WalletType.haven;
274 + bool get hasRescan => [
275 + WalletType.bitcoin,
276 + WalletType.monero,
277 + WalletType.litecoin,
278 + WalletType.wownero,
279 + WalletType.haven
280 + ].contains(wallet.type);
281
282 @computed
283 bool get isMoneroViewOnly {
@@ -545,30 +434,25 @@ abstract class DashboardViewModelBase with Store {
434 ReactionDisposer? _onMoneroBalanceChangeReaction;
435
436 @computed
548 - bool get hasPowNodes => wallet.type == WalletType.nano || wallet.type == WalletType.banano;
437 + bool get hasPowNodes => [WalletType.nano, WalletType.banano].contains(wallet.type);
438
439 @computed
440 bool get hasSignMessages {
552 - if (wallet.isHardwareWallet) {
553 - return false;
554 - }
555 - switch (wallet.type) {
556 - case WalletType.monero:
557 - case WalletType.litecoin:
558 - case WalletType.bitcoin:
559 - case WalletType.bitcoinCash:
560 - case WalletType.ethereum:
561 - case WalletType.polygon:
562 - case WalletType.solana:
563 - case WalletType.nano:
564 - case WalletType.banano:
565 - case WalletType.tron:
566 - case WalletType.wownero:
567 - return true;
568 - case WalletType.haven:
569 - case WalletType.none:
570 - return false;
571 - }
441 + if (wallet.isHardwareWallet) return false;
442 +
443 + return [
444 + WalletType.monero,
445 + WalletType.litecoin,
446 + WalletType.bitcoin,
447 + WalletType.bitcoinCash,
448 + WalletType.ethereum,
449 + WalletType.polygon,
450 + WalletType.solana,
451 + WalletType.nano,
452 + WalletType.banano,
453 + WalletType.tron,
454 + WalletType.wownero
455 + ].contains(wallet.type);
456 }
457
458 bool get showRepWarning {
@@ -593,11 +477,11 @@ abstract class DashboardViewModelBase with Store {
477 }
478
479 @action
596 - void _onWalletChange(
480 + void onWalletChange(
481 WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>? wallet) {
598 - if (wallet == null) {
599 - return;
600 - }
482 + if (wallet == null) return;
483 +
484 + _checkMweb();
485
486 this.wallet = wallet;
487 type = wallet.type;