Cw 853 mweb utxos are not displayed in coin control screen (#1873)
* fix displaying mweb utxos * fallback for failed electrum UTXO updates * remove throwing uncaught exception and un needed try/catch --------- Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
Serhii committed
Dec 14, 2024 at 02:37 UTC
d55e635f61c2f91798bc0c19fd31ffc0e813774b
3 files changed
+47
-47
cw_bitcoin/lib/electrum.dart
+12
-12
@@ -235,21 +235,21 @@ class ElectrumClient {
235
return [];
236
});
237
238
- Future<List<Map<String, dynamic>>> getListUnspent(String scriptHash) =>
239
- call(method: 'blockchain.scripthash.listunspent', params: [scriptHash])
240
- .then((dynamic result) {
241
- if (result is List) {
242
- return result.map((dynamic val) {
243
- if (val is Map<String, dynamic>) {
244
- return val;
245
- }
238
+ Future<List<Map<String, dynamic>>> getListUnspent(String scriptHash) async {
239
+ final result = await call(method: 'blockchain.scripthash.listunspent', params: [scriptHash]);
240
247
- return <String, dynamic>{};
248
- }).toList();
241
+ if (result is List) {
242
+ return result.map((dynamic val) {
243
+ if (val is Map<String, dynamic>) {
244
+ return val;
245
}
246
251
- return [];
252
- });
247
+ return <String, dynamic>{};
248
+ }).toList();
249
+ }
250
+
251
+ return [];
252
+ }
253
254
Future<List<Map<String, dynamic>>> getMempool(String scriptHash) =>
255
call(method: 'blockchain.scripthash.get_mempool', params: [scriptHash])
cw_bitcoin/lib/electrum_wallet.dart
+34
-34
@@ -1382,8 +1382,9 @@ abstract class ElectrumWalletBase
1382
}));
1383
1384
unspentCoins = updatedUnspentCoins;
1385
-
1386
- final currentWalletUnspentCoins = unspentCoinsInfo.values.where((element) => element.walletId == id);
1385
+
1386
+ final currentWalletUnspentCoins =
1387
+ unspentCoinsInfo.values.where((element) => element.walletId == id);
1388
1389
if (currentWalletUnspentCoins.length != updatedUnspentCoins.length) {
1390
unspentCoins.forEach((coin) => addCoinInfo(coin));
@@ -1450,10 +1451,9 @@ abstract class ElectrumWalletBase
1451
1452
@action
1453
Future<void> addCoinInfo(BitcoinUnspent coin) async {
1453
-
1454
// Check if the coin is already in the unspentCoinsInfo for the wallet
1455
- final existingCoinInfo = unspentCoinsInfo.values.firstWhereOrNull(
1456
- (element) => element.walletId == walletInfo.id && element == coin);
1455
+ final existingCoinInfo = unspentCoinsInfo.values
1456
+ .firstWhereOrNull((element) => element.walletId == walletInfo.id && element == coin);
1457
1458
if (existingCoinInfo == null) {
1459
final newInfo = UnspentCoinsInfo(
@@ -1475,19 +1475,18 @@ abstract class ElectrumWalletBase
1475
1476
Future<void> _refreshUnspentCoinsInfo() async {
1477
try {
1478
- final List<dynamic> keys = <dynamic>[];
1478
+ final List<dynamic> keys = [];
1479
final currentWalletUnspentCoins =
1480
- unspentCoinsInfo.values.where((element) => element.walletId.contains(id));
1480
+ unspentCoinsInfo.values.where((record) => record.walletId == id);
1481
1482
- if (currentWalletUnspentCoins.isNotEmpty) {
1483
- currentWalletUnspentCoins.forEach((element) {
1484
- final existUnspentCoins = unspentCoins
1485
- .where((coin) => element.hash.contains(coin.hash) && element.vout == coin.vout);
1482
+ for (final element in currentWalletUnspentCoins) {
1483
+ if (RegexUtils.addressTypeFromStr(element.address, network) is MwebAddress) continue;
1484
1487
- if (existUnspentCoins.isEmpty) {
1488
- keys.add(element.key);
1489
- }
1490
- });
1485
+ final existUnspentCoins = unspentCoins.where((coin) => element == coin);
1486
+
1487
+ if (existUnspentCoins.isEmpty) {
1488
+ keys.add(element.key);
1489
+ }
1490
}
1491
1492
if (keys.isNotEmpty) {
@@ -1499,7 +1498,8 @@ abstract class ElectrumWalletBase
1498
}
1499
1500
Future<void> cleanUpDuplicateUnspentCoins() async {
1502
- final currentWalletUnspentCoins = unspentCoinsInfo.values.where((element) => element.walletId == id);
1501
+ final currentWalletUnspentCoins =
1502
+ unspentCoinsInfo.values.where((element) => element.walletId == id);
1503
final Map<String, UnspentCoinsInfo> uniqueUnspentCoins = {};
1504
final List<dynamic> duplicateKeys = [];
1505
@@ -1535,7 +1535,8 @@ abstract class ElectrumWalletBase
1535
final ownAddresses = walletAddresses.allAddresses.map((addr) => addr.address).toSet();
1536
1537
final receiverAmount = outputs
1538
- .where((output) => !ownAddresses.contains(addressFromOutputScript(output.scriptPubKey, network)))
1538
+ .where((output) =>
1539
+ !ownAddresses.contains(addressFromOutputScript(output.scriptPubKey, network)))
1540
.fold<int>(0, (sum, output) => sum + output.amount.toInt());
1541
1542
if (receiverAmount == 0) {
@@ -1584,7 +1585,7 @@ abstract class ElectrumWalletBase
1585
allInputsAmount += outTransaction.amount.toInt();
1586
1587
final addressRecord =
1587
- walletAddresses.allAddresses.firstWhere((element) => element.address == address);
1588
+ walletAddresses.allAddresses.firstWhere((element) => element.address == address);
1589
final btcAddress = RegexUtils.addressTypeFromStr(addressRecord.address, network);
1590
final privkey = generateECPrivate(
1591
hd: addressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd,
@@ -1602,7 +1603,7 @@ abstract class ElectrumWalletBase
1603
scriptType: _getScriptType(btcAddress),
1604
),
1605
ownerDetails:
1605
- UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: btcAddress),
1606
+ UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: btcAddress),
1607
),
1608
);
1609
}
@@ -1630,7 +1631,7 @@ abstract class ElectrumWalletBase
1631
1632
// Calculate the total amount and fees
1633
int totalOutAmount =
1633
- outputs.fold<int>(0, (previousValue, output) => previousValue + output.value.toInt());
1634
+ outputs.fold<int>(0, (previousValue, output) => previousValue + output.value.toInt());
1635
int currentFee = allInputsAmount - totalOutAmount;
1636
int remainingFee = newFee - currentFee;
1637
@@ -1686,7 +1687,7 @@ abstract class ElectrumWalletBase
1687
vout: utxo.vout,
1688
scriptType: _getScriptType(address)),
1689
ownerDetails:
1689
- UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: address),
1690
+ UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: address),
1691
));
1692
1693
allInputsAmount += utxo.value;
@@ -1743,11 +1744,11 @@ abstract class ElectrumWalletBase
1744
final changeAddresses = walletAddresses.allAddresses.where((element) => element.isHidden);
1745
final List<BitcoinOutput> changeOutputs = outputs
1746
.where((output) => changeAddresses
1746
- .any((element) => element.address == output.address.toAddress(network)))
1747
+ .any((element) => element.address == output.address.toAddress(network)))
1748
.toList();
1749
1750
int totalChangeAmount =
1750
- changeOutputs.fold<int>(0, (sum, output) => sum + output.value.toInt());
1751
+ changeOutputs.fold<int>(0, (sum, output) => sum + output.value.toInt());
1752
1753
// The final amount that the receiver will receive
1754
int sendingAmount = allInputsAmount - newFee - totalChangeAmount;
@@ -1764,7 +1765,7 @@ abstract class ElectrumWalletBase
1765
1766
final transaction = txb.buildTransaction((txDigest, utxo, publicKey, sighash) {
1767
final key =
1767
- privateKeys.firstWhereOrNull((element) => element.getPublic().toHex() == publicKey);
1768
+ privateKeys.firstWhereOrNull((element) => element.getPublic().toHex() == publicKey);
1769
if (key == null) {
1770
throw Exception("Cannot find private key");
1771
}
@@ -1774,7 +1775,6 @@ abstract class ElectrumWalletBase
1775
} else {
1776
return key.signInput(txDigest, sigHash: sighash);
1777
}
1777
-
1778
});
1779
1780
return PendingBitcoinTransaction(
@@ -1787,16 +1787,16 @@ abstract class ElectrumWalletBase
1787
hasChange: changeOutputs.isNotEmpty,
1788
feeRate: newFee.toString(),
1789
)..addListener((transaction) async {
1790
- transactionHistory.transactions.values.forEach((tx) {
1791
- if (tx.id == hash) {
1792
- tx.isReplaced = true;
1793
- tx.isPending = false;
1794
- transactionHistory.addOne(tx);
1795
- }
1790
+ transactionHistory.transactions.values.forEach((tx) {
1791
+ if (tx.id == hash) {
1792
+ tx.isReplaced = true;
1793
+ tx.isPending = false;
1794
+ transactionHistory.addOne(tx);
1795
+ }
1796
+ });
1797
+ transactionHistory.addOne(transaction);
1798
+ await updateBalance();
1799
});
1797
- transactionHistory.addOne(transaction);
1798
- await updateBalance();
1799
- });
1800
} catch (e) {
1801
throw e;
1802
}
lib/src/screens/unspent_coins/unspent_coins_list_page.dart
+1
-1
@@ -154,7 +154,7 @@ class UnspentCoinsListFormState extends State<UnspentCoinsListForm> {
154
SizedBox(height: 15),
155
Expanded(
156
child: unspentCoinsListViewModel.items.isEmpty
157
- ? Center(child: Text('No unspent coins available\ntry to reconnect',textAlign: TextAlign.center))
157
+ ? Center(child: Text('No unspent coins available',textAlign: TextAlign.center))
158
: ListView.separated(
159
itemCount: unspentCoinsListViewModel.items.length,
160
separatorBuilder: (_, __) => SizedBox(height: 15),