mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-26 06:08:40 +01:00
* 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>
592 lines
16 KiB
Dart
592 lines
16 KiB
Dart
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";
|
|
|
|
Database? db;
|
|
|
|
Future<void> _addColumnIfNotExists(
|
|
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);
|
|
|
|
if (!columnExists) {
|
|
await db.execute(
|
|
"ALTER TABLE $table ADD COLUMN $column $definition;",
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<File> sqliteDebugMarkerFile() async {
|
|
final appDir = await getAppDir();
|
|
final dbDebugMarker = p.join(appDir.path, ".sqlite_db_debug");
|
|
return File(dbDebugMarker);
|
|
}
|
|
|
|
Future<void> initDb({String? pathOverride}) async {
|
|
if (!kDebugMode && !kProfileMode) {
|
|
await _initDb(pathOverride: pathOverride);
|
|
return;
|
|
}
|
|
final dbDebugMarker = await sqliteDebugMarkerFile();
|
|
try {
|
|
if (dbDebugMarker.existsSync()) {
|
|
throw Exception("Debug marker is present");
|
|
}
|
|
await _initDb(pathOverride: pathOverride);
|
|
} catch (e, s) {
|
|
await handleSqliteError(e, s);
|
|
}
|
|
}
|
|
|
|
Future<void> _initDb({String? pathOverride}) async {
|
|
if (Platform.isLinux || Platform.isWindows) {
|
|
databaseFactory = databaseFactoryFfi;
|
|
}
|
|
|
|
// getAppDir is predictable on all platforms and ensures the db gets included in backups.
|
|
final dbFileOld = File("${await getDatabasesPath()}/cake.db");
|
|
final dbFile = File("${(await getAppDir()).path}/cake.db");
|
|
|
|
if (Platform.isAndroid && dbFileOld.existsSync() && dbFileOld.path != dbFile.path) {
|
|
final copied = dbFileOld.copySync(dbFile.path);
|
|
if (copied.existsSync()) {
|
|
dbFileOld.deleteSync();
|
|
}
|
|
}
|
|
await db?.close();
|
|
db = await openDatabase(
|
|
dbFile.path,
|
|
version: 14,
|
|
onUpgrade: (db, oldVersion, newVersion) async {
|
|
printV("migrating: $oldVersion, $newVersion");
|
|
if (oldVersion <= 1) {
|
|
await db.execute("""
|
|
DELETE FROM WalletInfo
|
|
WHERE walletInfoId NOT IN (
|
|
SELECT MIN(walletInfoId)
|
|
FROM WalletInfo
|
|
GROUP BY id
|
|
);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_walletinfo_id_unique
|
|
ON WalletInfo (id);
|
|
""");
|
|
}
|
|
if (oldVersion <= 2) {
|
|
await db.execute('''
|
|
CREATE TABLE IF NOT EXISTS BalanceCardStyleSettings (
|
|
walletInfoId INTEGER,
|
|
accountIndex INTEGER DEFAULT -1,
|
|
gradientIndex INTEGER DEFAULT -1,
|
|
useSpecialDesign BOOLEAN DEFAULT FALSE,
|
|
backgroundImagePath TEXT DEFAULT "",
|
|
PRIMARY KEY (walletInfoId, accountIndex),
|
|
FOREIGN KEY (walletInfoId) REFERENCES WalletInfo(walletInfoId)
|
|
);
|
|
''');
|
|
await _addColumnIfNotExists(
|
|
db,
|
|
table: "WalletInfo",
|
|
column: "receiveInfoboxDismissed",
|
|
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");
|
|
}
|
|
|
|
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 <= 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 <= 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,
|
|
name TEXT NOT NULL,
|
|
"type" INTEGER NOT NULL,
|
|
isRecovery INTEGER DEFAULT (0) NOT NULL,
|
|
walletInfoDerivationInfoId INTEGER NOT NULL,
|
|
restoreHeight INTEGER DEFAULT (0) NOT NULL,
|
|
"timestamp" INTEGER DEFAULT (0) NOT NULL,
|
|
dirPath TEXT NOT NULL,
|
|
"path" TEXT NOT NULL,
|
|
address TEXT NOT NULL,
|
|
yatEid TEXT,
|
|
yatLastUsedAddressRaw TEXT,
|
|
showIntroCakePayCard INTEGER DEFAULT (1),
|
|
addressPageType TEXT,
|
|
network TEXT,
|
|
hardwareWalletType INTEGER,
|
|
parentAddress TEXT,
|
|
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
|
|
);
|
|
''');
|
|
|
|
await db.execute("""
|
|
CREATE TABLE WalletInfoDerivationInfo (
|
|
walletInfoDerivationInfoId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
address TEXT NOT NULL,
|
|
balance TEXT NOT NULL,
|
|
transactionsCount INTEGER DEFAULT (0) NOT NULL,
|
|
derivationType INTEGER NOT NULL,
|
|
derivationPath TEXT,
|
|
scriptType TEXT,
|
|
description TEXT
|
|
);
|
|
""");
|
|
|
|
await db.execute('''
|
|
CREATE TABLE WalletInfoAddress (
|
|
walletInfoAddressId INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
walletInfoId INTEGER,
|
|
"type" INTEGER NOT NULL,
|
|
address TEXT NOT NULL,
|
|
CONSTRAINT WalletInfoAddress_WalletInfo_FK FOREIGN KEY (walletInfoId) REFERENCES WalletInfo(walletInfoId)
|
|
);
|
|
''');
|
|
|
|
await db.execute("""
|
|
CREATE TABLE WalletInfoAddressInfo (
|
|
walletInfoAddressInfoId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
walletInfoId INTEGER NOT NULL,
|
|
mapKey INTEGER NOT NULL,
|
|
mapValueAccountIndex INTEGER NOT NULL,
|
|
mapValueAddress TEXT NOT NULL,
|
|
mapValueLabel TEXT NOT NULL,
|
|
CONSTRAINT WalletInfoAddressInfo_WalletInfo_FK FOREIGN KEY (walletInfoId) REFERENCES WalletInfo(walletInfoId)
|
|
);
|
|
""");
|
|
|
|
await db.execute('''
|
|
CREATE TABLE "WalletInfoAddressMap" (
|
|
walletInfoAddressMapId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
walletInfoId INTEGER NOT NULL,
|
|
addressKey TEXT NOT NULL,
|
|
addressValue TEXT NOT NULL,
|
|
CONSTRAINT WalletInfoAddress_WalletInfo_FK FOREIGN KEY (walletInfoId) REFERENCES WalletInfo(walletInfoId)
|
|
);
|
|
''');
|
|
await db.execute("""
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_walletinfo_id_unique
|
|
ON WalletInfo (id);
|
|
""");
|
|
await db.execute('''
|
|
CREATE TABLE BalanceCardStyleSettings (
|
|
walletInfoId INTEGER,
|
|
accountIndex INTEGER DEFAULT -1,
|
|
gradientIndex INTEGER DEFAULT -1,
|
|
useSpecialDesign BOOLEAN DEFAULT FALSE,
|
|
backgroundImagePath TEXT DEFAULT "",
|
|
iconStyleIndex INTEGER DEFAULT 0,
|
|
isGradientOnly BOOLEAN DEFAULT FALSE,
|
|
cardOrder INTEGER DEFAULT 0,
|
|
PRIMARY KEY (walletInfoId, accountIndex),
|
|
FOREIGN KEY (walletInfoId) REFERENCES WalletInfo(walletInfoId)
|
|
);
|
|
''');
|
|
await _createBridgeTransferTable(db);
|
|
await _createNodeTable(db);
|
|
await _createTradeTable(db);
|
|
await _createChartsTables(db);
|
|
await _createErc20TokenTable(db);
|
|
await _createSplTokenTable(db);
|
|
await _createTronTokenTable(db);
|
|
await _createImportedNFTTable(db);
|
|
await _createWalletInfoAccountTable(db);
|
|
},
|
|
);
|
|
}
|
|
|
|
Future<void> _createChartsTables(Database db) async {
|
|
await db.execute("""
|
|
CREATE TABLE PriceData (
|
|
fromCurrency TEXT NOT NULL,
|
|
toCurrency TEXT NOT NULL,
|
|
timestamp INTEGER NOT NULL,
|
|
price TEXT NOT NULL,
|
|
PRIMARY KEY (fromCurrency, toCurrency, timestamp)
|
|
);
|
|
""");
|
|
await db.execute("""
|
|
CREATE TABLE ChartsAssets (
|
|
asset TEXT PRIMARY KEY,
|
|
isFavorite BOOLEAN DEFAULT FALSE
|
|
);
|
|
""");
|
|
}
|
|
|
|
Future<void> _createTradeTable(Database db) async {
|
|
await db.execute("""
|
|
CREATE TABLE IF NOT EXISTS Trade (
|
|
tradeId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
id TEXT NOT NULL,
|
|
providerRaw INTEGER NOT NULL DEFAULT 0,
|
|
fromTitle TEXT,
|
|
fromName TEXT,
|
|
fromTag TEXT,
|
|
fromFullName TEXT,
|
|
fromDecimals INTEGER,
|
|
fromRaw INTEGER,
|
|
fromIconPath TEXT,
|
|
fromFlatIconPath TEXT,
|
|
fromChainIconPath TEXT,
|
|
toTitle TEXT,
|
|
toName TEXT,
|
|
toTag TEXT,
|
|
toFullName TEXT,
|
|
toDecimals INTEGER,
|
|
toRaw INTEGER,
|
|
toIconPath TEXT,
|
|
toFlatIconPath TEXT,
|
|
toChainIconPath TEXT,
|
|
stateRaw TEXT NOT NULL DEFAULT '',
|
|
createdAt INTEGER,
|
|
expiredAt INTEGER,
|
|
amount TEXT NOT NULL DEFAULT '',
|
|
receiveAmount TEXT,
|
|
inputAddress TEXT,
|
|
extraId TEXT,
|
|
outputTransaction TEXT,
|
|
refundAddress TEXT,
|
|
walletId TEXT,
|
|
payoutAddress TEXT,
|
|
toAddressExtraId TEXT,
|
|
password TEXT,
|
|
providerId TEXT,
|
|
providerName TEXT,
|
|
fromWalletAddress TEXT,
|
|
memo TEXT,
|
|
txId TEXT,
|
|
isRefund INTEGER DEFAULT 0,
|
|
isSendAll INTEGER DEFAULT 0,
|
|
router TEXT,
|
|
needToRegisterInSwapXyz INTEGER DEFAULT 0,
|
|
sourceTokenAddress TEXT,
|
|
sourceTokenDecimals INTEGER,
|
|
routerData TEXT,
|
|
routerValue TEXT,
|
|
routerChainId INTEGER,
|
|
sourceTokenAmountRaw TEXT,
|
|
requiresTokenApproval INTEGER DEFAULT 0,
|
|
chainId INTEGER,
|
|
fee REAL
|
|
);
|
|
""");
|
|
await db.execute("""
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_trade_id_unique
|
|
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();
|
|
} catch (e) {
|
|
return {
|
|
"error": e.toString(),
|
|
"stackTrace": StackTrace.current.toString(),
|
|
};
|
|
}
|
|
}
|
|
|
|
Future<List<String>> _getTableNames(Database db) async {
|
|
final tableNames = await db.rawQuery('SELECT name FROM sqlite_master WHERE type = "table"');
|
|
return tableNames.map((e) => e["name"].toString()).toList();
|
|
}
|
|
|
|
Future<Map<String, dynamic>> _dumpDb() async {
|
|
final tableNames = await _getTableNames(db!);
|
|
final ret = <String, dynamic>{};
|
|
for (final tableName in tableNames) {
|
|
ret[tableName] = await db!.query(tableName);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
Future<Map<String, dynamic>> dumpCustomDb(String path) async {
|
|
final db = await openDatabase(path);
|
|
final tableNames = await _getTableNames(db);
|
|
final ret = <String, dynamic>{};
|
|
for (final tableName in tableNames) {
|
|
ret[tableName] = await db.query(tableName);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
Future<void> _createBridgeTransferTable(Database db) async {
|
|
await db.execute("""
|
|
CREATE TABLE IF NOT EXISTS BridgeTransfer (
|
|
id TEXT NOT NULL PRIMARY KEY,
|
|
wallet_id TEXT NOT NULL,
|
|
source_chain_id INTEGER NOT NULL,
|
|
destination_chain_id INTEGER NOT NULL,
|
|
token_symbol TEXT NOT NULL,
|
|
token_contract TEXT NOT NULL,
|
|
amount TEXT NOT NULL,
|
|
recipient_address TEXT NOT NULL,
|
|
source_tx_hash TEXT NOT NULL,
|
|
status TEXT NOT NULL,
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER,
|
|
confirmed_at INTEGER,
|
|
amount_raw TEXT,
|
|
error_message TEXT,
|
|
status_message TEXT
|
|
);
|
|
""");
|
|
await db.execute("""
|
|
CREATE INDEX IF NOT EXISTS idx_bridgetransfer_wallet_id
|
|
ON BridgeTransfer(wallet_id);
|
|
""");
|
|
}
|
|
|
|
Future<void> _createErc20TokenTable(Database db) async {
|
|
await db.execute("""
|
|
CREATE TABLE IF NOT EXISTS Erc20Token (
|
|
Erc20TokenId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
walletName TEXT NOT NULL,
|
|
chainId INTEGER NOT NULL,
|
|
name TEXT NOT NULL DEFAULT '',
|
|
symbol TEXT NOT NULL DEFAULT '',
|
|
contractAddress TEXT NOT NULL,
|
|
decimal INTEGER NOT NULL DEFAULT 0,
|
|
enabled INTEGER NOT NULL DEFAULT 1,
|
|
iconPath TEXT,
|
|
tag TEXT,
|
|
isPotentialScam INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
""");
|
|
await db.execute("""
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_erc20token_wallet_chain_contract
|
|
ON Erc20Token (walletName, chainId, contractAddress);
|
|
""");
|
|
}
|
|
|
|
Future<void> _createSplTokenTable(Database db) async {
|
|
await db.execute("""
|
|
CREATE TABLE IF NOT EXISTS SPLToken (
|
|
SPLTokenId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
walletName TEXT NOT NULL,
|
|
name TEXT NOT NULL DEFAULT '',
|
|
symbol TEXT NOT NULL DEFAULT '',
|
|
mintAddress TEXT NOT NULL,
|
|
decimal INTEGER NOT NULL DEFAULT 0,
|
|
mint TEXT NOT NULL DEFAULT '',
|
|
enabled INTEGER NOT NULL DEFAULT 1,
|
|
iconPath TEXT,
|
|
tag TEXT,
|
|
isPotentialScam INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
""");
|
|
await db.execute("""
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_spltoken_wallet_mint
|
|
ON SPLToken (walletName, mintAddress);
|
|
""");
|
|
}
|
|
|
|
Future<void> _createImportedNFTTable(Database db) async {
|
|
await db.execute("""
|
|
CREATE TABLE IF NOT EXISTS ImportedNFT (
|
|
ImportedNFTId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
walletName TEXT NOT NULL,
|
|
chain TEXT NOT NULL,
|
|
identifier TEXT NOT NULL,
|
|
name TEXT,
|
|
symbol TEXT,
|
|
description TEXT,
|
|
imageUrl TEXT,
|
|
isOwned INTEGER
|
|
);
|
|
""");
|
|
await db.execute("""
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_importednft_wallet_chain_identifier
|
|
ON ImportedNFT (walletName, chain, identifier);
|
|
""");
|
|
}
|
|
|
|
Future<void> _createTronTokenTable(Database db) async {
|
|
await db.execute("""
|
|
CREATE TABLE IF NOT EXISTS TronToken (
|
|
TronTokenId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
walletName TEXT NOT NULL,
|
|
name TEXT NOT NULL DEFAULT '',
|
|
symbol TEXT NOT NULL DEFAULT '',
|
|
contractAddress TEXT NOT NULL,
|
|
decimal INTEGER NOT NULL DEFAULT 0,
|
|
enabled INTEGER NOT NULL DEFAULT 1,
|
|
iconPath TEXT,
|
|
tag TEXT,
|
|
isPotentialScam INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
""");
|
|
await db.execute("""
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_trontoken_wallet_contract
|
|
ON TronToken (walletName, contractAddress);
|
|
""");
|
|
}
|
|
|
|
Future<void> _createNodeTable(Database db) async {
|
|
await db.execute("""
|
|
CREATE TABLE Node (
|
|
NodeId INTEGER PRIMARY KEY,
|
|
uri TEXT NOT NULL,
|
|
path TEXT,
|
|
login TEXT,
|
|
label TEXT,
|
|
password TEXT,
|
|
isPow INTEGER NOT NULL,
|
|
useSSL INTEGER,
|
|
typeRaw INTEGER NOT NULL,
|
|
trusted INTEGER NOT NULL,
|
|
socksProxyAddress TEXT,
|
|
isEnabledForAutoSwitching BOOLEAN DEFAULT FALSE,
|
|
isOfficial BOOLEAN DEFAULT FALSE,
|
|
isBuiltin BOOLEAN DEFAULT FALSE,
|
|
isDefault BOOLEAN DEFAULT FALSE
|
|
);
|
|
""");
|
|
}
|