mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-26 06:08:40 +01:00
Cw 1551 quick bitcoin wallet sync (#3446)
* add Wallet Accounts page and integrate UI * account model refactor * add walletInfoAccount table and API * add WalletAccountList API * add multi-account support for Electrum wallets * add Bitcoin lightning card and card style handling * refine account filtering and card selection * update current account balance on wallet changes * update configure.dar * Use named parameters for card design * Add Bitcoin account handling and refactor lookup * refactor dashboard * refactor cards UI and account balance handling * Improve Bitcoin account selection and balances * restrict unspent coin usage to current account * filter transactions by current Bitcoin account * refactor electrum wallet * refactor address generation * add accountIndex to address fetch logic * Update configure.dart * reload transactions on Bitcoin account change * restore multiple BTC accounts and improve fetch * show account balance with in btc * track account index in Bitcoin transactions * discover btc BIP39 accounts during restore * fix account switching and card ordering bugs * fix card customizer * limit account name length in modal * update BTC account list balance display * auto-reformat * formating fix * skip HD map validation * fix 0 balance issue * minor fix * quick bitcoin wallet sync * restore shuffle change output * restore address lookup fix * Update electrum.dart * remove account customizer * Merge branch 'CW-1142-Add-accounts-feature-to-BTC' into CW-1551-Quick-Bitcoin-Wallet-Sync * probe only segwit in account discovery * add account discovery limit and tracking * Improve Electrum sync account handling [skip ci] * remove legacy monero account and address list UI * rework BTC account balance refres * avoid unnecessary BTC account reloads * refactor account header in addresses page * fix blank popup when editing an account * fix: dedupe UTXO balance * minor fix * add Bitcoin current account API * Apply batched suggestions from code review [skip ci] Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * address PR review comments [skip ci] * remove account customizer and fix accounts init * restrict extra BTC accounts to SegWit * add BTC multi-account toggle * Fix BTC sync gating and account balance update * minor fix * Update electrum_wallet.dart * store selected account on WalletInfo * Refine wallet account reset visibility * refactor BTC address prep and move accounts page * refactor account stack and customizer routing * migrate legacy Lightning card styles * unify dashboard account change state * fix account routing and Electrum balances * fix account setup and wallet cards UI * disable Bitcoin Accounts for all hardware * merge conflicts fix * minor fixes * update cards_view [skip ci] * reverted cards view update [skip ci] * fix asset name * moved the transaction filtering into the electrum wallet * localization * disable accounts for watch-only wallets * fix: stop card render from switching the wallet account * fix: restore Lightning transactions in tx history * minor fix * fix: skip duplicate legacy address generation [skip ci] * fix: correct account balance/design mismatch bugs * addressing review comments --------- Co-authored-by: Robert Malikowski <malikowskirobert@gmail.com> Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
co-authored by
Omar Hatem
Robert Malikowski
parent
0503d54290
commit
d7ebf42814
@@ -1,12 +1,32 @@
|
||||
class Account {
|
||||
Account({required this.id, required this.label, this.balance});
|
||||
Account({
|
||||
required this.id,
|
||||
required this.label,
|
||||
String? balance,
|
||||
}) : balance = balance ?? "0.00";
|
||||
|
||||
Account.fromMap(Map<String, Object> map)
|
||||
: this.id = map['id'] == null ? 0 : int.parse(map['id'] as String),
|
||||
this.label = (map['label'] ?? '') as String,
|
||||
this.balance = (map['balance'] ?? '0.00') as String;
|
||||
Account.fromMap(Map<String, Object?> map)
|
||||
: id = map["id"] is int ? map["id"] as int : int.tryParse(map["id"]?.toString() ?? "") ?? 0,
|
||||
label = (map["label"] ?? "") as String,
|
||||
balance = (map["balance"] ?? "0.00") as String;
|
||||
|
||||
final int id;
|
||||
final String label;
|
||||
final String? balance;
|
||||
final String balance;
|
||||
|
||||
Account copyWith({
|
||||
int? id,
|
||||
String? label,
|
||||
String? balance,
|
||||
}) => Account(
|
||||
id: id ?? this.id,
|
||||
label: label ?? this.label,
|
||||
balance: balance ?? this.balance,
|
||||
);
|
||||
|
||||
Map<String, Object> toMap() => {
|
||||
"id": id.toString(),
|
||||
"label": label,
|
||||
"balance": balance,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
abstract class AccountList<T> {
|
||||
ObservableList<T> get accounts;
|
||||
|
||||
void update();
|
||||
|
||||
List<T> getAll();
|
||||
|
||||
Future<void> addAccount({required String label});
|
||||
|
||||
Future<void> setLabelAccount({required int accountIndex, required String label});
|
||||
|
||||
void refresh();
|
||||
}
|
||||
@@ -98,6 +98,6 @@ class BalanceCardStyleSettings {
|
||||
}
|
||||
|
||||
Future<void> insert() async {
|
||||
db!.insert(tableName, toJson(), conflictAlgorithm: ConflictAlgorithm.replace);
|
||||
await db!.insert(tableName, toJson(), conflictAlgorithm: ConflictAlgorithm.replace);
|
||||
}
|
||||
}
|
||||
|
||||
+141
-76
@@ -3,6 +3,7 @@ import "dart:io";
|
||||
import "package:cw_core/db/sqlite_debug.dart";
|
||||
import "package:cw_core/root_dir.dart";
|
||||
import "package:cw_core/utils/print_verbose.dart";
|
||||
import "package:cw_core/wallet_type.dart";
|
||||
import "package:flutter/foundation.dart";
|
||||
import "package:path/path.dart" as p;
|
||||
import "package:sqflite_common_ffi/sqflite_ffi.dart";
|
||||
@@ -10,11 +11,11 @@ import "package:sqflite_common_ffi/sqflite_ffi.dart";
|
||||
Database? db;
|
||||
|
||||
Future<void> _addColumnIfNotExists(
|
||||
Database db, {
|
||||
required String table,
|
||||
required String column,
|
||||
required String definition,
|
||||
}) async {
|
||||
Database db, {
|
||||
required String table,
|
||||
required String column,
|
||||
required String definition,
|
||||
}) async {
|
||||
final result = await db.rawQuery("PRAGMA table_info($table)");
|
||||
final columnExists = result.any((row) => row["name"] == column);
|
||||
|
||||
@@ -65,7 +66,7 @@ Future<void> _initDb({String? pathOverride}) async {
|
||||
await db?.close();
|
||||
db = await openDatabase(
|
||||
dbFile.path,
|
||||
version: 13,
|
||||
version: 14,
|
||||
onUpgrade: (db, oldVersion, newVersion) async {
|
||||
printV("migrating: $oldVersion, $newVersion");
|
||||
if (oldVersion <= 1) {
|
||||
@@ -100,77 +101,101 @@ CREATE TABLE IF NOT EXISTS BalanceCardStyleSettings (
|
||||
definition: "BOOLEAN DEFAULT FALSE",
|
||||
);
|
||||
|
||||
await _addColumnIfNotExists(
|
||||
db,
|
||||
table: 'BalanceCardStyleSettings',
|
||||
column: 'cardOrder',
|
||||
definition: 'INTEGER DEFAULT 0',
|
||||
);
|
||||
}
|
||||
if (oldVersion <= 3) {
|
||||
await _addColumnIfNotExists(db,
|
||||
table: "WalletInfo", column: "showCombinedBalance", definition: "BOOLEAN DEFAULT TRUE");
|
||||
// null - primary token (eth, sol etc)
|
||||
// not null - address of fav token
|
||||
// if address doesn't correspond to a valid token, fallback to primary token
|
||||
await _addColumnIfNotExists(db,
|
||||
table: "WalletInfo", column: "favoriteTokenAddress", definition: "TEXT DEFAULT NULL");
|
||||
}
|
||||
await _addColumnIfNotExists(
|
||||
db,
|
||||
table: 'BalanceCardStyleSettings',
|
||||
column: 'cardOrder',
|
||||
definition: 'INTEGER DEFAULT 0',
|
||||
);
|
||||
}
|
||||
if (oldVersion <= 3) {
|
||||
await _addColumnIfNotExists(db,
|
||||
table: "WalletInfo", column: "showCombinedBalance", definition: "BOOLEAN DEFAULT TRUE");
|
||||
// null - primary token (eth, sol etc)
|
||||
// not null - address of fav token
|
||||
// if address doesn't correspond to a valid token, fallback to primary token
|
||||
await _addColumnIfNotExists(db,
|
||||
table: "WalletInfo", column: "favoriteTokenAddress", definition: "TEXT DEFAULT NULL");
|
||||
}
|
||||
|
||||
if (oldVersion <= 4) {
|
||||
await _createBridgeTransferTable(db);
|
||||
}
|
||||
if (oldVersion <= 4) {
|
||||
await _createBridgeTransferTable(db);
|
||||
}
|
||||
|
||||
if (oldVersion <= 5) {
|
||||
await _createTradeTable(db);
|
||||
}
|
||||
if (oldVersion <= 6) {
|
||||
await _addColumnIfNotExists(
|
||||
db,
|
||||
table: 'Trade',
|
||||
column: 'toAddressExtraId',
|
||||
definition: 'TEXT',
|
||||
);
|
||||
}
|
||||
if (oldVersion <= 7) {
|
||||
await _createNodeTable(db);
|
||||
}
|
||||
if (oldVersion <= 8) {
|
||||
await _addColumnIfNotExists(
|
||||
db,
|
||||
table: 'BalanceCardStyleSettings',
|
||||
column: 'iconStyleIndex',
|
||||
definition: 'INTEGER DEFAULT 0',
|
||||
);
|
||||
await _addColumnIfNotExists(
|
||||
db,
|
||||
table: 'BalanceCardStyleSettings',
|
||||
column: 'isGradientOnly',
|
||||
definition: 'BOOLEAN DEFAULT FALSE',
|
||||
);
|
||||
}
|
||||
if (oldVersion <= 9) {
|
||||
await _createErc20TokenTable(db);
|
||||
await _createSplTokenTable(db);
|
||||
await _createTronTokenTable(db);
|
||||
}
|
||||
if (oldVersion <= 5) {
|
||||
await _createTradeTable(db);
|
||||
}
|
||||
if (oldVersion <= 6) {
|
||||
await _addColumnIfNotExists(
|
||||
db,
|
||||
table: 'Trade',
|
||||
column: 'toAddressExtraId',
|
||||
definition: 'TEXT',
|
||||
);
|
||||
}
|
||||
if (oldVersion <= 7) {
|
||||
await _createNodeTable(db);
|
||||
}
|
||||
if (oldVersion <= 8) {
|
||||
await _addColumnIfNotExists(
|
||||
db,
|
||||
table: 'BalanceCardStyleSettings',
|
||||
column: 'iconStyleIndex',
|
||||
definition: 'INTEGER DEFAULT 0',
|
||||
);
|
||||
await _addColumnIfNotExists(
|
||||
db,
|
||||
table: 'BalanceCardStyleSettings',
|
||||
column: 'isGradientOnly',
|
||||
definition: 'BOOLEAN DEFAULT FALSE',
|
||||
);
|
||||
}
|
||||
if (oldVersion <= 9) {
|
||||
await _createErc20TokenTable(db);
|
||||
await _createSplTokenTable(db);
|
||||
await _createTronTokenTable(db);
|
||||
}
|
||||
if (oldVersion <= 10) {
|
||||
await _createImportedNFTTable(db);
|
||||
}
|
||||
if (oldVersion <= 11) {
|
||||
await _addColumnIfNotExists(
|
||||
db,
|
||||
table: "WalletInfo",
|
||||
column: "showSeedBackupReminder",
|
||||
definition: "BOOLEAN DEFAULT FALSE",
|
||||
);
|
||||
}
|
||||
if (oldVersion <= 12) {
|
||||
await _createChartsTables(db);
|
||||
}
|
||||
|
||||
if (oldVersion <= 10) {
|
||||
await _createImportedNFTTable(db);
|
||||
}
|
||||
if (oldVersion <= 11) {
|
||||
await _addColumnIfNotExists(
|
||||
db,
|
||||
table: "WalletInfo",
|
||||
column: "showSeedBackupReminder",
|
||||
definition: "BOOLEAN DEFAULT FALSE",
|
||||
);
|
||||
}
|
||||
if(oldVersion <= 12) {
|
||||
await _createChartsTables(db);
|
||||
}
|
||||
}, onCreate: (Database db, int version) async {
|
||||
await db.execute('''
|
||||
if (oldVersion <= 13) {
|
||||
await _createWalletInfoAccountTable(db);
|
||||
await _addColumnIfNotExists(
|
||||
db,
|
||||
table: "WalletInfo",
|
||||
column: "accountDiscoveryLimit",
|
||||
definition: "INTEGER DEFAULT NULL",
|
||||
);
|
||||
await _addColumnIfNotExists(
|
||||
db,
|
||||
table: "WalletInfo",
|
||||
column: "isMultiAccountsEnabled",
|
||||
definition: "INTEGER DEFAULT NULL",
|
||||
);
|
||||
await _addColumnIfNotExists(
|
||||
db,
|
||||
table: "WalletInfo",
|
||||
column: "currentAccountIndex",
|
||||
definition: "INTEGER NOT NULL DEFAULT 0",
|
||||
);
|
||||
|
||||
await _migrateBitcoinCardStylesForAccounts(db);
|
||||
}
|
||||
},
|
||||
onCreate: (Database db, int version) async {
|
||||
await db.execute('''
|
||||
CREATE TABLE WalletInfo (
|
||||
walletInfoId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
id TEXT NOT NULL,
|
||||
@@ -193,9 +218,12 @@ CREATE TABLE WalletInfo (
|
||||
hashedWalletIdentifier TEXT,
|
||||
isNonSeedWallet INTEGER DEFAULT (0) NOT NULL,
|
||||
sortOrder INTEGER DEFAULT (0) NOT NULL,
|
||||
currentAccountIndex INTEGER NOT NULL DEFAULT 0,
|
||||
receiveInfoboxDismissed BOOLEAN DEFAULT FALSE,
|
||||
showCombinedBalance BOOLEAN DEFAULT TRUE,
|
||||
favoriteTokenAddress TEXT DEFAULT NULL,
|
||||
accountDiscoveryLimit INTEGER DEFAULT NULL,
|
||||
isMultiAccountsEnabled INTEGER DEFAULT NULL,
|
||||
showSeedBackupReminder BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
''');
|
||||
@@ -269,8 +297,8 @@ CREATE TABLE BalanceCardStyleSettings (
|
||||
await _createErc20TokenTable(db);
|
||||
await _createSplTokenTable(db);
|
||||
await _createTronTokenTable(db);
|
||||
await _createImportedNFTTable(db);
|
||||
|
||||
await _createImportedNFTTable(db);
|
||||
await _createWalletInfoAccountTable(db);
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -356,6 +384,43 @@ ON Trade (id);
|
||||
""");
|
||||
}
|
||||
|
||||
Future<void> _createWalletInfoAccountTable(Database db) async {
|
||||
await db.execute("""
|
||||
CREATE TABLE IF NOT EXISTS WalletInfoAccount (
|
||||
walletInfoId INTEGER NOT NULL,
|
||||
accountIndex INTEGER NOT NULL,
|
||||
label TEXT NOT NULL,
|
||||
PRIMARY KEY (walletInfoId, accountIndex),
|
||||
CONSTRAINT WalletInfoAccount_WalletInfo_FK FOREIGN KEY (walletInfoId) REFERENCES WalletInfo(walletInfoId)
|
||||
);
|
||||
""");
|
||||
|
||||
await db.execute("""
|
||||
CREATE INDEX IF NOT EXISTS idx_walletinfoaccount_walletinfoid
|
||||
ON WalletInfoAccount(walletInfoId);
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
Future<void> _migrateBitcoinCardStylesForAccounts(Database db) async {
|
||||
const bitcoinWallets = 'SELECT walletInfoId FROM WalletInfo WHERE "type" = ?';
|
||||
final btc = WalletType.bitcoin.index;
|
||||
|
||||
// Lightning: 0 -> -2 (first, so accountIndex 0 is free for the Bitcoin card)
|
||||
await db.rawUpdate(
|
||||
"UPDATE OR REPLACE BalanceCardStyleSettings SET accountIndex = -2 "
|
||||
"WHERE accountIndex = 0 AND walletInfoId IN ($bitcoinWallets)",
|
||||
[btc],
|
||||
);
|
||||
|
||||
// Bitcoin: -1 -> 0 (primary account, first in order)
|
||||
await db.rawUpdate(
|
||||
"UPDATE OR REPLACE BalanceCardStyleSettings SET accountIndex = 0, cardOrder = 0 "
|
||||
"WHERE accountIndex = -1 AND walletInfoId IN ($bitcoinWallets)",
|
||||
[btc],
|
||||
);
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> dumpDb() async {
|
||||
try {
|
||||
return await _dumpDb();
|
||||
|
||||
@@ -142,6 +142,10 @@ abstract class WalletBase<BalanceType extends Balance, HistoryType extends Trans
|
||||
bool get hasLightningSupport => false;
|
||||
bool get hasSilentPaymentsScanning => false;
|
||||
|
||||
bool get hasAccountsSupport => false;
|
||||
bool get hasNativeAccounts => false;
|
||||
bool get canToggleMultiAccounts => hasAccountsSupport && !hasNativeAccounts;
|
||||
|
||||
// hardware wallet - bitbox, ledger, trezor.
|
||||
// we also have airgap wallets but those can't sign messages
|
||||
bool get canSignMessages => walletInfo.hardwareWalletType == null || walletInfo.isHardwareWallet;
|
||||
|
||||
+206
-47
@@ -244,6 +244,68 @@ class WalletInfoAddress {
|
||||
}
|
||||
}
|
||||
|
||||
class WalletInfoAccount {
|
||||
WalletInfoAccount({
|
||||
required this.walletInfoId,
|
||||
required this.accountIndex,
|
||||
required this.label,
|
||||
});
|
||||
|
||||
factory WalletInfoAccount.fromJson(Map<String, dynamic> json) => WalletInfoAccount(
|
||||
walletInfoId: json["walletInfoId"] as int,
|
||||
accountIndex: json["accountIndex"] as int,
|
||||
label: json["label"] as String,
|
||||
);
|
||||
|
||||
int walletInfoId;
|
||||
int accountIndex;
|
||||
String label;
|
||||
|
||||
static String get tableName => "walletInfoAccount";
|
||||
|
||||
static Future<List<WalletInfoAccount>> selectList(int walletInfoId) async {
|
||||
final query = await db!.query(
|
||||
tableName,
|
||||
where: "walletInfoId = ?",
|
||||
whereArgs: [walletInfoId],
|
||||
orderBy: "accountIndex ASC",
|
||||
);
|
||||
|
||||
return List.generate(query.length, (index) => WalletInfoAccount.fromJson(query[index]));
|
||||
}
|
||||
|
||||
static Future<int> deleteByWalletInfoId(int walletInfoId) async =>
|
||||
await db!.delete(tableName, where: "walletInfoId = ?", whereArgs: [walletInfoId]);
|
||||
|
||||
static Future<int> insertOrUpdate({
|
||||
required int walletInfoId,
|
||||
required int accountIndex,
|
||||
required String label,
|
||||
}) async =>
|
||||
await db!.transaction((txn) async {
|
||||
final updated = await txn.update(
|
||||
tableName,
|
||||
{"label": label},
|
||||
where: "walletInfoId = ? AND accountIndex = ?",
|
||||
whereArgs: [walletInfoId, accountIndex],
|
||||
);
|
||||
|
||||
if (updated > 0) return updated;
|
||||
|
||||
return await txn.insert(tableName, {
|
||||
"walletInfoId": walletInfoId,
|
||||
"accountIndex": accountIndex,
|
||||
"label": label,
|
||||
});
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"walletInfoId": walletInfoId,
|
||||
"accountIndex": accountIndex,
|
||||
"label": label,
|
||||
};
|
||||
}
|
||||
|
||||
class DerivationInfo {
|
||||
DerivationInfo({
|
||||
this.id = 0,
|
||||
@@ -346,6 +408,7 @@ class WalletInfo {
|
||||
this.hashedWalletIdentifier,
|
||||
this.isNonSeedWallet,
|
||||
this.sortOrder,
|
||||
this.currentAccountIndex,
|
||||
this.addressPageType,
|
||||
this.receiveInfoboxDismissed,
|
||||
this.showCombinedBalance,
|
||||
@@ -353,53 +416,65 @@ class WalletInfo {
|
||||
this.showSeedBackupReminder)
|
||||
: _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 = '',
|
||||
int? derivationInfoId,
|
||||
HardwareWalletType? hardwareWalletType,
|
||||
String? parentAddress,
|
||||
String? hashedWalletIdentifier,
|
||||
bool? isNonSeedWallet,
|
||||
int? sortOrder,
|
||||
bool? receiveInfoboxDismissed,
|
||||
bool? showCombinedBalance,
|
||||
String? favoriteTokenAddress}) {
|
||||
return WalletInfo(
|
||||
0,
|
||||
id,
|
||||
name,
|
||||
type,
|
||||
isRecovery,
|
||||
restoreHeight,
|
||||
date.millisecondsSinceEpoch,
|
||||
dirPath,
|
||||
path,
|
||||
address,
|
||||
yatEid,
|
||||
yatLastUsedAddressRaw,
|
||||
showIntroCakePayCard,
|
||||
derivationInfoId ?? -1,
|
||||
hardwareWalletType,
|
||||
parentAddress,
|
||||
hashedWalletIdentifier,
|
||||
isNonSeedWallet ?? false,
|
||||
sortOrder ?? 0,
|
||||
null,
|
||||
receiveInfoboxDismissed ?? false,
|
||||
showCombinedBalance ?? true,
|
||||
favoriteTokenAddress,
|
||||
false);
|
||||
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 = "",
|
||||
int? derivationInfoId,
|
||||
HardwareWalletType? hardwareWalletType,
|
||||
String? parentAddress,
|
||||
String? hashedWalletIdentifier,
|
||||
bool? isNonSeedWallet,
|
||||
int? sortOrder,
|
||||
int currentAccountIndex = 0,
|
||||
bool? receiveInfoboxDismissed,
|
||||
bool? showCombinedBalance,
|
||||
String? favoriteTokenAddress,
|
||||
}) {
|
||||
final wi = WalletInfo(
|
||||
0,
|
||||
id,
|
||||
name,
|
||||
type,
|
||||
isRecovery,
|
||||
restoreHeight,
|
||||
date.millisecondsSinceEpoch,
|
||||
dirPath,
|
||||
path,
|
||||
address,
|
||||
yatEid.isNotEmpty ? yatEid : null,
|
||||
yatLastUsedAddressRaw.isNotEmpty ? yatLastUsedAddressRaw : null,
|
||||
showIntroCakePayCard ?? false,
|
||||
derivationInfoId ?? -1,
|
||||
hardwareWalletType,
|
||||
parentAddress,
|
||||
hashedWalletIdentifier,
|
||||
isNonSeedWallet ?? false,
|
||||
sortOrder ?? 0,
|
||||
currentAccountIndex,
|
||||
null,
|
||||
receiveInfoboxDismissed ?? false,
|
||||
showCombinedBalance ?? true,
|
||||
favoriteTokenAddress?.isNotEmpty == true ? favoriteTokenAddress : null,
|
||||
false,
|
||||
);
|
||||
|
||||
if (type == WalletType.bitcoin) {
|
||||
wi.isMultiAccountsEnabled = false;
|
||||
} else if (type == WalletType.monero || type == WalletType.wownero) {
|
||||
wi.isMultiAccountsEnabled = true;
|
||||
}
|
||||
|
||||
return wi;
|
||||
}
|
||||
|
||||
static String get tableName => 'walletInfo';
|
||||
@@ -408,6 +483,8 @@ class WalletInfo {
|
||||
|
||||
int internalId;
|
||||
|
||||
int currentAccountIndex;
|
||||
|
||||
String id;
|
||||
String name;
|
||||
WalletType type;
|
||||
@@ -506,8 +583,76 @@ class WalletInfo {
|
||||
await WalletInfoAddress.insert(internalId, type, address);
|
||||
}
|
||||
|
||||
Future<List<WalletInfoAccount>> getAccounts() async {
|
||||
var accounts = await WalletInfoAccount.selectList(internalId);
|
||||
|
||||
if (accounts.isEmpty) {
|
||||
await WalletInfoAccount.insertOrUpdate(
|
||||
walletInfoId: internalId,
|
||||
accountIndex: 0,
|
||||
label: "Primary account",
|
||||
);
|
||||
|
||||
accounts = await WalletInfoAccount.selectList(internalId);
|
||||
}
|
||||
|
||||
if (!accounts.any((a) => a.accountIndex == currentAccountIndex)) {
|
||||
currentAccountIndex = accounts.first.accountIndex;
|
||||
await save();
|
||||
}
|
||||
|
||||
return accounts;
|
||||
}
|
||||
|
||||
Future<void> setSelectedAccount(int accountIndex) async {
|
||||
currentAccountIndex = accountIndex;
|
||||
await save();
|
||||
}
|
||||
|
||||
Future<void> setAccounts(List<WalletInfoAccount> accounts) async {
|
||||
await WalletInfoAccount.deleteByWalletInfoId(internalId);
|
||||
|
||||
for (final account in accounts) {
|
||||
await WalletInfoAccount.insertOrUpdate(
|
||||
walletInfoId: internalId,
|
||||
accountIndex: account.accountIndex,
|
||||
label: account.label,
|
||||
);
|
||||
}
|
||||
|
||||
if (accounts.isNotEmpty && !accounts.any((a) => a.accountIndex == currentAccountIndex)) {
|
||||
currentAccountIndex = accounts.first.accountIndex;
|
||||
await save();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> addAccount({
|
||||
required int accountIndex,
|
||||
required String label,
|
||||
}) async {
|
||||
await WalletInfoAccount.insertOrUpdate(
|
||||
walletInfoId: internalId,
|
||||
accountIndex: accountIndex,
|
||||
label: label,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> renameAccount({
|
||||
required int accountIndex,
|
||||
required String label,
|
||||
}) async {
|
||||
await WalletInfoAccount.insertOrUpdate(
|
||||
walletInfoId: internalId,
|
||||
accountIndex: accountIndex,
|
||||
label: label,
|
||||
);
|
||||
}
|
||||
|
||||
String? addressPageType;
|
||||
String? network;
|
||||
int? accountDiscoveryLimit;
|
||||
bool? isMultiAccountsEnabled;
|
||||
|
||||
int derivationInfoId;
|
||||
DerivationInfo? _derivationInfo;
|
||||
|
||||
@@ -586,12 +731,16 @@ class WalletInfo {
|
||||
"hashedWalletIdentifier": hashedWalletIdentifier,
|
||||
"isNonSeedWallet": isNonSeedWallet ? 1 : 0,
|
||||
"sortOrder": sortOrder,
|
||||
"currentAccountIndex": currentAccountIndex,
|
||||
"addressPageType": addressPageType,
|
||||
"receiveInfoboxDismissed": receiveInfoboxDismissed ? 1 : 0,
|
||||
"showCombinedBalance": showCombinedBalance ? 1 : 0,
|
||||
"favoriteTokenAddress": favoriteTokenAddress,
|
||||
"showSeedBackupReminder": showSeedBackupReminder ? 1 : 0,
|
||||
"network": network,
|
||||
"accountDiscoveryLimit": accountDiscoveryLimit,
|
||||
"isMultiAccountsEnabled":
|
||||
isMultiAccountsEnabled == null ? null : (isMultiAccountsEnabled! ? 1 : 0),
|
||||
};
|
||||
|
||||
factory WalletInfo.fromJson(Map<String, dynamic> json) {
|
||||
@@ -617,12 +766,17 @@ class WalletInfo {
|
||||
json['hashedWalletIdentifier'] as String?,
|
||||
(json['isNonSeedWallet'] as int) == 1,
|
||||
json['sortOrder'] as int? ?? 0,
|
||||
json['currentAccountIndex'] as int? ?? 0,
|
||||
json['addressPageType'] as String? ?? null,
|
||||
json['receiveInfoboxDismissed'] != 0,
|
||||
json["showCombinedBalance"] != 0,
|
||||
json["favoriteTokenAddress"] as String? ?? null,
|
||||
json["showSeedBackupReminder"] == 1);
|
||||
info.network = json['network'] as String?;
|
||||
info.accountDiscoveryLimit = json['accountDiscoveryLimit'] as int?;
|
||||
final rawIsMultiAccountsEnabled = json['isMultiAccountsEnabled'];
|
||||
info.isMultiAccountsEnabled =
|
||||
rawIsMultiAccountsEnabled == null ? null : (rawIsMultiAccountsEnabled as int) == 1;
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -670,6 +824,11 @@ class WalletInfo {
|
||||
await save();
|
||||
}
|
||||
|
||||
Future<void> setAccountDiscoveryLimit(int limit) async {
|
||||
accountDiscoveryLimit = limit;
|
||||
await save();
|
||||
}
|
||||
|
||||
Future<void> clearSeedBackupReminder() async {
|
||||
final previous = showSeedBackupReminder;
|
||||
showSeedBackupReminder = false;
|
||||
|
||||
@@ -271,6 +271,7 @@ class WalletInfo extends HiveObject {
|
||||
hashedWalletIdentifier,
|
||||
isNonSeedWallet,
|
||||
0,
|
||||
0,
|
||||
addressPageType,
|
||||
false,
|
||||
true,
|
||||
|
||||
Reference in New Issue
Block a user