CW-994 mweb enhancements (#2204)

* add mweb block explorer

* potential fix for #2

* fix spending when mweb is disabled

* Update cw_bitcoin/lib/litecoin_wallet.dart

* fix resolving conflict missing brackets

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
Matthew Fosse
2025-12-02 03:16:21 +01:00
committed by GitHub
co-authored by Omar Hatem
parent 3e4409d2ba
commit 20022c0393
4 changed files with 54 additions and 7 deletions
+7 -1
View File
@@ -11,7 +11,6 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_bitcoin/bitcoin_wallet.dart';
import 'package:cw_bitcoin/litecoin_wallet.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:blockchain_utils/blockchain_utils.dart';
import 'package:collection/collection.dart';
@@ -899,6 +898,13 @@ abstract class ElectrumWalletBase
throw BitcoinTransactionNoDustException();
}
// if mweb isn't enabled, don't consider spending mweb coins:
if (this is LitecoinWallet) {
var mwebEnabled = (this as LitecoinWallet).mwebEnabled;
if (!mwebEnabled) {
coinTypeToSpendFrom = UnspentCoinType.nonMweb;
}
}
// If there is only one output, and the amount to send is more than the max spendable amount
// then it is actually a send all transaction
+21 -5
View File
@@ -886,6 +886,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
if (unspent.vout == 0) {
unspent.isChange = true;
}
// printV("unspent: $unspent ${unspent.vout} ${utxo.value}");
mwebUnspentCoins.add(unspent);
});
@@ -1140,13 +1142,27 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
@override
Future<PendingTransaction> createTransaction(Object credentials) async {
try {
var tx = await super.createTransaction(credentials) as PendingBitcoinTransaction;
var creds;
if (!mwebEnabled) {
BitcoinTransactionCredentials btcCreds = (credentials as BitcoinTransactionCredentials);
// sets unspent coin type to nonMweb:
creds = BitcoinTransactionCredentials(
btcCreds.outputs,
priority: btcCreds.priority,
feeRate: btcCreds.feeRate,
coinTypeToSpendFrom: UnspentCoinType.nonMweb,
);
} else {
creds = credentials;
}
var tx = await super.createTransaction(creds as Object) as PendingBitcoinTransaction;
tx.isMweb = mwebEnabled;
if (!mwebEnabled) {
tx.changeAddressOverride = (await (walletAddresses as LitecoinWalletAddresses)
.getChangeAddress(coinTypeToSpendFrom: UnspentCoinType.nonMweb))
.address;
if (tx.shouldCommitUR()) {
tx.unsignedPsbt = await buildPsbt(tx, false);
}
@@ -1165,17 +1181,17 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
final address = output.address.toLowerCase();
final extractedAddress = output.extractedAddress?.toLowerCase();
if (address.contains("mweb")) {
if (address.startsWith("ltcmweb")) {
hasMwebOutput = true;
}
if (!address.contains("mweb")) {
if (!address.startsWith("ltcmweb")) {
hasRegularOutput = true;
}
if (extractedAddress != null && extractedAddress.isNotEmpty) {
if (extractedAddress.contains("mweb")) {
if (extractedAddress.startsWith("ltcmweb")) {
hasMwebOutput = true;
}
if (!extractedAddress.contains("mweb")) {
if (!extractedAddress.startsWith("ltcmweb")) {
hasRegularOutput = true;
}
}
@@ -188,7 +188,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
if (!element.isSending || element.isFrozen) {
return;
}
if (element.address.contains("mweb")) {
if (element.address.startsWith("ltcmweb")) {
comesFromMweb = true;
}
});
@@ -59,6 +59,7 @@ abstract class TransactionDetailsViewModelBase with Store {
if (!canReplaceByFee) _checkForRBF(tx);
break;
case WalletType.litecoin:
_addLitecoinListItems(tx, dateFormat);
case WalletType.bitcoinCash:
_addElectrumListItems(tx, dateFormat);
break;
@@ -388,6 +389,30 @@ abstract class TransactionDetailsViewModelBase with Store {
items.addAll(_items);
}
void _addLitecoinListItems(TransactionInfo tx, DateFormat dateFormat) {
_addElectrumListItems(tx, dateFormat);
bool isMweb = bitcoin!.txIsMweb(tx);
final _items = [
if (isMweb)
BlockExplorerListItem(
title: S.current.view_in_block_explorer,
value: S.current.view_transaction_on + 'mwebexplorer.com',
onTap: () async {
try {
final uri = Uri.parse('https://www.mwebexplorer.com/blocks/block/${tx.height}');
if (await canLaunchUrl(uri))
await launchUrl(uri, mode: LaunchMode.externalApplication);
} catch (e) {}
},
key: ValueKey('block_explorer_list_item_mweb_wallet_type_key'),
),
];
items.addAll(_items);
}
void _addHavenListItems(TransactionInfo tx, DateFormat dateFormat) {
items.addAll([
StandartListItem(