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 <omarh.ismail1@gmail.com>
cyan committed
Dec 11, 2024 at 15:31 UTC
e2a1d865afe2380cc9e814270ea98bfdf5456519
7 files changed
+87
-14
cw_core/lib/hive_type_ids.dart
+2
-1
@@ -18,4 +18,5 @@ const SPL_TOKEN_TYPE_ID = 16;
18
const DERIVATION_INFO_TYPE_ID = 17;
19
const TRON_TOKEN_TYPE_ID = 18;
20
const HARDWARE_WALLET_TYPE_TYPE_ID = 19;
21
-const MWEB_UTXO_TYPE_ID = 20;
\ No newline at end of file
21
+const MWEB_UTXO_TYPE_ID = 20;
22
+const HAVEN_SEED_STORE_TYPE_ID = 21;
\ No newline at end of file
cw_evm/lib/evm_chain_transaction_history.dart
-1
@@ -84,7 +84,6 @@ abstract class EVMChainTransactionHistoryBase
84
_update(tx);
85
}
86
}
87
- print('doneee');
87
} catch (e) {
88
log(e.toString());
89
}
lib/entities/default_settings_migration.dart
+23
-9
@@ -1,9 +1,13 @@
1
import 'dart:convert';
2
import 'dart:io' show Directory, File, Platform;
3
import 'package:cake_wallet/bitcoin/bitcoin.dart';
4
+import 'package:cake_wallet/core/key_service.dart';
5
import 'package:cake_wallet/core/secure_storage.dart';
6
import 'package:cake_wallet/entities/exchange_api_mode.dart';
7
import 'package:cake_wallet/entities/fiat_api_mode.dart';
8
+import 'package:cake_wallet/entities/haven_seed_store.dart';
9
+import 'package:cake_wallet/haven/haven.dart';
10
+import 'package:cw_core/cake_hive.dart';
11
import 'package:cw_core/pathForWallet.dart';
12
import 'package:cake_wallet/entities/secret_store_key.dart';
13
import 'package:cw_core/root_dir.dart';
@@ -52,7 +56,8 @@ Future<void> defaultSettingsMigration(
56
required Box<Node> powNodes,
57
required Box<WalletInfo> walletInfoSource,
58
required Box<Trade> tradeSource,
55
- required Box<Contact> contactSource}) async {
59
+ required Box<Contact> contactSource,
60
+ required Box<HavenSeedStore> havenSeedStore}) async {
61
if (Platform.isIOS) {
62
await ios_migrate_v1(walletInfoSource, tradeSource, contactSource);
63
}
@@ -290,20 +295,22 @@ Future<void> defaultSettingsMigration(
295
);
296
break;
297
case 45:
293
- await updateWalletTypeNodesWithNewNode(
298
+ await _backupHavenSeeds(havenSeedStore);
299
+
300
+ updateWalletTypeNodesWithNewNode(
301
newNodeUri: 'matic.nownodes.io',
302
sharedPreferences: sharedPreferences,
303
nodes: nodes,
304
type: WalletType.polygon,
305
useSSL: true,
306
);
300
- await updateWalletTypeNodesWithNewNode(
301
- newNodeUri: 'eth.nownodes.io',
302
- sharedPreferences: sharedPreferences,
303
- nodes: nodes,
304
- type: WalletType.ethereum,
305
- useSSL: true,
306
- );
307
+ updateWalletTypeNodesWithNewNode(
308
+ newNodeUri: 'eth.nownodes.io',
309
+ sharedPreferences: sharedPreferences,
310
+ nodes: nodes,
311
+ type: WalletType.ethereum,
312
+ useSSL: true,
313
+ );
314
default:
315
break;
316
}
@@ -318,6 +325,13 @@ Future<void> defaultSettingsMigration(
325
await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version);
326
}
327
328
+Future<void> _backupHavenSeeds(Box<HavenSeedStore> havenSeedStore) async {
329
+ final future = haven?.backupHavenSeeds(havenSeedStore);
330
+ if (future != null) {
331
+ await future;
332
+ }
333
+ return;
334
+}
335
/// generic function for changing any wallet default node
336
/// instead of making a new function for each change
337
Future<void> _changeDefaultNode({
lib/entities/haven_seed_store.dart
new
+19
@@ -0,0 +1,19 @@
1
+import 'package:cw_core/hive_type_ids.dart';
2
+import 'package:hive/hive.dart';
3
+
4
+part 'haven_seed_store.g.dart';
5
+
6
+@HiveType(typeId: HavenSeedStore.typeId)
7
+class HavenSeedStore extends HiveObject {
8
+ HavenSeedStore({required this.id, this.seed});
9
+
10
+ static const typeId = HAVEN_SEED_STORE_TYPE_ID;
11
+ static const boxName = 'HavenSeedStore';
12
+ static const boxKey = 'havenSeedStoreKey';
13
+
14
+ @HiveField(0, defaultValue: '')
15
+ String id;
16
+
17
+ @HiveField(2)
18
+ String? seed;
19
+}
lib/haven/cw_haven.dart
+17
@@ -307,6 +307,23 @@ class CWHaven extends Haven {
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);
lib/main.dart
+16
-2
@@ -9,6 +9,7 @@ import 'package:cake_wallet/entities/contact.dart';
9
import 'package:cake_wallet/entities/default_settings_migration.dart';
10
import 'package:cake_wallet/entities/get_encryption_key.dart';
11
import 'package:cake_wallet/core/secure_storage.dart';
12
+import 'package:cake_wallet/entities/haven_seed_store.dart';
13
import 'package:cake_wallet/entities/language_service.dart';
14
import 'package:cake_wallet/entities/template.dart';
15
import 'package:cake_wallet/entities/transaction_description.dart';
@@ -164,6 +165,10 @@ Future<void> initializeAppConfigs() async {
165
CakeHive.registerAdapter(AnonpayInvoiceInfoAdapter());
166
}
167
168
+ if (!CakeHive.isAdapterRegistered(HavenSeedStore.typeId)) {
169
+ CakeHive.registerAdapter(HavenSeedStoreAdapter());
170
+ }
171
+
172
if (!CakeHive.isAdapterRegistered(MwebUtxo.typeId)) {
173
CakeHive.registerAdapter(MwebUtxoAdapter());
174
}
@@ -188,6 +193,12 @@ Future<void> initializeAppConfigs() async {
193
final anonpayInvoiceInfo = await CakeHive.openBox<AnonpayInvoiceInfo>(AnonpayInvoiceInfo.boxName);
194
final unspentCoinsInfoSource = await CakeHive.openBox<UnspentCoinsInfo>(UnspentCoinsInfo.boxName);
195
196
+ final havenSeedStoreBoxKey =
197
+ await getEncryptionKey(secureStorage: secureStorage, forKey: HavenSeedStore.boxKey);
198
+ final havenSeedStore = await CakeHive.openBox<HavenSeedStore>(
199
+ HavenSeedStore.boxName,
200
+ encryptionKey: havenSeedStoreBoxKey);
201
+
202
await initialSetup(
203
sharedPreferences: await SharedPreferences.getInstance(),
204
nodes: nodes,
@@ -203,6 +214,7 @@ Future<void> initializeAppConfigs() async {
214
transactionDescriptions: transactionDescriptions,
215
secureStorage: secureStorage,
216
anonpayInvoiceInfo: anonpayInvoiceInfo,
217
+ havenSeedStore: havenSeedStore,
218
initialMigrationVersion: 45,
219
);
220
}
@@ -222,7 +234,8 @@ Future<void> initialSetup(
234
required SecureStorage secureStorage,
235
required Box<AnonpayInvoiceInfo> anonpayInvoiceInfo,
236
required Box<UnspentCoinsInfo> unspentCoinsInfoSource,
225
- int initialMigrationVersion = 15}) async {
237
+ required Box<HavenSeedStore> havenSeedStore,
238
+ int initialMigrationVersion = 15, }) async {
239
LanguageService.loadLocaleList();
240
await defaultSettingsMigration(
241
secureStorage: secureStorage,
@@ -232,7 +245,8 @@ Future<void> initialSetup(
245
contactSource: contactSource,
246
tradeSource: tradesSource,
247
nodes: nodes,
235
- powNodes: powNodes);
248
+ powNodes: powNodes,
249
+ havenSeedStore: havenSeedStore);
250
await setup(
251
walletInfoSource: walletInfoSource,
252
nodeSource: nodes,
tool/configure.dart
+10
-1
@@ -656,7 +656,14 @@ import 'package:cw_core/output_info.dart';
656
import 'package:cake_wallet/view_model/send/output.dart';
657
import 'package:cw_core/wallet_service.dart';
658
import 'package:hive/hive.dart';
659
-import 'package:cw_core/crypto_currency.dart';""";
659
+import 'package:cw_core/crypto_currency.dart';
660
+import 'package:cake_wallet/core/key_service.dart';
661
+import 'package:cake_wallet/core/secure_storage.dart';
662
+import 'package:cake_wallet/entities/haven_seed_store.dart';
663
+import 'package:cw_core/cake_hive.dart';
664
+import 'package:cw_core/wallet_info.dart';
665
+import 'package:cw_core/wallet_type.dart';
666
+""";
667
const havenCWHeaders = """
668
import 'package:cw_core/get_height_by_date.dart';
669
import 'package:cw_core/monero_amount_format.dart';
@@ -679,6 +686,7 @@ import 'package:cw_haven/mnemonics/french.dart';
686
import 'package:cw_haven/mnemonics/italian.dart';
687
import 'package:cw_haven/haven_transaction_creation_credentials.dart';
688
import 'package:cw_haven/api/balance_list.dart';
689
+import 'package:cw_haven/haven_wallet_service.dart';
690
""";
691
const havenCwPart = "part 'cw_haven.dart';";
692
const havenContent = """
@@ -779,6 +787,7 @@ abstract class Haven {
787
void onStartup();
788
int getTransactionInfoAccountId(TransactionInfo tx);
789
WalletService createHavenWalletService(Box<WalletInfo> walletInfoSource);
790
+ Future<void> backupHavenSeeds(Box<HavenSeedStore> havenSeedStore);
791
CryptoCurrency assetOfTransaction(TransactionInfo tx);
792
List<AssetRate> getAssetRate();
793
}