fix: tweak sync percent feature and track progress during spark anon set download

This commit is contained in:
julian 2024-12-15 20:22:39 -06:00 committed by julian-CStack
parent c1ef98833a
commit 1884bfbaf7
4 changed files with 100 additions and 37 deletions

View file

@ -39,6 +39,7 @@ import '../../../../wallets/isar/providers/wallet_info_provider.dart';
import '../../../../wallets/wallet/impl/epiccash_wallet.dart'; import '../../../../wallets/wallet/impl/epiccash_wallet.dart';
import '../../../../wallets/wallet/impl/monero_wallet.dart'; import '../../../../wallets/wallet/impl/monero_wallet.dart';
import '../../../../wallets/wallet/impl/wownero_wallet.dart'; import '../../../../wallets/wallet/impl/wownero_wallet.dart';
import '../../../../wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart';
import '../../../../widgets/animated_text.dart'; import '../../../../widgets/animated_text.dart';
import '../../../../widgets/background.dart'; import '../../../../widgets/background.dart';
import '../../../../widgets/conditional_parent.dart'; import '../../../../widgets/conditional_parent.dart';
@ -233,7 +234,10 @@ class _WalletNetworkSettingsViewState
_percent = 1; _percent = 1;
_blocksRemaining = 0; _blocksRemaining = 0;
} else { } else {
_percent = 0; _percent =
(ref.read(pWallets).getWallet(widget.walletId) as ElectrumXInterface?)
?.refreshingPercent ??
0;
_blocksRemaining = -1; _blocksRemaining = -1;
} }

View file

@ -564,6 +564,11 @@ abstract class Wallet<T extends CryptoCurrency> {
return future; return future;
} }
void _fireRefreshPercentChange(double percent) {
(this as ElectrumXInterface?)?.refreshingPercent = percent;
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(percent, walletId));
}
// Should fire events // Should fire events
Future<void> _refresh(Completer<void> completer) async { Future<void> _refresh(Completer<void> completer) async {
// Awaiting this lock could be dangerous. // Awaiting this lock could be dangerous.
@ -612,15 +617,14 @@ abstract class Wallet<T extends CryptoCurrency> {
} }
} }
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.0, walletId)); _fireRefreshPercentChange(0);
_checkAlive();
await updateChainHeight(); await updateChainHeight();
if (this is BitcoinFrostWallet) { if (this is BitcoinFrostWallet) {
await (this as BitcoinFrostWallet).lookAhead(); await (this as BitcoinFrostWallet).lookAhead();
} }
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.1, walletId)); _fireRefreshPercentChange(0.1);
// TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided. // TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided.
if (this is MultiAddressInterface) { if (this is MultiAddressInterface) {
@ -630,8 +634,7 @@ abstract class Wallet<T extends CryptoCurrency> {
} }
} }
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.2, walletId)); _fireRefreshPercentChange(0.2);
_checkAlive();
// TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided. // TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided.
if (this is MultiAddressInterface) { if (this is MultiAddressInterface) {
@ -640,21 +643,21 @@ abstract class Wallet<T extends CryptoCurrency> {
.checkChangeAddressForTransactions(); .checkChangeAddressForTransactions();
} }
} }
_checkAlive(); _fireRefreshPercentChange(0.3);
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.3, walletId));
if (this is SparkInterface && !viewOnly) { if (this is SparkInterface && !viewOnly) {
// this should be called before updateTransactions() // this should be called before updateTransactions()
await (this as SparkInterface).refreshSparkData(null); await (this as SparkInterface).refreshSparkData((0.3, 0.6));
} }
final fetchFuture = updateTransactions(); final fetchFuture = updateTransactions();
_checkAlive();
_fireRefreshPercentChange(0.6);
final utxosRefreshFuture = updateUTXOs(); final utxosRefreshFuture = updateUTXOs();
// if (currentHeight != storedHeight) { // if (currentHeight != storedHeight) {
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.60, walletId)); _fireRefreshPercentChange(0.65);
await utxosRefreshFuture; await utxosRefreshFuture;
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.70, walletId)); _fireRefreshPercentChange(0.70);
await fetchFuture; await fetchFuture;
@ -665,8 +668,7 @@ abstract class Wallet<T extends CryptoCurrency> {
// check utxos again for notification outputs // check utxos again for notification outputs
await updateUTXOs(); await updateUTXOs();
} }
_checkAlive(); _fireRefreshPercentChange(0.80);
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.80, walletId));
// await getAllTxsToWatch(); // await getAllTxsToWatch();
@ -677,16 +679,11 @@ abstract class Wallet<T extends CryptoCurrency> {
await (this as LelantusInterface).refreshLelantusData(); await (this as LelantusInterface).refreshLelantusData();
} }
} }
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.90, walletId)); _fireRefreshPercentChange(0.90);
await updateBalance(); await updateBalance();
_checkAlive(); _fireRefreshPercentChange(1.0);
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(1.0, walletId));
if (this is! SparkInterface) {
tAlive = false; // interrupt timer as its not needed anymore
}
completer.complete(); completer.complete();
} catch (error, strace) { } catch (error, strace) {

View file

@ -42,6 +42,8 @@ mixin ElectrumXInterface<T extends ElectrumXCurrencyInterface>
int? get maximumFeerate => null; int? get maximumFeerate => null;
double? refreshingPercent;
static const _kServerBatchCutoffVersion = [1, 6]; static const _kServerBatchCutoffVersion = [1, 6];
List<int>? _serverVersion; List<int>? _serverVersion;
Future<bool> get serverCanBatch async { Future<bool> get serverCanBatch async {

View file

@ -14,6 +14,8 @@ import '../../../models/isar/models/blockchain_data/v2/output_v2.dart';
import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart';
import '../../../models/isar/models/isar_models.dart'; import '../../../models/isar/models/isar_models.dart';
import '../../../models/signing_data.dart'; import '../../../models/signing_data.dart';
import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart';
import '../../../services/event_bus/global_event_bus.dart';
import '../../../utilities/amount/amount.dart'; import '../../../utilities/amount/amount.dart';
import '../../../utilities/enums/derive_path_type_enum.dart'; import '../../../utilities/enums/derive_path_type_enum.dart';
import '../../../utilities/extensions/extensions.dart'; import '../../../utilities/extensions/extensions.dart';
@ -795,8 +797,24 @@ mixin SparkInterface<T extends ElectrumXCurrencyInterface>
} }
} }
// returns next percent
double _triggerEventHelper(double current, double increment) {
refreshingPercent = current;
GlobalEventBus.instance.fire(
RefreshPercentChangedEvent(
current,
walletId,
),
);
return current + increment;
}
// Linearly make calls so there is less chance of timing out or otherwise breaking
Future<void> refreshSparkData( Future<void> refreshSparkData(
void Function(int countFetched, int totalCount)? progressUpdated, (
double startingPercent,
double endingPercent,
)? refreshProgressRange,
) async { ) async {
final start = DateTime.now(); final start = DateTime.now();
try { try {
@ -818,25 +836,55 @@ mixin SparkInterface<T extends ElectrumXCurrencyInterface>
} }
groupIds.add(latestGroupId); groupIds.add(latestGroupId);
// start fetch and update process for each set groupId as required final steps = groupIds.length +
final possibleFutures = groupIds.map( 1 // get used tags step
(e) => +
FiroCacheCoordinator.runFetchAndUpdateSparkAnonSetCacheForGroupId( 1 // check updated cache step
e, +
1 // identify coins step
+
1 // cross ref coins and txns
+
1; // update balance
final percentIncrement = refreshProgressRange == null
? null
: (refreshProgressRange.$2 - refreshProgressRange.$1) / steps;
double currentPercent = refreshProgressRange?.$1 ?? 0;
// fetch and update process for each set groupId as required
for (final gId in groupIds) {
await FiroCacheCoordinator.runFetchAndUpdateSparkAnonSetCacheForGroupId(
gId,
electrumXClient, electrumXClient,
cryptoCurrency.network, cryptoCurrency.network,
null, // null,
), (a, b) {
if (percentIncrement != null) {
_triggerEventHelper(
currentPercent + (percentIncrement * (a / b)),
0,
);
}
},
);
if (percentIncrement != null) {
currentPercent += percentIncrement;
}
}
if (percentIncrement != null) {
currentPercent = _triggerEventHelper(currentPercent, percentIncrement);
}
await FiroCacheCoordinator.runFetchAndUpdateSparkUsedCoinTags(
electrumXClient,
cryptoCurrency.network,
); );
// wait for each fetch and update to complete if (percentIncrement != null) {
await Future.wait([ currentPercent = _triggerEventHelper(currentPercent, percentIncrement);
...possibleFutures, }
FiroCacheCoordinator.runFetchAndUpdateSparkUsedCoinTags(
electrumXClient,
cryptoCurrency.network,
),
]);
// Get cached timestamps per groupId. These timestamps are used to check // Get cached timestamps per groupId. These timestamps are used to check
// and try to id coins that were added to the spark anon set cache // and try to id coins that were added to the spark anon set cache
@ -883,6 +931,10 @@ mixin SparkInterface<T extends ElectrumXCurrencyInterface>
); );
} }
if (percentIncrement != null) {
currentPercent = _triggerEventHelper(currentPercent, percentIncrement);
}
// get address(es) to get the private key hex strings required for // get address(es) to get the private key hex strings required for
// identifying spark coins // identifying spark coins
final sparkAddresses = await mainDB.isar.addresses final sparkAddresses = await mainDB.isar.addresses
@ -930,6 +982,10 @@ mixin SparkInterface<T extends ElectrumXCurrencyInterface>
isar: mainDB.isar, isar: mainDB.isar,
); );
if (percentIncrement != null) {
currentPercent = _triggerEventHelper(currentPercent, percentIncrement);
}
// check for spark coins in mempool // check for spark coins in mempool
final mempoolMyCoins = await _refreshSparkCoinsMempoolCheck( final mempoolMyCoins = await _refreshSparkCoinsMempoolCheck(
privateKeyHexSet: privateKeyHexSet, privateKeyHexSet: privateKeyHexSet,
@ -991,6 +1047,10 @@ mixin SparkInterface<T extends ElectrumXCurrencyInterface>
}); });
} }
if (percentIncrement != null) {
currentPercent = _triggerEventHelper(currentPercent, percentIncrement);
}
// used to check if balance is spendable or total // used to check if balance is spendable or total
final currentHeight = await chainHeight; final currentHeight = await chainHeight;