dev
dart 175 lines 5.4 KB
Raw
1 import 'dart:async';
2
3 import 'package:cake_wallet/core/wallet_loading_service.dart';
4 import 'package:cake_wallet/entities/wallet_group.dart';
5 import 'package:cake_wallet/entities/wallet_manager.dart';
6 import 'package:cake_wallet/reactions/wallet_utils.dart';
7 import 'package:cake_wallet/store/app_store.dart';
8 import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
9 import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
10 import 'package:cake_wallet/wallet_types.g.dart';
11 import 'package:cw_core/wallet_info.dart';
12 import 'package:cw_core/wallet_type.dart';
13 import 'package:mobx/mobx.dart';
14
15 part 'wallet_groups_display_view_model.g.dart';
16
17 class WalletGroupsDisplayViewModel = WalletGroupsDisplayViewModelBase
18 with _$WalletGroupsDisplayViewModel;
19
20 abstract class WalletGroupsDisplayViewModelBase with Store {
21 WalletGroupsDisplayViewModelBase(
22 this._appStore,
23 this._walletLoadingService,
24 this._walletManager,
25 this.walletListViewModel, {
26 required this.type,
27 }) : isFetchingMnemonic = false {
28 reaction((_) => _appStore.wallet, (_) => unawaited(updateWalletInfoSourceList()));
29 unawaited(updateWalletInfoSourceList());
30 }
31
32 final WalletType type;
33 final AppStore _appStore;
34 final WalletManager _walletManager;
35 final WalletLoadingService _walletLoadingService;
36 final WalletListViewModel walletListViewModel;
37
38 @observable
39 ObservableList<WalletGroup> multiWalletGroups = ObservableList<WalletGroup>();
40
41 @observable
42 ObservableList<WalletInfo> singleWalletsList = ObservableList<WalletInfo>();
43
44 @observable
45 WalletGroup? selectedWalletGroup;
46
47 @observable
48 WalletInfo? selectedSingleWallet;
49
50 @observable
51 bool isFetchingMnemonic;
52
53 @computed
54 bool get hasNoFilteredWallet {
55 return singleWalletsList.isEmpty && multiWalletGroups.isEmpty;
56 }
57
58 @action
59 Future<String?> getSelectedWalletMnemonic() async {
60 WalletListItem walletToUse;
61
62 bool isGroupSelected = selectedWalletGroup != null;
63
64 if (isGroupSelected) {
65 walletToUse = convertWalletInfoToWalletListItem(selectedWalletGroup!.wallets.first);
66 } else {
67 walletToUse = convertWalletInfoToWalletListItem(selectedSingleWallet!);
68 }
69
70 try {
71 isFetchingMnemonic = true;
72 final wallet = await _walletLoadingService.load(
73 walletToUse.type,
74 walletToUse.name,
75 );
76
77 return wallet.seed;
78 } catch (e) {
79 return null;
80 } finally {
81 isFetchingMnemonic = false;
82 }
83 }
84
85 @action
86 void selectWalletGroup(WalletGroup walletGroup) {
87 selectedWalletGroup = walletGroup;
88 selectedSingleWallet = null;
89 }
90
91 @action
92 void selectSingleWallet(WalletInfo singleWallet) {
93 selectedSingleWallet = singleWallet;
94 selectedWalletGroup = null;
95 }
96
97 @action
98 Future<void> updateWalletInfoSourceList() async {
99 List<WalletGroup> wallets = [];
100
101 multiWalletGroups.clear();
102 singleWalletsList.clear();
103
104 await _walletManager.updateWalletGroups();
105
106 final walletGroups = List<WalletGroup>.from(_walletManager.walletGroups);
107
108 // Iterate through the wallet groups to filter and categorize wallets
109 for (var group in walletGroups) {
110 // Handle group wallet filtering
111 bool shouldExcludeGroup = false;
112 for (final wallet in group.wallets) {
113 // Check for non-BIP39 wallet types
114 bool isNonBIP39Wallet = !isBIP39Wallet(wallet.type);
115
116 // Check for nano derivation type
117 final di = await wallet.getDerivationInfo();
118 bool isNanoDerivationType =
119 wallet.type == WalletType.nano && di.derivationType == DerivationType.nano;
120
121 // Check for electrum derivation type
122 bool isElectrumDerivationType =
123 (wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin) &&
124 di.derivationType == DerivationType.electrum;
125
126 // Check that selected wallet type is not present already in group
127 bool isSameTypeAsSelectedWallet = wallet.type == type;
128
129 bool isNonSeedWallet = wallet.isNonSeedWallet;
130
131 bool isNotMoneroBip39Wallet =
132 wallet.type == WalletType.monero && di.derivationType != DerivationType.bip39;
133
134 bool isNotDecredBip39Wallet = wallet.type == WalletType.decred &&
135 di.derivationType != DerivationType.bip39 &&
136 di.derivationType != DerivationType.unknown;
137
138 // Exclude if any of these conditions are true
139 shouldExcludeGroup = shouldExcludeGroup ||
140 isNonBIP39Wallet ||
141 isNanoDerivationType ||
142 isElectrumDerivationType ||
143 isSameTypeAsSelectedWallet ||
144 isNonSeedWallet ||
145 isNotMoneroBip39Wallet ||
146 isNotDecredBip39Wallet;
147 }
148
149 if (shouldExcludeGroup) continue;
150
151 // If the group passes the filters, add it to the wallets list
152 wallets.add(group);
153 }
154
155 for (var group in wallets) {
156 if (group.wallets.length == 1) {
157 singleWalletsList.add(group.wallets.first);
158 } else {
159 multiWalletGroups.add(group);
160 }
161 }
162 }
163
164 WalletListItem convertWalletInfoToWalletListItem(WalletInfo info) {
165 return WalletListItem(
166 name: info.name,
167 type: info.type,
168 key: info.id,
169 isCurrent: info.name == _appStore.wallet?.name && info.type == _appStore.wallet?.type,
170 isEnabled: availableWalletTypes.contains(info.type),
171 isTestnet: info.network?.toLowerCase().contains('testnet') ?? false,
172 isHardware: info.isHardwareWallet,
173 );
174 }
175 }