Fix Bitcoin transactions not showing (#978)

* handle multiple responses coming in a single event

* Add timeout for getting transaction info, to allow other transactions to be returned in case of any failure or network issue

* Handle other cases of receiving multiple messages in the same response
This commit is contained in:
Omar Hatem 2023-07-13 21:46:55 +03:00 committed by GitHub
parent d7fa9991e1
commit bc432b1042
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -66,54 +66,68 @@ class ElectrumClient {
socket!.listen((Uint8List event) { socket!.listen((Uint8List event) {
try { try {
final msg = utf8.decode(event.toList()); final msg = utf8.decode(event.toList());
final response = final messagesList = msg.split("\n");
json.decode(msg) as Map<String, dynamic>; for (var message in messagesList) {
_handleResponse(response); if (message.isEmpty) {
} on FormatException catch (e) { continue;
final msg = e.message.toLowerCase(); }
_parseResponse(message);
if (e.source is String) {
unterminatedString += e.source as String;
}
if (msg.contains("not a subtype of type")) {
unterminatedString += e.source as String;
return;
}
if (isJSONStringCorrect(unterminatedString)) {
final response =
json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response);
unterminatedString = '';
}
} on TypeError catch (e) {
if (!e.toString().contains('Map<String, Object>') && !e.toString().contains('Map<String, dynamic>')) {
return;
}
final source = utf8.decode(event.toList());
unterminatedString += source;
if (isJSONStringCorrect(unterminatedString)) {
final response =
json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response);
// unterminatedString = null;
unterminatedString = '';
} }
} catch (e) { } catch (e) {
print(e.toString()); print(e.toString());
} }
}, onError: (Object error) { }, onError: (Object error) {
print(error.toString()); print(error.toString());
unterminatedString = '';
_setIsConnected(false); _setIsConnected(false);
}, onDone: () { }, onDone: () {
unterminatedString = '';
_setIsConnected(false); _setIsConnected(false);
}); });
keepAlive(); keepAlive();
} }
void _parseResponse(String message) {
try {
final response = json.decode(message) as Map<String, dynamic>;
_handleResponse(response);
} on FormatException catch (e) {
final msg = e.message.toLowerCase();
if (e.source is String) {
unterminatedString += e.source as String;
}
if (msg.contains("not a subtype of type")) {
unterminatedString += e.source as String;
return;
}
if (isJSONStringCorrect(unterminatedString)) {
final response =
json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response);
unterminatedString = '';
}
} on TypeError catch (e) {
if (!e.toString().contains('Map<String, Object>') && !e.toString().contains('Map<String, dynamic>')) {
return;
}
unterminatedString += message;
if (isJSONStringCorrect(unterminatedString)) {
final response =
json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response);
// unterminatedString = null;
unterminatedString = '';
}
} catch (e) {
print(e.toString());
}
}
void keepAlive() { void keepAlive() {
_aliveTimer?.cancel(); _aliveTimer?.cancel();
_aliveTimer = Timer.periodic(aliveTimerDuration, (_) async => ping()); _aliveTimer = Timer.periodic(aliveTimerDuration, (_) async => ping());
@ -217,7 +231,7 @@ class ElectrumClient {
Future<Map<String, dynamic>> getTransactionRaw( Future<Map<String, dynamic>> getTransactionRaw(
{required String hash}) async => {required String hash}) async =>
call(method: 'blockchain.transaction.get', params: [hash, true]) callWithTimeout(method: 'blockchain.transaction.get', params: [hash, true], timeout: 10000)
.then((dynamic result) { .then((dynamic result) {
if (result is Map<String, dynamic>) { if (result is Map<String, dynamic>) {
return result; return result;
@ -228,7 +242,7 @@ class ElectrumClient {
Future<String> getTransactionHex( Future<String> getTransactionHex(
{required String hash}) async => {required String hash}) async =>
call(method: 'blockchain.transaction.get', params: [hash, false]) callWithTimeout(method: 'blockchain.transaction.get', params: [hash, false], timeout: 10000)
.then((dynamic result) { .then((dynamic result) {
if (result is String) { if (result is String) {
return result; return result;