From e2a1d865afe2380cc9e814270ea98bfdf5456519 Mon Sep 17 00:00:00 2001 From: cyan Date: Wed, 11 Dec 2024 15:31:01 -0500 Subject: [PATCH] CW-673: Save Haven seeds to show it to the user after Haven removal (#1518) * haven: backup seeds * haven backup fixes * ci fix * reorder build script * disable haven * properly call cw_haven code * [skip ci] update PR * Update evm_chain_transaction_history.dart remove print --------- Co-authored-by: Omar Hatem --- cw_core/lib/hive_type_ids.dart | 3 +- cw_evm/lib/evm_chain_transaction_history.dart | 1 - lib/entities/default_settings_migration.dart | 32 +++++++++++++------ lib/entities/haven_seed_store.dart | 19 +++++++++++ lib/haven/cw_haven.dart | 17 ++++++++++ lib/main.dart | 18 +++++++++-- tool/configure.dart | 11 ++++++- 7 files changed, 87 insertions(+), 14 deletions(-) create mode 100644 lib/entities/haven_seed_store.dart diff --git a/cw_core/lib/hive_type_ids.dart b/cw_core/lib/hive_type_ids.dart index 6432c484b..0899ac665 100644 --- a/cw_core/lib/hive_type_ids.dart +++ b/cw_core/lib/hive_type_ids.dart @@ -18,4 +18,5 @@ const SPL_TOKEN_TYPE_ID = 16; const DERIVATION_INFO_TYPE_ID = 17; const TRON_TOKEN_TYPE_ID = 18; const HARDWARE_WALLET_TYPE_TYPE_ID = 19; -const MWEB_UTXO_TYPE_ID = 20; \ No newline at end of file +const MWEB_UTXO_TYPE_ID = 20; +const HAVEN_SEED_STORE_TYPE_ID = 21; \ No newline at end of file diff --git a/cw_evm/lib/evm_chain_transaction_history.dart b/cw_evm/lib/evm_chain_transaction_history.dart index 4a05746da..7c46ebecc 100644 --- a/cw_evm/lib/evm_chain_transaction_history.dart +++ b/cw_evm/lib/evm_chain_transaction_history.dart @@ -84,7 +84,6 @@ abstract class EVMChainTransactionHistoryBase _update(tx); } } - print('doneee'); } catch (e) { log(e.toString()); } diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index d91ad6442..92cb752cd 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -1,9 +1,13 @@ import 'dart:convert'; import 'dart:io' show Directory, File, Platform; import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/core/key_service.dart'; import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; +import 'package:cake_wallet/entities/haven_seed_store.dart'; +import 'package:cake_wallet/haven/haven.dart'; +import 'package:cw_core/cake_hive.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cw_core/root_dir.dart'; @@ -52,7 +56,8 @@ Future defaultSettingsMigration( required Box powNodes, required Box walletInfoSource, required Box tradeSource, - required Box contactSource}) async { + required Box contactSource, + required Box havenSeedStore}) async { if (Platform.isIOS) { await ios_migrate_v1(walletInfoSource, tradeSource, contactSource); } @@ -290,20 +295,22 @@ Future defaultSettingsMigration( ); break; case 45: - await updateWalletTypeNodesWithNewNode( + await _backupHavenSeeds(havenSeedStore); + + updateWalletTypeNodesWithNewNode( newNodeUri: 'matic.nownodes.io', sharedPreferences: sharedPreferences, nodes: nodes, type: WalletType.polygon, useSSL: true, ); - await updateWalletTypeNodesWithNewNode( - newNodeUri: 'eth.nownodes.io', - sharedPreferences: sharedPreferences, - nodes: nodes, - type: WalletType.ethereum, - useSSL: true, - ); + updateWalletTypeNodesWithNewNode( + newNodeUri: 'eth.nownodes.io', + sharedPreferences: sharedPreferences, + nodes: nodes, + type: WalletType.ethereum, + useSSL: true, + ); default: break; } @@ -318,6 +325,13 @@ Future defaultSettingsMigration( await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version); } +Future _backupHavenSeeds(Box havenSeedStore) async { + final future = haven?.backupHavenSeeds(havenSeedStore); + if (future != null) { + await future; + } + return; +} /// generic function for changing any wallet default node /// instead of making a new function for each change Future _changeDefaultNode({ diff --git a/lib/entities/haven_seed_store.dart b/lib/entities/haven_seed_store.dart new file mode 100644 index 000000000..f899799d8 --- /dev/null +++ b/lib/entities/haven_seed_store.dart @@ -0,0 +1,19 @@ +import 'package:cw_core/hive_type_ids.dart'; +import 'package:hive/hive.dart'; + +part 'haven_seed_store.g.dart'; + +@HiveType(typeId: HavenSeedStore.typeId) +class HavenSeedStore extends HiveObject { + HavenSeedStore({required this.id, this.seed}); + + static const typeId = HAVEN_SEED_STORE_TYPE_ID; + static const boxName = 'HavenSeedStore'; + static const boxKey = 'havenSeedStoreKey'; + + @HiveField(0, defaultValue: '') + String id; + + @HiveField(2) + String? seed; +} diff --git a/lib/haven/cw_haven.dart b/lib/haven/cw_haven.dart index 57c4e49c3..c54e47eb4 100644 --- a/lib/haven/cw_haven.dart +++ b/lib/haven/cw_haven.dart @@ -307,6 +307,23 @@ class CWHaven extends Haven { 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); diff --git a/lib/main.dart b/lib/main.dart index 00d76800d..510705105 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,6 +9,7 @@ import 'package:cake_wallet/entities/contact.dart'; import 'package:cake_wallet/entities/default_settings_migration.dart'; import 'package:cake_wallet/entities/get_encryption_key.dart'; import 'package:cake_wallet/core/secure_storage.dart'; +import 'package:cake_wallet/entities/haven_seed_store.dart'; import 'package:cake_wallet/entities/language_service.dart'; import 'package:cake_wallet/entities/template.dart'; import 'package:cake_wallet/entities/transaction_description.dart'; @@ -164,6 +165,10 @@ Future initializeAppConfigs() async { CakeHive.registerAdapter(AnonpayInvoiceInfoAdapter()); } + if (!CakeHive.isAdapterRegistered(HavenSeedStore.typeId)) { + CakeHive.registerAdapter(HavenSeedStoreAdapter()); + } + if (!CakeHive.isAdapterRegistered(MwebUtxo.typeId)) { CakeHive.registerAdapter(MwebUtxoAdapter()); } @@ -188,6 +193,12 @@ Future initializeAppConfigs() async { final anonpayInvoiceInfo = await CakeHive.openBox(AnonpayInvoiceInfo.boxName); final unspentCoinsInfoSource = await CakeHive.openBox(UnspentCoinsInfo.boxName); + final havenSeedStoreBoxKey = + await getEncryptionKey(secureStorage: secureStorage, forKey: HavenSeedStore.boxKey); + final havenSeedStore = await CakeHive.openBox( + HavenSeedStore.boxName, + encryptionKey: havenSeedStoreBoxKey); + await initialSetup( sharedPreferences: await SharedPreferences.getInstance(), nodes: nodes, @@ -203,6 +214,7 @@ Future initializeAppConfigs() async { transactionDescriptions: transactionDescriptions, secureStorage: secureStorage, anonpayInvoiceInfo: anonpayInvoiceInfo, + havenSeedStore: havenSeedStore, initialMigrationVersion: 45, ); } @@ -222,7 +234,8 @@ Future initialSetup( required SecureStorage secureStorage, required Box anonpayInvoiceInfo, required Box unspentCoinsInfoSource, - int initialMigrationVersion = 15}) async { + required Box havenSeedStore, + int initialMigrationVersion = 15, }) async { LanguageService.loadLocaleList(); await defaultSettingsMigration( secureStorage: secureStorage, @@ -232,7 +245,8 @@ Future initialSetup( contactSource: contactSource, tradeSource: tradesSource, nodes: nodes, - powNodes: powNodes); + powNodes: powNodes, + havenSeedStore: havenSeedStore); await setup( walletInfoSource: walletInfoSource, nodeSource: nodes, diff --git a/tool/configure.dart b/tool/configure.dart index d9d5c6667..6abd73d9e 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -656,7 +656,14 @@ import 'package:cw_core/output_info.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:hive/hive.dart'; -import 'package:cw_core/crypto_currency.dart';"""; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cake_wallet/core/key_service.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; +import 'package:cake_wallet/entities/haven_seed_store.dart'; +import 'package:cw_core/cake_hive.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_type.dart'; +"""; const havenCWHeaders = """ import 'package:cw_core/get_height_by_date.dart'; import 'package:cw_core/monero_amount_format.dart'; @@ -679,6 +686,7 @@ import 'package:cw_haven/mnemonics/french.dart'; import 'package:cw_haven/mnemonics/italian.dart'; import 'package:cw_haven/haven_transaction_creation_credentials.dart'; import 'package:cw_haven/api/balance_list.dart'; +import 'package:cw_haven/haven_wallet_service.dart'; """; const havenCwPart = "part 'cw_haven.dart';"; const havenContent = """ @@ -779,6 +787,7 @@ abstract class Haven { void onStartup(); int getTransactionInfoAccountId(TransactionInfo tx); WalletService createHavenWalletService(Box walletInfoSource); + Future backupHavenSeeds(Box havenSeedStore); CryptoCurrency assetOfTransaction(TransactionInfo tx); List getAssetRate(); }