fix balance being stale cuz it's overriden by an old value

This commit is contained in:
Omar
2026-10-03 01:23:12 +02:00
parent ddb754882a
commit 1de16191ce
3 changed files with 84 additions and 15 deletions
+8
View File
@@ -36,6 +36,14 @@ class ElectrumBalance extends Balance {
@override
Money frozen;
ElectrumBalance copy() => ElectrumBalance(
confirmed: confirmed,
unconfirmed: unconfirmed,
frozen: frozen,
secondConfirmed: secondConfirmed,
secondUnconfirmed: secondUnconfirmed,
);
static ElectrumBalance? fromJSON(String? jsonSource, Currency currency) {
if (jsonSource == null) return null;
+49 -8
View File
@@ -428,7 +428,7 @@ abstract class ElectrumWalletBase
return;
}
balance[currency] = newBalance;
balance[currency] = newBalance.copy();
}
Map<int, Set<String>> get addressesSetByAccount {
@@ -1845,8 +1845,8 @@ abstract class ElectrumWalletBase
isViewOnly: false,
)..addListener((transaction) async {
transactionHistory.addOne(transaction);
await updateBalance();
await updateAllUnspents();
await updateBalance();
});
}
@@ -1950,8 +1950,8 @@ abstract class ElectrumWalletBase
unspentCoins
.removeWhere((utxo) => estimatedTx.utxos.any((e) => e.utxo.txHash == utxo.hash));
await updateBalance();
await updateAllUnspents();
await updateBalance();
});
} catch (e) {
throw e;
@@ -2736,8 +2736,8 @@ abstract class ElectrumWalletBase
}
});
transactionHistory.addOne(transaction);
await updateBalance();
await updateAllUnspents();
await updateBalance();
});
} catch (e) {
throw e;
@@ -4037,6 +4037,10 @@ abstract class ElectrumWalletBase
var totalConfirmed = 0;
var totalUnconfirmed = 0;
final confirmedByAccount = <int, int>{};
final unconfirmedByAccount = <int, int>{};
final frozenByAccount = <int, int>{};
if (hasSilentPaymentsScanning) {
// Add values from unspent coins that are not fetched by the address list
// i.e. scanned silent payments
@@ -4044,8 +4048,13 @@ abstract class ElectrumWalletBase
if (tx.unspents != null) {
tx.unspents!.forEach((unspent) {
if (unspent.bitcoinAddressRecord is BitcoinSilentPaymentAddressRecord) {
if (unspent.isFrozen) totalFrozen += unspent.value;
final account = unspent.bitcoinAddressRecord.accountIndex;
if (unspent.isFrozen) {
totalFrozen += unspent.value;
frozenByAccount[account] = (frozenByAccount[account] ?? 0) + unspent.value;
}
totalConfirmed += unspent.value;
confirmedByAccount[account] = (confirmedByAccount[account] ?? 0) + unspent.value;
}
});
}
@@ -4062,6 +4071,8 @@ abstract class ElectrumWalletBase
element.value == info.value) {
if (info.isFrozen) {
totalFrozen += element.value;
final account = element.bitcoinAddressRecord.accountIndex;
frozenByAccount[account] = (frozenByAccount[account] ?? 0) + element.value;
}
}
});
@@ -4089,6 +4100,10 @@ abstract class ElectrumWalletBase
totalConfirmed += confirmed;
totalUnconfirmed += unconfirmed;
final account = addressRecord.accountIndex;
confirmedByAccount[account] = (confirmedByAccount[account] ?? 0) + confirmed;
unconfirmedByAccount[account] = (unconfirmedByAccount[account] ?? 0) + unconfirmed;
addressRecord.balance = confirmed + unconfirmed;
if (confirmed > 0 || unconfirmed > 0) {
addressRecord.setAsUsed();
@@ -4096,6 +4111,26 @@ abstract class ElectrumWalletBase
}
}
if (hasAccountsSupport) {
final perAccount = <int, ElectrumBalance>{};
final accounts = <int>{
...confirmedByAccount.keys,
...unconfirmedByAccount.keys,
...frozenByAccount.keys,
...walletAddresses.accountIndexes,
};
for (final account in accounts) {
perAccount[account] = ElectrumBalance(
confirmed: Money.fromInt(confirmedByAccount[account] ?? 0, currency),
unconfirmed: Money.fromInt(unconfirmedByAccount[account] ?? 0, currency),
frozen: Money.fromInt(frozenByAccount[account] ?? 0, currency),
);
}
accountBalances = ObservableMap<int, ElectrumBalance>.of(perAccount);
}
return ElectrumBalance(
confirmed: Money.fromInt(totalConfirmed, currency),
unconfirmed: Money.fromInt(totalUnconfirmed, currency),
@@ -4138,13 +4173,19 @@ abstract class ElectrumWalletBase
try {
final fetchedTotal = await fetchBalances();
if (!electrumClient.isConnected || syncStatus is LostConnectionSyncStatus) {
printV("updateBalance: connection lost during fetch, keeping existing balance");
return;
}
if (type == WalletType.bitcoin && hasAccountsSupport) {
// If the wallet has accounts support, we only want to update the balance for the current account.
final accountBalance = accountBalances[currentAccountIndex];
if (accountBalance == null) {
return;
if (accountBalance != null) {
balance[currency] = accountBalance.copy();
} else {
printV("updateBalance: no balance for account $currentAccountIndex, keeping existing");
}
balance[currency] = accountBalance;
} else {
balance[currency] = fetchedTotal;
}
+27 -7
View File
@@ -1,3 +1,4 @@
import 'dart:async' show Zone;
import 'dart:io' show Platform;
import 'dart:math';
import "package:collection/collection.dart";
@@ -425,7 +426,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
updateAddressesByMatch();
updateReceiveAddresses();
updateChangeAddresses();
_validateAddresses();
await _validateAddresses();
await updateAddressesInBox();
if (currentReceiveAddressIndex >= receiveAddresses.length) {
@@ -506,7 +507,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
if (shouldSkipHardwareWalletType) continue;
await _generateInitialAddresses(accountIndex: accountIndex, type: type);
// Legacy derivation for these types is identical to the standard one.
if (includeLegacy && !LEGACY_DUPLICATE_ADDRESS_TYPES.contains(type)) {
await _generateInitialAddresses(
@@ -1001,13 +1002,32 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
updateAddressesByMatch();
}
void _validateAddresses() {
_addresses.forEach((element) async {
if (element.type == SegwitAddresType.mweb) {
// this would add a ton of startup lag for mweb addresses since we have 1000 of them
return;
static const _validationTimeSlice = Duration(milliseconds: 16);
Future<void> _validateAddresses() async {
final addresses = _addresses.toList();
final slice = Stopwatch()..start();
for (final element in addresses) {
try {
await _validateAddress(element);
} catch (e, s) {
Zone.current.handleUncaughtError(e, s);
}
if (slice.elapsed >= _validationTimeSlice) {
await Future<void>.delayed(Duration.zero);
slice.reset();
}
}
}
Future<void> _validateAddress(BitcoinAddressRecord element) async {
if (element.type == SegwitAddresType.mweb) {
// this would add a ton of startup lag for mweb addresses since we have 1000 of them
return;
}
try {
final mainHd = _hdForAddressGeneration(
isHidden: false,