CW-193 Fixes for fetching of electrum transactions.
M committed
Oct 17, 2022 at 16:55 UTC
902935bc16ecd11ed99b18a1ad2d6ca23c3b342c
3 files changed
+56
-32
cw_bitcoin/lib/electrum.dart
+16
-15
@@ -65,8 +65,9 @@ class ElectrumClient {
65
66
socket!.listen((Uint8List event) {
67
try {
68
+ final msg = utf8.decode(event.toList());
69
final response =
69
- json.decode(utf8.decode(event.toList())) as Map<String, dynamic>;
70
+ json.decode(msg) as Map<String, dynamic>;
71
_handleResponse(response);
72
} on FormatException catch (e) {
73
final msg = e.message.toLowerCase();
@@ -136,14 +137,14 @@ class ElectrumClient {
137
return [];
138
});
139
139
- Future<Map<String, Object>> getBalance(String scriptHash) =>
140
+ Future<Map<String, dynamic>> getBalance(String scriptHash) =>
141
call(method: 'blockchain.scripthash.get_balance', params: [scriptHash])
142
.then((dynamic result) {
142
- if (result is Map<String, Object>) {
143
+ if (result is Map<String, dynamic>) {
144
return result;
145
}
146
146
- return <String, Object>{};
147
+ return <String, dynamic>{};
148
});
149
150
Future<List<Map<String, dynamic>>> getHistory(String scriptHash) =>
@@ -151,11 +152,11 @@ class ElectrumClient {
152
.then((dynamic result) {
153
if (result is List) {
154
return result.map((dynamic val) {
154
- if (val is Map<String, Object>) {
155
+ if (val is Map<String, dynamic>) {
156
return val;
157
}
158
158
- return <String, Object>{};
159
+ return <String, dynamic>{};
160
}).toList();
161
}
162
@@ -170,12 +171,12 @@ class ElectrumClient {
171
.then((dynamic result) {
172
if (result is List) {
173
return result.map((dynamic val) {
173
- if (val is Map<String, Object>) {
174
+ if (val is Map<String, dynamic>) {
175
val['address'] = address;
176
return val;
177
}
178
178
- return <String, Object>{};
179
+ return <String, dynamic>{};
180
}).toList();
181
}
182
@@ -187,11 +188,11 @@ class ElectrumClient {
188
.then((dynamic result) {
189
if (result is List) {
190
return result.map((dynamic val) {
190
- if (val is Map<String, Object>) {
191
+ if (val is Map<String, dynamic>) {
192
return val;
193
}
194
194
- return <String, Object>{};
195
+ return <String, dynamic>{};
196
}).toList();
197
}
198
@@ -203,26 +204,26 @@ class ElectrumClient {
204
.then((dynamic result) {
205
if (result is List) {
206
return result.map((dynamic val) {
206
- if (val is Map<String, Object>) {
207
+ if (val is Map<String, dynamic>) {
208
return val;
209
}
210
210
- return <String, Object>{};
211
+ return <String, dynamic>{};
212
}).toList();
213
}
214
215
return [];
216
});
217
217
- Future<Map<String, Object>> getTransactionRaw(
218
+ Future<Map<String, dynamic>> getTransactionRaw(
219
{required String hash}) async =>
220
call(method: 'blockchain.transaction.get', params: [hash, true])
221
.then((dynamic result) {
221
- if (result is Map<String, Object>) {
222
+ if (result is Map<String, dynamic>) {
223
return result;
224
}
225
225
- return <String, Object>{};
226
+ return <String, dynamic>{};
227
});
228
229
Future<String> getTransactionHex(
cw_bitcoin/lib/electrum_wallet.dart
+26
-7
@@ -455,7 +455,13 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
455
.addresses.map((address) => electrumClient
456
.getListUnspentWithAddress(address.address, networkType)
457
.then((unspent) => unspent
458
- .map((unspent) => BitcoinUnspent.fromJSON(address, unspent)))));
458
+ .map((unspent) {
459
+ try {
460
+ return BitcoinUnspent.fromJSON(address, unspent);
461
+ } catch(_) {
462
+ return null;
463
+ }
464
+ }).whereNotNull())));
465
unspentCoins = unspent.expand((e) => e).toList();
466
467
if (unspentCoinsInfo.isEmpty) {
@@ -542,8 +548,9 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
548
confirmations: confirmations);
549
}
550
545
- Future<ElectrumTransactionInfo> fetchTransactionInfo(
551
+ Future<ElectrumTransactionInfo?> fetchTransactionInfo(
552
{required String hash, required int height}) async {
553
+ try {
554
final tx = await getTransactionExpanded(hash: hash, height: height);
555
final addresses = walletAddresses.addresses.map((addr) => addr.address).toSet();
556
return ElectrumTransactionInfo.fromElectrumBundle(
@@ -552,6 +559,9 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
559
networkType,
560
addresses: addresses,
561
height: height);
562
+ } catch(_) {
563
+ return null;
564
+ }
565
}
566
567
@override
@@ -578,12 +588,20 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
588
});
589
final historiesWithDetails = await Future.wait(
590
normalizedHistories
581
- .map((transaction) => fetchTransactionInfo(
582
- hash: transaction['tx_hash'] as String,
583
- height: transaction['height'] as int)));
584
-
591
+ .map((transaction) {
592
+ try {
593
+ return fetchTransactionInfo(
594
+ hash: transaction['tx_hash'] as String,
595
+ height: transaction['height'] as int);
596
+ } catch(_) {
597
+ return Future.value(null);
598
+ }
599
+ }));
600
return historiesWithDetails.fold<Map<String, ElectrumTransactionInfo>>(
601
<String, ElectrumTransactionInfo>{}, (acc, tx) {
602
+ if (tx == null) {
603
+ return acc;
604
+ }
605
acc[tx.id] = acc[tx.id]?.updated(tx) ?? tx;
606
return acc;
607
});
@@ -601,7 +619,8 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
619
walletAddresses.updateReceiveAddresses();
620
await transactionHistory.save();
621
_isTransactionUpdating = false;
604
- } catch (e) {
622
+ } catch (e, stacktrace) {
623
+ print(stacktrace);
624
print(e);
625
_isTransactionUpdating = false;
626
}
lib/reactions/on_wallet_sync_status_change.dart
+14
-10
@@ -21,18 +21,22 @@ void startWalletSyncStatusChangeReaction(
21
_onWalletSyncStatusChangeReaction?.reaction.dispose();
22
_onWalletSyncStatusChangeReaction =
23
reaction((_) => wallet.syncStatus, (SyncStatus status) async {
24
- if (status is ConnectedSyncStatus) {
25
- await wallet.startSync();
24
+ try {
25
+ if (status is ConnectedSyncStatus) {
26
+ await wallet.startSync();
27
27
- if (wallet.type == WalletType.haven) {
28
- await updateHavenRate(fiatConversionStore);
28
+ if (wallet.type == WalletType.haven) {
29
+ await updateHavenRate(fiatConversionStore);
30
+ }
31
}
30
- }
31
- if (status is SyncingSyncStatus) {
32
- await _wakeLock.enableWake();
33
- }
34
- if (status is SyncedSyncStatus || status is FailedSyncStatus) {
35
- await _wakeLock.disableWake();
32
+ if (status is SyncingSyncStatus) {
33
+ await _wakeLock.enableWake();
34
+ }
35
+ if (status is SyncedSyncStatus || status is FailedSyncStatus) {
36
+ await _wakeLock.disableWake();
37
+ }
38
+ } catch(e) {
39
+ print(e.toString());
40
}
41
});
42
}