Cw 868 fix false synchronised status when the socket connection fails due to network issues (#1892)

* prevent setting Synced status when the connection is lost

* fallback for UTXO fetch failures

* minor fix
This commit is contained in:
Serhii 2024-12-25 21:27:28 +02:00 committed by GitHub
parent 20d30013d0
commit b79ef988c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 64 additions and 11 deletions

View file

@ -235,7 +235,7 @@ class ElectrumClient {
return [];
});
Future<List<Map<String, dynamic>>> getListUnspent(String scriptHash) async {
Future<List<Map<String, dynamic>>?> getListUnspent(String scriptHash) async {
final result = await call(method: 'blockchain.scripthash.listunspent', params: [scriptHash]);
if (result is List) {
@ -248,7 +248,7 @@ class ElectrumClient {
}).toList();
}
return [];
return null;
}
Future<List<Map<String, dynamic>>> getMempool(String scriptHash) =>

View file

@ -478,6 +478,7 @@ abstract class ElectrumWalletBase
if (alwaysScan == true) {
_setListeners(walletInfo.restoreHeight);
} else {
if (syncStatus is LostConnectionSyncStatus) return;
syncStatus = SyncedSyncStatus();
}
} catch (e, stacktrace) {
@ -1361,6 +1362,10 @@ abstract class ElectrumWalletBase
Future<void> updateAllUnspents() async {
List<BitcoinUnspent> updatedUnspentCoins = [];
final previousUnspentCoins = List<BitcoinUnspent>.from(unspentCoins.where((utxo) =>
utxo.bitcoinAddressRecord.type != SegwitAddresType.mweb &&
utxo.bitcoinAddressRecord is! BitcoinSilentPaymentAddressRecord));
if (hasSilentPaymentsScanning) {
// Update unspents stored from scanned silent payment transactions
transactionHistory.transactions.values.forEach((tx) {
@ -1377,13 +1382,27 @@ abstract class ElectrumWalletBase
if (addr is! BitcoinSilentPaymentAddressRecord) addr.balance = 0;
});
await Future.wait(walletAddresses.allAddresses
final addressFutures = walletAddresses.allAddresses
.where((element) => element.type != SegwitAddresType.mweb)
.map((address) async {
updatedUnspentCoins.addAll(await fetchUnspent(address));
}));
.map((address) => fetchUnspent(address))
.toList();
unspentCoins = updatedUnspentCoins;
final results = await Future.wait(addressFutures);
final failedCount = results.where((result) => result == null).length;
if (failedCount == 0) {
for (final result in results) {
updatedUnspentCoins.addAll(result!);
}
unspentCoins = updatedUnspentCoins;
} else {
unspentCoins = handleFailedUtxoFetch(
failedCount: failedCount,
previousUnspentCoins: previousUnspentCoins,
updatedUnspentCoins: updatedUnspentCoins,
results: results,
);
}
final currentWalletUnspentCoins =
unspentCoinsInfo.values.where((element) => element.walletId == id);
@ -1396,6 +1415,38 @@ abstract class ElectrumWalletBase
await _refreshUnspentCoinsInfo();
}
List<BitcoinUnspent> handleFailedUtxoFetch({
required int failedCount,
required List<BitcoinUnspent> previousUnspentCoins,
required List<BitcoinUnspent> updatedUnspentCoins,
required List<List<BitcoinUnspent>?> results,
}) {
if (failedCount == results.length) {
printV("All UTXOs failed to fetch, falling back to previous UTXOs");
return previousUnspentCoins;
}
final successfulUtxos = <BitcoinUnspent>[];
for (final result in results) {
if (result != null) {
successfulUtxos.addAll(result);
}
}
if (failedCount > 0 && successfulUtxos.isEmpty) {
printV("Some UTXOs failed, but no successful UTXOs, falling back to previous UTXOs");
return previousUnspentCoins;
}
if (failedCount > 0) {
printV("Some UTXOs failed, updating with successful UTXOs");
updatedUnspentCoins.addAll(successfulUtxos);
}
return updatedUnspentCoins;
}
Future<void> updateCoins(List<BitcoinUnspent> newUnspentCoins) async {
if (newUnspentCoins.isEmpty) {
return;
@ -1427,15 +1478,17 @@ abstract class ElectrumWalletBase
@action
Future<void> updateUnspentsForAddress(BitcoinAddressRecord address) async {
final newUnspentCoins = await fetchUnspent(address);
await updateCoins(newUnspentCoins);
await updateCoins(newUnspentCoins ?? []);
}
@action
Future<List<BitcoinUnspent>> fetchUnspent(BitcoinAddressRecord address) async {
List<Map<String, dynamic>> unspents = [];
Future<List<BitcoinUnspent>?> fetchUnspent(BitcoinAddressRecord address) async {
List<BitcoinUnspent> updatedUnspentCoins = [];
unspents = await electrumClient.getListUnspent(address.getScriptHash(network));
final unspents = await electrumClient.getListUnspent(address.getScriptHash(network));
// Failed to fetch unspents
if (unspents == null) return null;
await Future.wait(unspents.map((unspent) async {
try {