stack_wallet/lib/utilities/db_version_migration.dart
2022-12-14 10:26:48 -06:00

177 lines
6.5 KiB
Dart

import 'package:hive/hive.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/models/lelantus_coin.dart';
import 'package:stackwallet/models/node_model.dart';
import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/services/wallets_service.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/prefs.dart';
class DbVersionMigrator {
Future<void> migrate(
int fromVersion, {
required SecureStorageInterface secureStore,
}) async {
Logging.instance.log(
"Running migrate fromVersion $fromVersion",
level: LogLevel.Warning,
);
switch (fromVersion) {
case 0:
await Hive.openBox<dynamic>(DB.boxNameAllWalletsData);
await Hive.openBox<dynamic>(DB.boxNamePrefs);
final walletsService =
WalletsService(secureStorageInterface: secureStore);
final nodeService = NodeService(secureStorageInterface: secureStore);
final prefs = Prefs.instance;
final walletInfoList = await walletsService.walletNames;
await prefs.init();
ElectrumX? client;
int? latestSetId;
// only instantiate client if there are firo wallets
if (walletInfoList.values.any((element) => element.coin == Coin.firo)) {
await Hive.openBox<NodeModel>(DB.boxNameNodeModels);
await Hive.openBox<NodeModel>(DB.boxNamePrimaryNodes);
final node = nodeService.getPrimaryNodeFor(coin: Coin.firo) ??
DefaultNodes.firo;
List<ElectrumXNode> failovers = nodeService
.failoverNodesFor(coin: Coin.firo)
.map(
(e) => ElectrumXNode(
address: e.host,
port: e.port,
name: e.name,
id: e.id,
useSSL: e.useSSL,
),
)
.toList();
client = ElectrumX.from(
node: ElectrumXNode(
address: node.host,
port: node.port,
name: node.name,
id: node.id,
useSSL: node.useSSL),
prefs: prefs,
failovers: failovers,
);
try {
latestSetId = await client.getLatestCoinId();
} catch (e) {
// default to 2 for now
latestSetId = 2;
Logging.instance.log(
"Failed to fetch latest coin id during firo db migrate: $e \nUsing a default value of 2",
level: LogLevel.Warning);
}
}
for (final walletInfo in walletInfoList.values) {
// migrate each firo wallet's lelantus coins
if (walletInfo.coin == Coin.firo) {
await Hive.openBox<dynamic>(walletInfo.walletId);
final _lelantusCoins = DB.instance.get<dynamic>(
boxName: walletInfo.walletId, key: '_lelantus_coins') as List?;
final List<Map<dynamic, LelantusCoin>> lelantusCoins = [];
for (var lCoin in _lelantusCoins ?? []) {
lelantusCoins
.add({lCoin.keys.first: lCoin.values.first as LelantusCoin});
}
List<Map<dynamic, LelantusCoin>> coins = [];
for (final element in lelantusCoins) {
LelantusCoin coin = element.values.first;
int anonSetId = coin.anonymitySetId;
if (coin.anonymitySetId == 1 &&
(coin.publicCoin == '' ||
coin.publicCoin == "jmintData.publicCoin")) {
anonSetId = latestSetId!;
}
coins.add({
element.keys.first: LelantusCoin(coin.index, coin.value,
coin.publicCoin, coin.txId, anonSetId, coin.isUsed)
});
}
Logger.print("newcoins $coins", normalLength: false);
await DB.instance.put<dynamic>(
boxName: walletInfo.walletId,
key: '_lelantus_coins',
value: coins);
}
}
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 1);
// try to continue migrating
return await migrate(1, secureStore: secureStore);
case 1:
await Hive.openBox<ExchangeTransaction>(DB.boxNameTrades);
await Hive.openBox<Trade>(DB.boxNameTradesV2);
final trades =
DB.instance.values<ExchangeTransaction>(boxName: DB.boxNameTrades);
for (final old in trades) {
if (old.statusObject != null) {
final trade = Trade.fromExchangeTransaction(old, false);
await DB.instance.put<Trade>(
boxName: DB.boxNameTradesV2,
key: trade.uuid,
value: trade,
);
}
}
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 2);
// try to continue migrating
return await migrate(2, secureStore: secureStore);
case 2:
await Hive.openBox<dynamic>(DB.boxNamePrefs);
final prefs = Prefs.instance;
await prefs.init();
if (!(await prefs.isExternalCallsSet())) {
prefs.externalCalls = true;
}
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 3);
return await migrate(3, secureStore: secureStore);
case 3:
// clear possible broken firo cache
await DB.instance.deleteBoxFromDisk(
boxName: DB.instance.boxNameSetCache(coin: Coin.firo));
await DB.instance.deleteBoxFromDisk(
boxName: DB.instance.boxNameUsedSerialsCache(coin: Coin.firo));
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 4);
// try to continue migrating
return await migrate(4, secureStore: secureStore);
default:
// finally return
return;
}
}
}