From 698f0199d04166a855f706293b6a50529bac54a9 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Wed, 23 Apr 2025 12:19:59 +0200 Subject: [PATCH] Add the code to enable removing Haven wallets (#2222) --- lib/di.dart | 4 +- lib/haven/cw_haven.dart | 362 +++++----------------------------------- 2 files changed, 49 insertions(+), 317 deletions(-) diff --git a/lib/di.dart b/lib/di.dart index 6354a0c0f..27636c606 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -33,6 +33,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/hardware_wallet/require_hardware_wallet_connection.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart'; import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; +import 'package:cake_wallet/haven/cw_haven.dart'; import 'package:cake_wallet/src/screens/dev/monero_background_sync.dart'; import 'package:cake_wallet/src/screens/dev/moneroc_call_profiler.dart'; import 'package:cake_wallet/src/screens/settings/background_sync_page.dart'; @@ -1115,8 +1116,9 @@ Future setup({ return zano!.createZanoWalletService(_walletInfoSource); case WalletType.decred: return decred!.createDecredWalletService(_walletInfoSource, _unspentCoinsInfoSource); - case WalletType.none: case WalletType.haven: + return HavenWalletService(_walletInfoSource); + case WalletType.none: throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService'); } }); diff --git a/lib/haven/cw_haven.dart b/lib/haven/cw_haven.dart index c54e47eb4..b69e733c3 100644 --- a/lib/haven/cw_haven.dart +++ b/lib/haven/cw_haven.dart @@ -1,348 +1,78 @@ -part of 'haven.dart'; +import 'dart:io'; -class CWHavenAccountList extends HavenAccountList { - CWHavenAccountList(this._wallet); +import 'package:cw_core/balance.dart'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/transaction_history.dart'; +import 'package:cw_core/transaction_info.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_credentials.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_service.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:hive/hive.dart'; - final Object _wallet; +class HavenWalletService extends WalletService { + final Box walletInfoSource; + + HavenWalletService(this.walletInfoSource); @override - @computed - ObservableList get accounts { - final havenWallet = _wallet as HavenWallet; - final accounts = havenWallet.walletAddresses.accountList.accounts - .map((acc) => Account(id: acc.id, label: acc.label)) - .toList(); - return ObservableList.of(accounts); - } + WalletType getType() => WalletType.haven; @override - void update(Object wallet) { - final havenWallet = wallet as HavenWallet; - havenWallet.walletAddresses.accountList.update(); - } + Future remove(String wallet) async { + final path = await pathForWalletDir(name: wallet, type: WalletType.haven); - @override - void refresh(Object wallet) { - final havenWallet = wallet as HavenWallet; - havenWallet.walletAddresses.accountList.refresh(); - } + final file = Directory(path); + final isExist = file.existsSync(); - @override - List getAll(Object wallet) { - final havenWallet = wallet as HavenWallet; - return havenWallet.walletAddresses.accountList - .getAll() - .map((acc) => Account(id: acc.id, label: acc.label)) - .toList(); - } - - @override - Future addAccount(Object wallet, {required String label}) async { - final havenWallet = wallet as HavenWallet; - await havenWallet.walletAddresses.accountList.addAccount(label: label); - } - - @override - Future setLabelAccount(Object wallet, - {required int accountIndex, required String label}) async { - final havenWallet = wallet as HavenWallet; - await havenWallet.walletAddresses.accountList - .setLabelAccount(accountIndex: accountIndex, label: label); - } -} - -class CWHavenSubaddressList extends MoneroSubaddressList { - CWHavenSubaddressList(this._wallet); - - final Object _wallet; - - @override - @computed - ObservableList get subaddresses { - final havenWallet = _wallet as HavenWallet; - final subAddresses = havenWallet.walletAddresses.subaddressList.subaddresses - .map((sub) => Subaddress(id: sub.id, address: sub.address, label: sub.label)) - .toList(); - return ObservableList.of(subAddresses); - } - - @override - void update(Object wallet, {required int accountIndex}) { - final havenWallet = wallet as HavenWallet; - havenWallet.walletAddresses.subaddressList.update(accountIndex: accountIndex); - } - - @override - void refresh(Object wallet, {required int accountIndex}) { - final havenWallet = wallet as HavenWallet; - havenWallet.walletAddresses.subaddressList.refresh(accountIndex: accountIndex); - } - - @override - List getAll(Object wallet) { - final havenWallet = wallet as HavenWallet; - return havenWallet.walletAddresses.subaddressList - .getAll() - .map((sub) => Subaddress(id: sub.id, label: sub.label, address: sub.address)) - .toList(); - } - - @override - Future addSubaddress(Object wallet, - {required int accountIndex, required String label}) async { - final havenWallet = wallet as HavenWallet; - await havenWallet.walletAddresses.subaddressList - .addSubaddress(accountIndex: accountIndex, label: label); - } - - @override - Future setLabelSubaddress(Object wallet, - {required int accountIndex, required int addressIndex, required String label}) async { - final havenWallet = wallet as HavenWallet; - await havenWallet.walletAddresses.subaddressList - .setLabelSubaddress(accountIndex: accountIndex, addressIndex: addressIndex, label: label); - } -} - -class CWHavenWalletDetails extends HavenWalletDetails { - CWHavenWalletDetails(this._wallet); - - final Object _wallet; - - @computed - @override - Account get account { - final havenWallet = _wallet as HavenWallet; - final acc = havenWallet.walletAddresses.account as monero_account.Account; - return Account(id: acc.id, label: acc.label); - } - - @computed - @override - HavenBalance get balance { - final havenWallet = _wallet as HavenWallet; - final balance = havenWallet.balance; - throw Exception('Unimplemented'); - //return HavenBalance( - // fullBalance: balance.fullBalance, - // unlockedBalance: balance.unlockedBalance); - } -} - -class CWHaven extends Haven { - @override - HavenAccountList getAccountList(Object wallet) { - return CWHavenAccountList(wallet); - } - - @override - MoneroSubaddressList getSubaddressList(Object wallet) { - return CWHavenSubaddressList(wallet); - } - - @override - TransactionHistoryBase getTransactionHistory(Object wallet) { - final havenWallet = wallet as HavenWallet; - return havenWallet.transactionHistory; - } - - @override - HavenWalletDetails getMoneroWalletDetails(Object wallet) { - return CWHavenWalletDetails(wallet); - } - - @override - int getHeightByDate({required DateTime date}) => getHavenHeightByDate(date: date); - - @override - Future getCurrentHeight() => getHavenCurrentHeight(); - - @override - TransactionPriority getDefaultTransactionPriority() { - return MoneroTransactionPriority.automatic; - } - - @override - TransactionPriority deserializeMoneroTransactionPriority({required int raw}) { - return MoneroTransactionPriority.deserialize(raw: raw); - } - - @override - List getTransactionPriorities() { - return MoneroTransactionPriority.all; - } - - @override - List getMoneroWordList(String language) { - switch (language.toLowerCase()) { - case 'english': - return EnglishMnemonics.words; - case 'chinese (simplified)': - return ChineseSimplifiedMnemonics.words; - case 'dutch': - return DutchMnemonics.words; - case 'german': - return GermanMnemonics.words; - case 'japanese': - return JapaneseMnemonics.words; - case 'portuguese': - return PortugueseMnemonics.words; - case 'russian': - return RussianMnemonics.words; - case 'spanish': - return SpanishMnemonics.words; - case 'french': - return FrenchMnemonics.words; - case 'italian': - return ItalianMnemonics.words; - default: - return EnglishMnemonics.words; + if (isExist) { + await file.delete(recursive: true); } + + final walletInfo = walletInfoSource.values + .firstWhere((info) => info.id == WalletBase.idFor(wallet, getType())); + await walletInfoSource.delete(walletInfo.key); } @override - WalletCredentials createHavenRestoreWalletFromKeysCredentials( - {required String name, - required String spendKey, - required String viewKey, - required String address, - required String password, - required String language, - required int height}) { - return HavenRestoreWalletFromKeysCredentials( - name: name, - spendKey: spendKey, - viewKey: viewKey, - address: address, - password: password, - language: language, - height: height); + Future, TransactionInfo>> create( + WalletCredentials credentials, + {bool? isTestnet}) { + throw UnimplementedError(); } @override - WalletCredentials createHavenRestoreWalletFromSeedCredentials( - {required String name, - required String password, - required int height, - required String mnemonic}) { - return HavenRestoreWalletFromSeedCredentials( - name: name, password: password, height: height, mnemonic: mnemonic); + Future isWalletExit(String name) { + throw UnimplementedError(); } @override - WalletCredentials createHavenNewWalletCredentials( - {required String name, required String language, String? password}) { - return HavenNewWalletCredentials(name: name, password: password, language: language); + Future, TransactionInfo>> openWallet( + String name, String password) { + throw UnimplementedError(); } @override - Map getKeys(Object wallet) { - final havenWallet = wallet as HavenWallet; - final keys = havenWallet.keys; - return { - 'privateSpendKey': keys.privateSpendKey, - 'privateViewKey': keys.privateViewKey, - 'publicSpendKey': keys.publicSpendKey, - 'publicViewKey': keys.publicViewKey - }; + Future rename(String currentName, String password, String newName) { + throw UnimplementedError(); } @override - Object createHavenTransactionCreationCredentials( - {required List outputs, - required TransactionPriority priority, - required String assetType}) { - return HavenTransactionCreationCredentials( - outputs: outputs - .map((out) => OutputInfo( - fiatAmount: out.fiatAmount, - cryptoAmount: out.cryptoAmount, - address: out.address, - note: out.note, - sendAll: out.sendAll, - extractedAddress: out.extractedAddress, - isParsedAddress: out.isParsedAddress, - formattedCryptoAmount: out.formattedCryptoAmount)) - .toList(), - priority: priority as MoneroTransactionPriority, - assetType: assetType); + Future, TransactionInfo>> + restoreFromHardwareWallet(WalletCredentials credentials) { + throw UnimplementedError(); } @override - String formatterMoneroAmountToString({required int amount}) { - return moneroAmountToString(amount: amount); + Future, TransactionInfo>> + restoreFromKeys(WalletCredentials credentials, {bool? isTestnet}) { + throw UnimplementedError(); } @override - double formatterMoneroAmountToDouble({required int amount}) { - return moneroAmountToDouble(amount: amount); + Future, TransactionInfo>> + restoreFromSeed(WalletCredentials credentials, {bool? isTestnet}) { + throw UnimplementedError(); } - - @override - int formatterMoneroParseAmount({required String amount}) { - return moneroParseAmount(amount: amount); - } - - @override - Account getCurrentAccount(Object wallet) { - final havenWallet = wallet as HavenWallet; - final acc = havenWallet.walletAddresses.account as monero_account.Account; - return Account(id: acc.id, label: acc.label); - } - - @override - void setCurrentAccount(Object wallet, int id, String label) { - final havenWallet = wallet as HavenWallet; - havenWallet.walletAddresses.account = monero_account.Account(id: id, label: label); - } - - @override - void onStartup() { - monero_wallet_api.onStartup(); - } - - @override - int getTransactionInfoAccountId(TransactionInfo tx) { - final havenTransactionInfo = tx as HavenTransactionInfo; - return havenTransactionInfo.accountIndex; - } - - @override - Future backupHavenSeeds(Box havenSeedStore) async { - final walletInfoSource = await CakeHive.openBox(WalletInfo.boxName); - final wallets = walletInfoSource.values - .where((element) => element.type == WalletType.haven); - for (var w in wallets) { - final walletService = HavenWalletService(walletInfoSource); - final flutterSecureStorage = secureStorageShared; - final keyService = KeyService(flutterSecureStorage); - final password = await keyService.getWalletPassword(walletName: w.name); - final wallet = await walletService.openWallet(w.name, password); - await havenSeedStore.add(HavenSeedStore(id: wallet.id, seed: wallet.seed)); - wallet.close(); - } - await havenSeedStore.flush(); - } - - @override - WalletService createHavenWalletService(Box walletInfoSource) { - return HavenWalletService(walletInfoSource); - } - - @override - String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) { - final havenWallet = wallet as HavenWallet; - return havenWallet.getTransactionAddress(accountIndex, addressIndex); - } - - @override - CryptoCurrency assetOfTransaction(TransactionInfo tx) { - final transaction = tx as HavenTransactionInfo; - final asset = CryptoCurrency.fromString(transaction.assetType); - return asset; - } - - @override - List getAssetRate() => - getRate().map((rate) => AssetRate(rate.getAssetType(), rate.getRate())).toList(); }