From d55e635f61c2f91798bc0c19fd31ffc0e813774b Mon Sep 17 00:00:00 2001 From: Serhii Date: Sat, 14 Dec 2024 02:37:48 +0200 Subject: [PATCH] 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 --- cw_bitcoin/lib/electrum.dart | 24 +++---- cw_bitcoin/lib/electrum_wallet.dart | 68 +++++++++---------- .../unspent_coins_list_page.dart | 2 +- 3 files changed, 47 insertions(+), 47 deletions(-) diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index 28e3f47be..4fc4c1ad8 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -235,21 +235,21 @@ class ElectrumClient { return []; }); - Future>> getListUnspent(String scriptHash) => - call(method: 'blockchain.scripthash.listunspent', params: [scriptHash]) - .then((dynamic result) { - if (result is List) { - return result.map((dynamic val) { - if (val is Map) { - return val; - } + Future>> getListUnspent(String scriptHash) async { + final result = await call(method: 'blockchain.scripthash.listunspent', params: [scriptHash]); - return {}; - }).toList(); + if (result is List) { + return result.map((dynamic val) { + if (val is Map) { + return val; } - return []; - }); + return {}; + }).toList(); + } + + return []; + } Future>> getMempool(String scriptHash) => call(method: 'blockchain.scripthash.get_mempool', params: [scriptHash]) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index a5bb9c655..d9041cba4 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -1382,8 +1382,9 @@ abstract class ElectrumWalletBase })); unspentCoins = updatedUnspentCoins; - - final currentWalletUnspentCoins = unspentCoinsInfo.values.where((element) => element.walletId == id); + + final currentWalletUnspentCoins = + unspentCoinsInfo.values.where((element) => element.walletId == id); if (currentWalletUnspentCoins.length != updatedUnspentCoins.length) { unspentCoins.forEach((coin) => addCoinInfo(coin)); @@ -1450,10 +1451,9 @@ abstract class ElectrumWalletBase @action Future addCoinInfo(BitcoinUnspent coin) async { - // Check if the coin is already in the unspentCoinsInfo for the wallet - final existingCoinInfo = unspentCoinsInfo.values.firstWhereOrNull( - (element) => element.walletId == walletInfo.id && element == coin); + final existingCoinInfo = unspentCoinsInfo.values + .firstWhereOrNull((element) => element.walletId == walletInfo.id && element == coin); if (existingCoinInfo == null) { final newInfo = UnspentCoinsInfo( @@ -1475,19 +1475,18 @@ abstract class ElectrumWalletBase Future _refreshUnspentCoinsInfo() async { try { - final List keys = []; + final List keys = []; final currentWalletUnspentCoins = - unspentCoinsInfo.values.where((element) => element.walletId.contains(id)); + unspentCoinsInfo.values.where((record) => record.walletId == id); - if (currentWalletUnspentCoins.isNotEmpty) { - currentWalletUnspentCoins.forEach((element) { - final existUnspentCoins = unspentCoins - .where((coin) => element.hash.contains(coin.hash) && element.vout == coin.vout); + for (final element in currentWalletUnspentCoins) { + if (RegexUtils.addressTypeFromStr(element.address, network) is MwebAddress) continue; - if (existUnspentCoins.isEmpty) { - keys.add(element.key); - } - }); + final existUnspentCoins = unspentCoins.where((coin) => element == coin); + + if (existUnspentCoins.isEmpty) { + keys.add(element.key); + } } if (keys.isNotEmpty) { @@ -1499,7 +1498,8 @@ abstract class ElectrumWalletBase } Future cleanUpDuplicateUnspentCoins() async { - final currentWalletUnspentCoins = unspentCoinsInfo.values.where((element) => element.walletId == id); + final currentWalletUnspentCoins = + unspentCoinsInfo.values.where((element) => element.walletId == id); final Map uniqueUnspentCoins = {}; final List duplicateKeys = []; @@ -1535,7 +1535,8 @@ abstract class ElectrumWalletBase final ownAddresses = walletAddresses.allAddresses.map((addr) => addr.address).toSet(); final receiverAmount = outputs - .where((output) => !ownAddresses.contains(addressFromOutputScript(output.scriptPubKey, network))) + .where((output) => + !ownAddresses.contains(addressFromOutputScript(output.scriptPubKey, network))) .fold(0, (sum, output) => sum + output.amount.toInt()); if (receiverAmount == 0) { @@ -1584,7 +1585,7 @@ abstract class ElectrumWalletBase allInputsAmount += outTransaction.amount.toInt(); final addressRecord = - walletAddresses.allAddresses.firstWhere((element) => element.address == address); + walletAddresses.allAddresses.firstWhere((element) => element.address == address); final btcAddress = RegexUtils.addressTypeFromStr(addressRecord.address, network); final privkey = generateECPrivate( hd: addressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, @@ -1602,7 +1603,7 @@ abstract class ElectrumWalletBase scriptType: _getScriptType(btcAddress), ), ownerDetails: - UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: btcAddress), + UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: btcAddress), ), ); } @@ -1630,7 +1631,7 @@ abstract class ElectrumWalletBase // Calculate the total amount and fees int totalOutAmount = - outputs.fold(0, (previousValue, output) => previousValue + output.value.toInt()); + outputs.fold(0, (previousValue, output) => previousValue + output.value.toInt()); int currentFee = allInputsAmount - totalOutAmount; int remainingFee = newFee - currentFee; @@ -1686,7 +1687,7 @@ abstract class ElectrumWalletBase vout: utxo.vout, scriptType: _getScriptType(address)), ownerDetails: - UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: address), + UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: address), )); allInputsAmount += utxo.value; @@ -1743,11 +1744,11 @@ abstract class ElectrumWalletBase final changeAddresses = walletAddresses.allAddresses.where((element) => element.isHidden); final List changeOutputs = outputs .where((output) => changeAddresses - .any((element) => element.address == output.address.toAddress(network))) + .any((element) => element.address == output.address.toAddress(network))) .toList(); int totalChangeAmount = - changeOutputs.fold(0, (sum, output) => sum + output.value.toInt()); + changeOutputs.fold(0, (sum, output) => sum + output.value.toInt()); // The final amount that the receiver will receive int sendingAmount = allInputsAmount - newFee - totalChangeAmount; @@ -1764,7 +1765,7 @@ abstract class ElectrumWalletBase final transaction = txb.buildTransaction((txDigest, utxo, publicKey, sighash) { final key = - privateKeys.firstWhereOrNull((element) => element.getPublic().toHex() == publicKey); + privateKeys.firstWhereOrNull((element) => element.getPublic().toHex() == publicKey); if (key == null) { throw Exception("Cannot find private key"); } @@ -1774,7 +1775,6 @@ abstract class ElectrumWalletBase } else { return key.signInput(txDigest, sigHash: sighash); } - }); return PendingBitcoinTransaction( @@ -1787,16 +1787,16 @@ abstract class ElectrumWalletBase hasChange: changeOutputs.isNotEmpty, feeRate: newFee.toString(), )..addListener((transaction) async { - transactionHistory.transactions.values.forEach((tx) { - if (tx.id == hash) { - tx.isReplaced = true; - tx.isPending = false; - transactionHistory.addOne(tx); - } + transactionHistory.transactions.values.forEach((tx) { + if (tx.id == hash) { + tx.isReplaced = true; + tx.isPending = false; + transactionHistory.addOne(tx); + } + }); + transactionHistory.addOne(transaction); + await updateBalance(); }); - transactionHistory.addOne(transaction); - await updateBalance(); - }); } catch (e) { throw e; } diff --git a/lib/src/screens/unspent_coins/unspent_coins_list_page.dart b/lib/src/screens/unspent_coins/unspent_coins_list_page.dart index f26a2a17f..d44107939 100644 --- a/lib/src/screens/unspent_coins/unspent_coins_list_page.dart +++ b/lib/src/screens/unspent_coins/unspent_coins_list_page.dart @@ -154,7 +154,7 @@ class UnspentCoinsListFormState extends State { SizedBox(height: 15), Expanded( child: unspentCoinsListViewModel.items.isEmpty - ? Center(child: Text('No unspent coins available\ntry to reconnect',textAlign: TextAlign.center)) + ? Center(child: Text('No unspent coins available',textAlign: TextAlign.center)) : ListView.separated( itemCount: unspentCoinsListViewModel.items.length, separatorBuilder: (_, __) => SizedBox(height: 15),