mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-08 19:59:29 +00:00
speed up initial load time
This commit is contained in:
parent
309a483026
commit
d747347414
3 changed files with 147 additions and 10 deletions
|
@ -8,6 +8,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter_libmonero/monero/monero.dart';
|
import 'package:flutter_libmonero/monero/monero.dart';
|
||||||
import 'package:flutter_libmonero/wownero/wownero.dart';
|
import 'package:flutter_libmonero/wownero/wownero.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
|
@ -16,7 +18,6 @@ import 'package:stackwallet/db/isar/main_db.dart';
|
||||||
import 'package:stackwallet/services/node_service.dart';
|
import 'package:stackwallet/services/node_service.dart';
|
||||||
import 'package:stackwallet/services/notifications_service.dart';
|
import 'package:stackwallet/services/notifications_service.dart';
|
||||||
import 'package:stackwallet/services/trade_sent_from_stack_service.dart';
|
import 'package:stackwallet/services/trade_sent_from_stack_service.dart';
|
||||||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
import 'package:stackwallet/utilities/enums/sync_type_enum.dart';
|
import 'package:stackwallet/utilities/enums/sync_type_enum.dart';
|
||||||
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
|
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
|
||||||
|
@ -134,6 +135,11 @@ class Wallets {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> load(Prefs prefs, MainDB mainDB) async {
|
Future<void> load(Prefs prefs, MainDB mainDB) async {
|
||||||
|
// return await _loadV1(prefs, mainDB);
|
||||||
|
return await _loadV2(prefs, mainDB);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _loadV1(Prefs prefs, MainDB mainDB) async {
|
||||||
if (hasLoaded) {
|
if (hasLoaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -186,8 +192,8 @@ class Wallets {
|
||||||
if (isVerified) {
|
if (isVerified) {
|
||||||
// TODO: integrate this into the new wallets somehow?
|
// TODO: integrate this into the new wallets somehow?
|
||||||
// requires some thinking
|
// requires some thinking
|
||||||
final txTracker =
|
// final txTracker =
|
||||||
TransactionNotificationTracker(walletId: walletInfo.walletId);
|
// TransactionNotificationTracker(walletId: walletInfo.walletId);
|
||||||
|
|
||||||
final wallet = await Wallet.load(
|
final wallet = await Wallet.load(
|
||||||
walletId: walletInfo.walletId,
|
walletId: walletInfo.walletId,
|
||||||
|
@ -234,6 +240,124 @@ class Wallets {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _loadV2(Prefs prefs, MainDB mainDB) async {
|
||||||
|
if (hasLoaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hasLoaded = true;
|
||||||
|
|
||||||
|
// clear out any wallet hive boxes where the wallet was deleted in previous app run
|
||||||
|
for (final walletId in DB.instance
|
||||||
|
.values<String>(boxName: DB.boxNameWalletsToDeleteOnStart)) {
|
||||||
|
await mainDB.isar.writeTxn(() async => await mainDB.isar.walletInfo
|
||||||
|
.where()
|
||||||
|
.walletIdEqualTo(walletId)
|
||||||
|
.deleteAll());
|
||||||
|
}
|
||||||
|
// clear list
|
||||||
|
await DB.instance
|
||||||
|
.deleteAll<String>(boxName: DB.boxNameWalletsToDeleteOnStart);
|
||||||
|
|
||||||
|
final walletInfoList = await mainDB.isar.walletInfo.where().findAll();
|
||||||
|
if (walletInfoList.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Future<String>> walletIDInitFutures = [];
|
||||||
|
final List<Future<void>> deleteFutures = [];
|
||||||
|
final List<({Wallet wallet, bool shouldAutoSync})> walletsToInitLinearly =
|
||||||
|
[];
|
||||||
|
|
||||||
|
final List<String> walletIdsToEnableAutoSync = [];
|
||||||
|
bool shouldAutoSyncAll = false;
|
||||||
|
switch (prefs.syncType) {
|
||||||
|
case SyncingType.currentWalletOnly:
|
||||||
|
// do nothing as this will be set when going into a wallet from the main screen
|
||||||
|
break;
|
||||||
|
case SyncingType.selectedWalletsAtStartup:
|
||||||
|
walletIdsToEnableAutoSync.addAll(prefs.walletIdsSyncOnStartup);
|
||||||
|
break;
|
||||||
|
case SyncingType.allWalletsOnStartup:
|
||||||
|
shouldAutoSyncAll = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final walletInfo in walletInfoList) {
|
||||||
|
try {
|
||||||
|
final isVerified = await walletInfo.isMnemonicVerified(mainDB.isar);
|
||||||
|
Logging.instance.log(
|
||||||
|
"LOADING WALLET: ${walletInfo.name}:${walletInfo.walletId} "
|
||||||
|
"IS VERIFIED: $isVerified",
|
||||||
|
level: LogLevel.Info,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isVerified) {
|
||||||
|
// TODO: integrate this into the new wallets somehow?
|
||||||
|
// requires some thinking
|
||||||
|
// final txTracker =
|
||||||
|
// TransactionNotificationTracker(walletId: walletInfo.walletId);
|
||||||
|
|
||||||
|
final walletIdCompleter = Completer<String>();
|
||||||
|
|
||||||
|
walletIDInitFutures.add(walletIdCompleter.future);
|
||||||
|
|
||||||
|
await Wallet.load(
|
||||||
|
walletId: walletInfo.walletId,
|
||||||
|
mainDB: mainDB,
|
||||||
|
secureStorageInterface: nodeService.secureStorageInterface,
|
||||||
|
nodeService: nodeService,
|
||||||
|
prefs: prefs,
|
||||||
|
).then((wallet) {
|
||||||
|
if (wallet is CwBasedInterface) {
|
||||||
|
// walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync));
|
||||||
|
|
||||||
|
walletIdCompleter.complete("dummy_ignore");
|
||||||
|
} else {
|
||||||
|
walletIdCompleter.complete(wallet.walletId);
|
||||||
|
}
|
||||||
|
|
||||||
|
_wallets[wallet.walletId] = wallet;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// wallet creation was not completed by user so we remove it completely
|
||||||
|
deleteFutures.add(_deleteWallet(walletInfo.walletId));
|
||||||
|
}
|
||||||
|
} catch (e, s) {
|
||||||
|
Logging.instance.log("$e $s", level: LogLevel.Fatal);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final asyncWalletIds = await Future.wait(walletIDInitFutures);
|
||||||
|
asyncWalletIds.removeWhere((e) => e == "dummy_ignore");
|
||||||
|
|
||||||
|
final List<Future<void>> walletInitFutures = asyncWalletIds
|
||||||
|
.map(
|
||||||
|
(id) => _wallets[id]!.init().then(
|
||||||
|
(_) {
|
||||||
|
if (shouldAutoSyncAll || walletIdsToEnableAutoSync.contains(id)) {
|
||||||
|
_wallets[id]!.shouldAutoSync = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (walletInitFutures.isNotEmpty && walletsToInitLinearly.isNotEmpty) {
|
||||||
|
unawaited(Future.wait([
|
||||||
|
_initLinearly(walletsToInitLinearly),
|
||||||
|
...walletInitFutures,
|
||||||
|
]));
|
||||||
|
} else if (walletInitFutures.isNotEmpty) {
|
||||||
|
unawaited(Future.wait(walletInitFutures));
|
||||||
|
} else if (walletsToInitLinearly.isNotEmpty) {
|
||||||
|
unawaited(_initLinearly(walletsToInitLinearly));
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally await any deletions that haven't completed yet
|
||||||
|
await Future.wait(deleteFutures);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> loadAfterStackRestore(
|
Future<void> loadAfterStackRestore(
|
||||||
Prefs prefs,
|
Prefs prefs,
|
||||||
List<Wallet> wallets,
|
List<Wallet> wallets,
|
||||||
|
|
|
@ -633,9 +633,11 @@ class FiroWallet extends Bip39HDWallet
|
||||||
level: LogLevel.Info,
|
level: LogLevel.Info,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final canBatch = await serverCanBatch;
|
||||||
|
|
||||||
for (final type in cryptoCurrency.supportedDerivationPathTypes) {
|
for (final type in cryptoCurrency.supportedDerivationPathTypes) {
|
||||||
receiveFutures.add(
|
receiveFutures.add(
|
||||||
serverCanBatch
|
canBatch
|
||||||
? checkGapsBatched(
|
? checkGapsBatched(
|
||||||
txCountBatchSize,
|
txCountBatchSize,
|
||||||
root,
|
root,
|
||||||
|
@ -657,7 +659,7 @@ class FiroWallet extends Bip39HDWallet
|
||||||
);
|
);
|
||||||
for (final type in cryptoCurrency.supportedDerivationPathTypes) {
|
for (final type in cryptoCurrency.supportedDerivationPathTypes) {
|
||||||
changeFutures.add(
|
changeFutures.add(
|
||||||
serverCanBatch
|
canBatch
|
||||||
? checkGapsBatched(
|
? checkGapsBatched(
|
||||||
txCountBatchSize,
|
txCountBatchSize,
|
||||||
root,
|
root,
|
||||||
|
|
|
@ -35,11 +35,20 @@ mixin ElectrumXInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
|
||||||
|
|
||||||
static const _kServerBatchCutoffVersion = [1, 6];
|
static const _kServerBatchCutoffVersion = [1, 6];
|
||||||
List<int>? _serverVersion;
|
List<int>? _serverVersion;
|
||||||
bool get serverCanBatch {
|
Future<bool> get serverCanBatch async {
|
||||||
// Firo server added batching without incrementing version number...
|
// Firo server added batching without incrementing version number...
|
||||||
if (cryptoCurrency is Firo) {
|
if (cryptoCurrency is Firo) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
_serverVersion ??= _parseServerVersion((await electrumXClient
|
||||||
|
.getServerFeatures()
|
||||||
|
.timeout(const Duration(seconds: 2)))["server_version"] as String);
|
||||||
|
} catch (_) {
|
||||||
|
// ignore failure as it doesn't matter
|
||||||
|
}
|
||||||
|
|
||||||
if (_serverVersion != null && _serverVersion!.length > 2) {
|
if (_serverVersion != null && _serverVersion!.length > 2) {
|
||||||
if (_serverVersion![0] > _kServerBatchCutoffVersion[0]) {
|
if (_serverVersion![0] > _kServerBatchCutoffVersion[0]) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -1025,7 +1034,7 @@ mixin ElectrumXInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
|
||||||
try {
|
try {
|
||||||
final List<Map<String, dynamic>> allTxHashes = [];
|
final List<Map<String, dynamic>> allTxHashes = [];
|
||||||
|
|
||||||
if (serverCanBatch) {
|
if (await serverCanBatch) {
|
||||||
final Map<int, List<List<dynamic>>> batches = {};
|
final Map<int, List<List<dynamic>>> batches = {};
|
||||||
final Map<int, List<String>> batchIndexToAddressListMap = {};
|
final Map<int, List<String>> batchIndexToAddressListMap = {};
|
||||||
const batchSizeMax = 100;
|
const batchSizeMax = 100;
|
||||||
|
@ -1363,9 +1372,11 @@ mixin ElectrumXInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
|
||||||
level: LogLevel.Info,
|
level: LogLevel.Info,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final canBatch = await serverCanBatch;
|
||||||
|
|
||||||
for (final type in cryptoCurrency.supportedDerivationPathTypes) {
|
for (final type in cryptoCurrency.supportedDerivationPathTypes) {
|
||||||
receiveFutures.add(
|
receiveFutures.add(
|
||||||
serverCanBatch
|
canBatch
|
||||||
? checkGapsBatched(
|
? checkGapsBatched(
|
||||||
txCountBatchSize,
|
txCountBatchSize,
|
||||||
root,
|
root,
|
||||||
|
@ -1387,7 +1398,7 @@ mixin ElectrumXInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
|
||||||
);
|
);
|
||||||
for (final type in cryptoCurrency.supportedDerivationPathTypes) {
|
for (final type in cryptoCurrency.supportedDerivationPathTypes) {
|
||||||
changeFutures.add(
|
changeFutures.add(
|
||||||
serverCanBatch
|
canBatch
|
||||||
? checkGapsBatched(
|
? checkGapsBatched(
|
||||||
txCountBatchSize,
|
txCountBatchSize,
|
||||||
root,
|
root,
|
||||||
|
@ -1510,7 +1521,7 @@ mixin ElectrumXInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
|
||||||
try {
|
try {
|
||||||
final fetchedUtxoList = <List<Map<String, dynamic>>>[];
|
final fetchedUtxoList = <List<Map<String, dynamic>>>[];
|
||||||
|
|
||||||
if (serverCanBatch) {
|
if (await serverCanBatch) {
|
||||||
final Map<int, List<List<dynamic>>> batchArgs = {};
|
final Map<int, List<List<dynamic>>> batchArgs = {};
|
||||||
const batchSizeMax = 10;
|
const batchSizeMax = 10;
|
||||||
int batchNumber = 0;
|
int batchNumber = 0;
|
||||||
|
|
Loading…
Reference in a new issue