import 'dart:convert'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:isar/isar.dart'; import 'package:stackwallet/db/hive/db.dart'; import 'package:stackwallet/db/isar/main_db.dart'; import 'package:stackwallet/models/isar/models/transaction_note.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'package:stackwallet/wallets/isar/models/wallet_info.dart'; import 'package:stackwallet/wallets/wallet/supporting/epiccash_wallet_info_extension.dart'; Future migrateWalletsToIsar({ required SecureStorageInterface secureStore, }) async { final allWalletsBox = await Hive.openBox(DB.boxNameAllWalletsData); final names = DB.instance .get(boxName: DB.boxNameAllWalletsData, key: 'names') as Map?; if (names == null) { // no wallets to migrate return; } // // Parse the old data from the Hive map into a nice list // final List< ({ Coin coin, String name, String walletId, })> oldInfo = Map.from(names).values.map((e) { final map = e as Map; return ( coin: Coin.values.byName(map["coin"] as String), walletId: map["id"] as String, name: map["name"] as String, ); }).toList(); // // Get current ordered list of favourite wallet Ids // final List favourites = (await Hive.openBox(DB.boxNameFavoriteWallets)).values.toList(); final List newInfo = []; final List migratedNotes = []; // // Convert each old info into the new Isar WalletInfo // for (final old in oldInfo) { final walletBox = await Hive.openBox(old.walletId); // // First handle transaction notes // final newNoteCount = await MainDB.instance.isar.transactionNotes .where() .walletIdEqualTo(old.walletId) .count(); if (newNoteCount == 0) { final map = walletBox.get('notes') as Map?; if (map != null) { final notes = Map.from(map); for (final txid in notes.keys) { final note = notes[txid]; if (note != null && note.isNotEmpty) { final newNote = TransactionNote( walletId: old.walletId, txid: txid, value: note, ); migratedNotes.add(newNote); } } } } // // Set other data values // Map otherData = {}; otherData[WalletInfoKeys.tokenContractAddresses] = walletBox.get( DBKeys.ethTokenContracts, ) as List?; // epiccash specifics if (old.coin == Coin.epicCash) { final epicWalletInfo = ExtraEpiccashWalletInfo.fromMap({ "receivingIndex": walletBox.get("receivingIndex") as int? ?? 0, "changeIndex": walletBox.get("changeIndex") as int? ?? 0, "slatesToAddresses": walletBox.get("slate_to_address") as Map? ?? {}, "slatesToCommits": walletBox.get("slatesToCommits") as Map? ?? {}, "lastScannedBlock": walletBox.get("lastScannedBlock") as int? ?? 0, "restoreHeight": walletBox.get("restoreHeight") as int? ?? 0, "creationHeight": walletBox.get("creationHeight") as int? ?? 0, }); otherData[WalletInfoKeys.epiccashData] = jsonEncode( epicWalletInfo.toMap(), ); } // // Clear out any keys with null values as they are not needed // otherData.removeWhere((key, value) => value == null); final info = WalletInfo( coinName: old.coin.name, walletId: old.walletId, name: old.name, mainAddressType: old.coin.primaryAddressType, favouriteOrderIndex: favourites.indexOf(old.walletId), isMnemonicVerified: allWalletsBox .get("${old.walletId}_mnemonicHasBeenVerified") as bool? ?? false, cachedChainHeight: walletBox.get( DBKeys.storedChainHeight, ) as int? ?? 0, cachedBalanceString: walletBox.get( DBKeys.cachedBalance, ) as String?, cachedBalanceSecondaryString: walletBox.get( DBKeys.cachedBalanceSecondary, ) as String?, otherDataJsonString: jsonEncode(otherData), ); newInfo.add(info); } if (migratedNotes.isNotEmpty) { await MainDB.instance.isar.writeTxn(() async { await MainDB.instance.isar.transactionNotes.putAll(migratedNotes); }); } await MainDB.instance.isar.writeTxn(() async { await MainDB.instance.isar.walletInfo.putAll(newInfo); }); await _cleanupOnSuccess(walletIds: newInfo.map((e) => e.walletId).toList()); } Future _cleanupOnSuccess({required List walletIds}) async { await Hive.deleteBoxFromDisk(DB.boxNameFavoriteWallets); await Hive.deleteBoxFromDisk(DB.boxNameAllWalletsData); for (final walletId in walletIds) { await Hive.deleteBoxFromDisk(walletId); } }