Add the code to enable removing Haven wallets (#2222)

Omar Hatem committed Apr 23, 2025 at 12:19 UTC 698f0199d04166a855f706293b6a50529bac54a9
2 files changed +47 -315
lib/di.dart
+3 -1
@@ -33,6 +33,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart';
33 import 'package:cake_wallet/entities/hardware_wallet/require_hardware_wallet_connection.dart';
34 import 'package:cake_wallet/entities/parse_address_from_domain.dart';
35 import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
36 +import 'package:cake_wallet/haven/cw_haven.dart';
37 import 'package:cake_wallet/src/screens/dev/monero_background_sync.dart';
38 import 'package:cake_wallet/src/screens/dev/moneroc_call_profiler.dart';
39 import 'package:cake_wallet/src/screens/settings/background_sync_page.dart';
@@ -1115,8 +1116,9 @@ Future<void> setup({
1116 return zano!.createZanoWalletService(_walletInfoSource);
1117 case WalletType.decred:
1118 return decred!.createDecredWalletService(_walletInfoSource, _unspentCoinsInfoSource);
1118 - case WalletType.none:
1119 case WalletType.haven:
1120 + return HavenWalletService(_walletInfoSource);
1121 + case WalletType.none:
1122 throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService');
1123 }
1124 });
lib/haven/cw_haven.dart
+44 -314
@@ -1,348 +1,78 @@
1 -part of 'haven.dart';
1 +import 'dart:io';
2
3 -class CWHavenAccountList extends HavenAccountList {
4 - CWHavenAccountList(this._wallet);
3 +import 'package:cw_core/balance.dart';
4 +import 'package:cw_core/pathForWallet.dart';
5 +import 'package:cw_core/transaction_history.dart';
6 +import 'package:cw_core/transaction_info.dart';
7 +import 'package:cw_core/wallet_base.dart';
8 +import 'package:cw_core/wallet_credentials.dart';
9 +import 'package:cw_core/wallet_info.dart';
10 +import 'package:cw_core/wallet_service.dart';
11 +import 'package:cw_core/wallet_type.dart';
12 +import 'package:hive/hive.dart';
13
6 - final Object _wallet;
14 +class HavenWalletService extends WalletService {
15 + final Box<WalletInfo> walletInfoSource;
16
8 - @override
9 - @computed
10 - ObservableList<Account> get accounts {
11 - final havenWallet = _wallet as HavenWallet;
12 - final accounts = havenWallet.walletAddresses.accountList.accounts
13 - .map((acc) => Account(id: acc.id, label: acc.label))
14 - .toList();
15 - return ObservableList<Account>.of(accounts);
16 - }
17 -
18 - @override
19 - void update(Object wallet) {
20 - final havenWallet = wallet as HavenWallet;
21 - havenWallet.walletAddresses.accountList.update();
22 - }
23 -
24 - @override
25 - void refresh(Object wallet) {
26 - final havenWallet = wallet as HavenWallet;
27 - havenWallet.walletAddresses.accountList.refresh();
28 - }
29 -
30 - @override
31 - List<Account> getAll(Object wallet) {
32 - final havenWallet = wallet as HavenWallet;
33 - return havenWallet.walletAddresses.accountList
34 - .getAll()
35 - .map((acc) => Account(id: acc.id, label: acc.label))
36 - .toList();
37 - }
38 -
39 - @override
40 - Future<void> addAccount(Object wallet, {required String label}) async {
41 - final havenWallet = wallet as HavenWallet;
42 - await havenWallet.walletAddresses.accountList.addAccount(label: label);
43 - }
44 -
45 - @override
46 - Future<void> setLabelAccount(Object wallet,
47 - {required int accountIndex, required String label}) async {
48 - final havenWallet = wallet as HavenWallet;
49 - await havenWallet.walletAddresses.accountList
50 - .setLabelAccount(accountIndex: accountIndex, label: label);
51 - }
52 -}
53 -
54 -class CWHavenSubaddressList extends MoneroSubaddressList {
55 - CWHavenSubaddressList(this._wallet);
56 -
57 - final Object _wallet;
58 -
59 - @override
60 - @computed
61 - ObservableList<Subaddress> get subaddresses {
62 - final havenWallet = _wallet as HavenWallet;
63 - final subAddresses = havenWallet.walletAddresses.subaddressList.subaddresses
64 - .map((sub) => Subaddress(id: sub.id, address: sub.address, label: sub.label))
65 - .toList();
66 - return ObservableList<Subaddress>.of(subAddresses);
67 - }
68 -
69 - @override
70 - void update(Object wallet, {required int accountIndex}) {
71 - final havenWallet = wallet as HavenWallet;
72 - havenWallet.walletAddresses.subaddressList.update(accountIndex: accountIndex);
73 - }
74 -
75 - @override
76 - void refresh(Object wallet, {required int accountIndex}) {
77 - final havenWallet = wallet as HavenWallet;
78 - havenWallet.walletAddresses.subaddressList.refresh(accountIndex: accountIndex);
79 - }
80 -
81 - @override
82 - List<Subaddress> getAll(Object wallet) {
83 - final havenWallet = wallet as HavenWallet;
84 - return havenWallet.walletAddresses.subaddressList
85 - .getAll()
86 - .map((sub) => Subaddress(id: sub.id, label: sub.label, address: sub.address))
87 - .toList();
88 - }
89 -
90 - @override
91 - Future<void> addSubaddress(Object wallet,
92 - {required int accountIndex, required String label}) async {
93 - final havenWallet = wallet as HavenWallet;
94 - await havenWallet.walletAddresses.subaddressList
95 - .addSubaddress(accountIndex: accountIndex, label: label);
96 - }
97 -
98 - @override
99 - Future<void> setLabelSubaddress(Object wallet,
100 - {required int accountIndex, required int addressIndex, required String label}) async {
101 - final havenWallet = wallet as HavenWallet;
102 - await havenWallet.walletAddresses.subaddressList
103 - .setLabelSubaddress(accountIndex: accountIndex, addressIndex: addressIndex, label: label);
104 - }
105 -}
106 -
107 -class CWHavenWalletDetails extends HavenWalletDetails {
108 - CWHavenWalletDetails(this._wallet);
109 -
110 - final Object _wallet;
111 -
112 - @computed
113 - @override
114 - Account get account {
115 - final havenWallet = _wallet as HavenWallet;
116 - final acc = havenWallet.walletAddresses.account as monero_account.Account;
117 - return Account(id: acc.id, label: acc.label);
118 - }
119 -
120 - @computed
121 - @override
122 - HavenBalance get balance {
123 - final havenWallet = _wallet as HavenWallet;
124 - final balance = havenWallet.balance;
125 - throw Exception('Unimplemented');
126 - //return HavenBalance(
127 - // fullBalance: balance.fullBalance,
128 - // unlockedBalance: balance.unlockedBalance);
129 - }
130 -}
131 -
132 -class CWHaven extends Haven {
133 - @override
134 - HavenAccountList getAccountList(Object wallet) {
135 - return CWHavenAccountList(wallet);
136 - }
17 + HavenWalletService(this.walletInfoSource);
18
19 @override
139 - MoneroSubaddressList getSubaddressList(Object wallet) {
140 - return CWHavenSubaddressList(wallet);
141 - }
20 + WalletType getType() => WalletType.haven;
21
22 @override
144 - TransactionHistoryBase getTransactionHistory(Object wallet) {
145 - final havenWallet = wallet as HavenWallet;
146 - return havenWallet.transactionHistory;
147 - }
148 -
149 - @override
150 - HavenWalletDetails getMoneroWalletDetails(Object wallet) {
151 - return CWHavenWalletDetails(wallet);
152 - }
23 + Future<void> remove(String wallet) async {
24 + final path = await pathForWalletDir(name: wallet, type: WalletType.haven);
25
154 - @override
155 - int getHeightByDate({required DateTime date}) => getHavenHeightByDate(date: date);
156 -
157 - @override
158 - Future<int> getCurrentHeight() => getHavenCurrentHeight();
159 -
160 - @override
161 - TransactionPriority getDefaultTransactionPriority() {
162 - return MoneroTransactionPriority.automatic;
163 - }
26 + final file = Directory(path);
27 + final isExist = file.existsSync();
28
165 - @override
166 - TransactionPriority deserializeMoneroTransactionPriority({required int raw}) {
167 - return MoneroTransactionPriority.deserialize(raw: raw);
168 - }
169 -
170 - @override
171 - List<TransactionPriority> getTransactionPriorities() {
172 - return MoneroTransactionPriority.all;
173 - }
174 -
175 - @override
176 - List<String> getMoneroWordList(String language) {
177 - switch (language.toLowerCase()) {
178 - case 'english':
179 - return EnglishMnemonics.words;
180 - case 'chinese (simplified)':
181 - return ChineseSimplifiedMnemonics.words;
182 - case 'dutch':
183 - return DutchMnemonics.words;
184 - case 'german':
185 - return GermanMnemonics.words;
186 - case 'japanese':
187 - return JapaneseMnemonics.words;
188 - case 'portuguese':
189 - return PortugueseMnemonics.words;
190 - case 'russian':
191 - return RussianMnemonics.words;
192 - case 'spanish':
193 - return SpanishMnemonics.words;
194 - case 'french':
195 - return FrenchMnemonics.words;
196 - case 'italian':
197 - return ItalianMnemonics.words;
198 - default:
199 - return EnglishMnemonics.words;
29 + if (isExist) {
30 + await file.delete(recursive: true);
31 }
201 - }
202 -
203 - @override
204 - WalletCredentials createHavenRestoreWalletFromKeysCredentials(
205 - {required String name,
206 - required String spendKey,
207 - required String viewKey,
208 - required String address,
209 - required String password,
210 - required String language,
211 - required int height}) {
212 - return HavenRestoreWalletFromKeysCredentials(
213 - name: name,
214 - spendKey: spendKey,
215 - viewKey: viewKey,
216 - address: address,
217 - password: password,
218 - language: language,
219 - height: height);
220 - }
32
222 - @override
223 - WalletCredentials createHavenRestoreWalletFromSeedCredentials(
224 - {required String name,
225 - required String password,
226 - required int height,
227 - required String mnemonic}) {
228 - return HavenRestoreWalletFromSeedCredentials(
229 - name: name, password: password, height: height, mnemonic: mnemonic);
33 + final walletInfo = walletInfoSource.values
34 + .firstWhere((info) => info.id == WalletBase.idFor(wallet, getType()));
35 + await walletInfoSource.delete(walletInfo.key);
36 }
37
38 @override
233 - WalletCredentials createHavenNewWalletCredentials(
234 - {required String name, required String language, String? password}) {
235 - return HavenNewWalletCredentials(name: name, password: password, language: language);
39 + Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>> create(
40 + WalletCredentials credentials,
41 + {bool? isTestnet}) {
42 + throw UnimplementedError();
43 }
44
45 @override
239 - Map<String, String> getKeys(Object wallet) {
240 - final havenWallet = wallet as HavenWallet;
241 - final keys = havenWallet.keys;
242 - return <String, String>{
243 - 'privateSpendKey': keys.privateSpendKey,
244 - 'privateViewKey': keys.privateViewKey,
245 - 'publicSpendKey': keys.publicSpendKey,
246 - 'publicViewKey': keys.publicViewKey
247 - };
46 + Future<bool> isWalletExit(String name) {
47 + throw UnimplementedError();
48 }
49
50 @override
251 - Object createHavenTransactionCreationCredentials(
252 - {required List<Output> outputs,
253 - required TransactionPriority priority,
254 - required String assetType}) {
255 - return HavenTransactionCreationCredentials(
256 - outputs: outputs
257 - .map((out) => OutputInfo(
258 - fiatAmount: out.fiatAmount,
259 - cryptoAmount: out.cryptoAmount,
260 - address: out.address,
261 - note: out.note,
262 - sendAll: out.sendAll,
263 - extractedAddress: out.extractedAddress,
264 - isParsedAddress: out.isParsedAddress,
265 - formattedCryptoAmount: out.formattedCryptoAmount))
266 - .toList(),
267 - priority: priority as MoneroTransactionPriority,
268 - assetType: assetType);
51 + Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>> openWallet(
52 + String name, String password) {
53 + throw UnimplementedError();
54 }
55
56 @override
272 - String formatterMoneroAmountToString({required int amount}) {
273 - return moneroAmountToString(amount: amount);
57 + Future<void> rename(String currentName, String password, String newName) {
58 + throw UnimplementedError();
59 }
60
61 @override
277 - double formatterMoneroAmountToDouble({required int amount}) {
278 - return moneroAmountToDouble(amount: amount);
62 + Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>>
63 + restoreFromHardwareWallet(WalletCredentials credentials) {
64 + throw UnimplementedError();
65 }
66
67 @override
282 - int formatterMoneroParseAmount({required String amount}) {
283 - return moneroParseAmount(amount: amount);
68 + Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>>
69 + restoreFromKeys(WalletCredentials credentials, {bool? isTestnet}) {
70 + throw UnimplementedError();
71 }
72
73 @override
287 - Account getCurrentAccount(Object wallet) {
288 - final havenWallet = wallet as HavenWallet;
289 - final acc = havenWallet.walletAddresses.account as monero_account.Account;
290 - return Account(id: acc.id, label: acc.label);
74 + Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>>
75 + restoreFromSeed(WalletCredentials credentials, {bool? isTestnet}) {
76 + throw UnimplementedError();
77 }
292 -
293 - @override
294 - void setCurrentAccount(Object wallet, int id, String label) {
295 - final havenWallet = wallet as HavenWallet;
296 - havenWallet.walletAddresses.account = monero_account.Account(id: id, label: label);
297 - }
298 -
299 - @override
300 - void onStartup() {
301 - monero_wallet_api.onStartup();
302 - }
303 -
304 - @override
305 - int getTransactionInfoAccountId(TransactionInfo tx) {
306 - final havenTransactionInfo = tx as HavenTransactionInfo;
307 - return havenTransactionInfo.accountIndex;
308 - }
309 -
310 - @override
311 - Future<void> backupHavenSeeds(Box<HavenSeedStore> havenSeedStore) async {
312 - final walletInfoSource = await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
313 - final wallets = walletInfoSource.values
314 - .where((element) => element.type == WalletType.haven);
315 - for (var w in wallets) {
316 - final walletService = HavenWalletService(walletInfoSource);
317 - final flutterSecureStorage = secureStorageShared;
318 - final keyService = KeyService(flutterSecureStorage);
319 - final password = await keyService.getWalletPassword(walletName: w.name);
320 - final wallet = await walletService.openWallet(w.name, password);
321 - await havenSeedStore.add(HavenSeedStore(id: wallet.id, seed: wallet.seed));
322 - wallet.close();
323 - }
324 - await havenSeedStore.flush();
325 - }
326 -
327 - @override
328 - WalletService createHavenWalletService(Box<WalletInfo> walletInfoSource) {
329 - return HavenWalletService(walletInfoSource);
330 - }
331 -
332 - @override
333 - String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) {
334 - final havenWallet = wallet as HavenWallet;
335 - return havenWallet.getTransactionAddress(accountIndex, addressIndex);
336 - }
337 -
338 - @override
339 - CryptoCurrency assetOfTransaction(TransactionInfo tx) {
340 - final transaction = tx as HavenTransactionInfo;
341 - final asset = CryptoCurrency.fromString(transaction.assetType);
342 - return asset;
343 - }
344 -
345 - @override
346 - List<AssetRate> getAssetRate() =>
347 - getRate().map((rate) => AssetRate(rate.getAssetType(), rate.getRate())).toList();
78 }