mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-21 06:18:42 +02:00
* feat: initial hive -> SQLite Includes migration script and initial work done to remove dependency on hive generators. Also contains some refactoring to make sync code async. Features new dev screen that lists all SQLite tables Aspects that need testing: - backups (from this version, and from previous versions as well) - wallet loading / wallet list - almost everything else - renaming - deletion - sorting in wallet list - wallet groups - wallet seed/keys - wallet switching - wallet creation / restore - all methods - wallet address page - hardware wallet connection (and prompts from mall screens) - contacts - advanced settings in wallet creation - derivation paths - some minor wownero fixes - base, hardware wallets * fix: build errors * fix: Bad state: No element in backup restore * address comments from review * fix: HardwareWalletType
309 lines
7.3 KiB
Dart
309 lines
7.3 KiB
Dart
// NOTE: This code was generated by Hive, but since Hive is on the way out, this
|
|
// code no longer uses hive generators, so when we get rid of hive we also will
|
|
// be able to get rid of
|
|
|
|
import 'dart:async';
|
|
|
|
import 'package:cw_core/utils/print_verbose.dart';
|
|
import 'package:cw_core/wallet_info.dart' as newWi;
|
|
import 'package:cw_core/address_info.dart';
|
|
import 'package:cw_core/hive_type_ids.dart';
|
|
import 'package:cw_core/wallet_type.dart';
|
|
import 'package:hive/hive.dart';
|
|
|
|
part 'wallet_info_legacy.part.dart';
|
|
|
|
// // @HiveType(typeId: DERIVATION_TYPE_TYPE_ID)
|
|
// enum DerivationType {
|
|
// // @HiveField(0)
|
|
// unknown,
|
|
// // @HiveField(1)
|
|
// def, // default is a reserved word
|
|
// // @HiveField(2)
|
|
// nano,
|
|
// // @HiveField(3)
|
|
// bip39,
|
|
// // @HiveField(4)
|
|
// electrum,
|
|
// }
|
|
|
|
// // @HiveType(typeId: HARDWARE_WALLET_TYPE_TYPE_ID)
|
|
// enum HardwareWalletType {
|
|
// // @HiveField(0)
|
|
// ledger,
|
|
// }
|
|
|
|
// @HiveType(typeId: DerivationInfo.typeId)
|
|
class DerivationInfo extends HiveObject {
|
|
DerivationInfo({
|
|
this.derivationType,
|
|
this.derivationPath,
|
|
this.balance = "",
|
|
this.address = "",
|
|
this.transactionsCount = 0,
|
|
this.scriptType,
|
|
this.description,
|
|
});
|
|
|
|
static const typeId = DERIVATION_INFO_TYPE_ID;
|
|
|
|
// @HiveField(0, defaultValue: '')
|
|
String address;
|
|
|
|
// @HiveField(1, defaultValue: '')
|
|
String balance;
|
|
|
|
// @HiveField(2, defaultValue: 0)
|
|
int transactionsCount;
|
|
|
|
// @HiveField(3)
|
|
newWi.DerivationType? derivationType;
|
|
|
|
// @HiveField(4)
|
|
String? derivationPath;
|
|
|
|
// @HiveField(5)
|
|
final String? scriptType;
|
|
|
|
// @HiveField(6)
|
|
final String? description;
|
|
}
|
|
|
|
// @HiveType(typeId: WalletInfo.typeId)
|
|
class WalletInfo extends HiveObject {
|
|
WalletInfo(
|
|
this.id,
|
|
this.name,
|
|
this.type,
|
|
this.isRecovery,
|
|
this.restoreHeight,
|
|
this.timestamp,
|
|
this.dirPath,
|
|
this.path,
|
|
this.address,
|
|
this.yatEid,
|
|
this.yatLastUsedAddressRaw,
|
|
this.showIntroCakePayCard,
|
|
this.derivationInfo,
|
|
this.hardwareWalletType,
|
|
this.parentAddress,
|
|
this.hashedWalletIdentifier,
|
|
this.isNonSeedWallet,
|
|
) : _yatLastUsedAddressController = StreamController<String>.broadcast();
|
|
|
|
factory WalletInfo.external({
|
|
required String id,
|
|
required String name,
|
|
required WalletType type,
|
|
required bool isRecovery,
|
|
required int restoreHeight,
|
|
required DateTime date,
|
|
required String dirPath,
|
|
required String path,
|
|
required String address,
|
|
bool? showIntroCakePayCard,
|
|
String yatEid = '',
|
|
String yatLastUsedAddressRaw = '',
|
|
DerivationInfo? derivationInfo,
|
|
newWi.HardwareWalletType? hardwareWalletType,
|
|
String? parentAddress,
|
|
String? hashedWalletIdentifier,
|
|
bool? isNonSeedWallet,
|
|
}) {
|
|
return WalletInfo(
|
|
id,
|
|
name,
|
|
type,
|
|
isRecovery,
|
|
restoreHeight,
|
|
date.millisecondsSinceEpoch,
|
|
dirPath,
|
|
path,
|
|
address,
|
|
yatEid,
|
|
yatLastUsedAddressRaw,
|
|
showIntroCakePayCard,
|
|
derivationInfo,
|
|
hardwareWalletType,
|
|
parentAddress,
|
|
hashedWalletIdentifier,
|
|
isNonSeedWallet ?? false,
|
|
);
|
|
}
|
|
|
|
static const typeId = WALLET_INFO_TYPE_ID;
|
|
static const boxName = 'WalletInfo';
|
|
|
|
// @HiveField(0, defaultValue: '')
|
|
String id;
|
|
|
|
// @HiveField(1, defaultValue: '')
|
|
String name;
|
|
|
|
// @HiveField(2)
|
|
WalletType type;
|
|
|
|
// @HiveField(3, defaultValue: false)
|
|
bool isRecovery;
|
|
|
|
// @HiveField(4, defaultValue: 0)
|
|
int restoreHeight;
|
|
|
|
// @HiveField(5, defaultValue: 0)
|
|
int timestamp;
|
|
|
|
// @HiveField(6, defaultValue: '')
|
|
String dirPath;
|
|
|
|
// @HiveField(7, defaultValue: '')
|
|
String path;
|
|
|
|
// @HiveField(8, defaultValue: '')
|
|
String address;
|
|
|
|
// @HiveField(10)
|
|
Map<String, String>? addresses;
|
|
|
|
// @HiveField(11)
|
|
String? yatEid;
|
|
|
|
// @HiveField(12)
|
|
String? yatLastUsedAddressRaw;
|
|
|
|
// @HiveField(13)
|
|
bool? showIntroCakePayCard;
|
|
|
|
// @HiveField(14)
|
|
Map<int, List<AddressInfo>>? addressInfos;
|
|
|
|
// @HiveField(15)
|
|
List<String>? usedAddresses;
|
|
|
|
@deprecated
|
|
// @HiveField(16)
|
|
newWi.DerivationType? derivationType; // no longer used
|
|
|
|
@deprecated
|
|
// @HiveField(17)
|
|
String? derivationPath; // no longer used
|
|
|
|
// @HiveField(18)
|
|
String? addressPageType;
|
|
|
|
// @HiveField(19)
|
|
String? network;
|
|
|
|
// @HiveField(20)
|
|
DerivationInfo? derivationInfo;
|
|
|
|
// @HiveField(21)
|
|
newWi.HardwareWalletType? hardwareWalletType;
|
|
|
|
// @HiveField(22)
|
|
String? parentAddress;
|
|
|
|
// @HiveField(23)
|
|
List<String>? hiddenAddresses;
|
|
|
|
// @HiveField(24)
|
|
List<String>? manualAddresses;
|
|
|
|
// @HiveField(25)
|
|
String? hashedWalletIdentifier;
|
|
|
|
// @HiveField(26, defaultValue: false)
|
|
bool isNonSeedWallet;
|
|
|
|
String get yatLastUsedAddress => yatLastUsedAddressRaw ?? '';
|
|
|
|
set yatLastUsedAddress(String address) {
|
|
yatLastUsedAddressRaw = address;
|
|
_yatLastUsedAddressController.add(address);
|
|
}
|
|
|
|
String get yatEmojiId => yatEid ?? '';
|
|
|
|
bool get isShowIntroCakePayCard {
|
|
if (showIntroCakePayCard == null) {
|
|
return type != WalletType.haven;
|
|
}
|
|
return showIntroCakePayCard!;
|
|
}
|
|
|
|
bool get isHardwareWallet => hardwareWalletType != null;
|
|
|
|
DateTime get date => DateTime.fromMillisecondsSinceEpoch(timestamp);
|
|
|
|
Stream<String> get yatLastUsedAddressStream => _yatLastUsedAddressController.stream;
|
|
|
|
StreamController<String> _yatLastUsedAddressController;
|
|
|
|
Future<void> updateRestoreHeight(int height) async {
|
|
restoreHeight = height;
|
|
await save();
|
|
}
|
|
|
|
Future<void> migrateToSqlite() async {
|
|
final di = newWi.DerivationInfo(
|
|
id: 0,
|
|
derivationType: derivationInfo?.derivationType ?? derivationType ?? newWi.DerivationType.unknown,
|
|
derivationPath: derivationInfo?.derivationPath ?? derivationPath ?? '',
|
|
);
|
|
final derivationInfoId = await di.save();
|
|
final walletInfo = newWi.WalletInfo(
|
|
0,
|
|
id,
|
|
name,
|
|
type,
|
|
isRecovery,
|
|
restoreHeight,
|
|
timestamp,
|
|
dirPath,
|
|
path,
|
|
address,
|
|
yatEid,
|
|
yatLastUsedAddressRaw,
|
|
showIntroCakePayCard,
|
|
derivationInfoId,
|
|
hardwareWalletType,
|
|
parentAddress,
|
|
hashedWalletIdentifier,
|
|
isNonSeedWallet,
|
|
0,
|
|
);
|
|
final wiId = await walletInfo.save();
|
|
for (final address in usedAddresses ?? <String>[]) {
|
|
await newWi.WalletInfoAddress.insert(wiId, newWi.WalletInfoAddressType.used, address);
|
|
}
|
|
for (final address in hiddenAddresses ?? <String>[]) {
|
|
await newWi.WalletInfoAddress.insert(wiId, newWi.WalletInfoAddressType.hidden, address);
|
|
}
|
|
for (final address in manualAddresses ?? <String>[]) {
|
|
await newWi.WalletInfoAddress.insert(wiId, newWi.WalletInfoAddressType.manual, address);
|
|
}
|
|
for (int i = 0; i < (addressInfos?.length ?? 0); i++) {
|
|
for (final address in addressInfos![i] ?? <AddressInfo>[]) {
|
|
await newWi.WalletInfoAddressInfo.insert(
|
|
walletInfoId: wiId,
|
|
mapKey: i,
|
|
accountIndex: address.accountIndex??0,
|
|
address: address.address,
|
|
label: address.label,
|
|
);
|
|
}
|
|
}
|
|
await walletInfo.setAddresses(addresses ?? <String, String>{});
|
|
}
|
|
|
|
static Future<void> migrateAllToSqlite(final Box<WalletInfo> box) async {
|
|
printV('Migrating WalletInfo to SQLite: start');
|
|
final sw = Stopwatch()..start();
|
|
final list = box.values.toList();
|
|
for (final wi in list) {
|
|
await wi.migrateToSqlite();
|
|
await wi.delete();
|
|
}
|
|
printV('Migrating WalletInfo to SQLite: end (${sw.elapsedMilliseconds}ms)');
|
|
}
|
|
}
|