From a9df2ee285e7fedda06f239a48cf4994609c137e Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Wed, 28 May 2025 13:19:33 +0200 Subject: [PATCH] feat: add unsignedPsbt to PendingBitcoinTransaction --- cw_bitcoin/lib/bitcoin_wallet.dart | 10 ++++-- cw_bitcoin/lib/electrum_wallet.dart | 31 +++++++++++-------- .../lib/pending_bitcoin_transaction.dart | 24 +++++++++----- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 9231022f6..54d7e5a51 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -372,8 +372,13 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { publicKeys: tx.publicKeys!, masterFingerprint: Uint8List(0)); - final originalPsbt = await signPsbt( - base64.encode(transaction.asPsbtV0()), getUtxoWithPrivateKeys()); + if (tx.isViewOnly) { + tx.unsignedPsbt = transaction.serialize(); + return tx; + } + + final originalPsbt = + await signPsbt(base64.encode(transaction.asPsbtV0()), getUtxoWithPrivateKeys()); tx.commitOverride = () async { final sender = await payjoinManager.initSender( @@ -405,6 +410,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { feeRate: "", network: network, hasChange: true, + isViewOnly: false, ).commit(); } diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index a29efa48c..70e20813e 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -1119,7 +1119,8 @@ abstract class ElectrumWalletBase network: network, hasChange: estimatedTx.hasChange, isSendAll: estimatedTx.isSendAll, - hasTaprootInputs: false, // ToDo: (Konsti) Support Taproot + hasTaprootInputs: false, // ToDo: (Konsti) Support Taproot, + isViewOnly: false, )..addListener((transaction) async { transactionHistory.addOne(transaction); await updateBalance(); @@ -1190,18 +1191,21 @@ abstract class ElectrumWalletBase } }); - return PendingBitcoinTransaction(transaction, type, - electrumClient: electrumClient, - amount: estimatedTx.amount, - fee: estimatedTx.fee, - feeRate: feeRateInt.toString(), - network: network, - hasChange: estimatedTx.hasChange, - isSendAll: estimatedTx.isSendAll, - hasTaprootInputs: hasTaprootInputs, - utxos: estimatedTx.utxos, - publicKeys: estimatedTx.publicKeys) - ..addListener((transaction) async { + return PendingBitcoinTransaction( + transaction, + type, + electrumClient: electrumClient, + amount: estimatedTx.amount, + fee: estimatedTx.fee, + feeRate: feeRateInt.toString(), + network: network, + hasChange: estimatedTx.hasChange, + isSendAll: estimatedTx.isSendAll, + hasTaprootInputs: hasTaprootInputs, + utxos: estimatedTx.utxos, + publicKeys: estimatedTx.publicKeys, + isViewOnly: keys.privateKey.isEmpty, + )..addListener((transaction) async { transactionHistory.addOne(transaction); if (estimatedTx.spendsSilentPayment) { transactionHistory.transactions.values.forEach((tx) { @@ -1862,6 +1866,7 @@ abstract class ElectrumWalletBase network: network, hasChange: changeOutputs.isNotEmpty, feeRate: newFee.toString(), + isViewOnly: keys.privateKey.isEmpty, )..addListener((transaction) async { transactionHistory.transactions.values.forEach((tx) { if (tx.id == hash) { diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart index e07786f76..b5906ae97 100644 --- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart +++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart @@ -34,6 +34,8 @@ class PendingBitcoinTransaction with PendingTransaction { this.utxos = const [], this.publicKeys, this.commitOverride, + this.unsignedPsbt, + required this.isViewOnly, }) : _listeners = []; final WalletType type; @@ -46,6 +48,7 @@ class PendingBitcoinTransaction with PendingTransaction { final bool isSendAll; final bool hasChange; final bool hasTaprootInputs; + final bool isViewOnly; List utxos; bool isMweb; String? changeAddressOverride; @@ -55,6 +58,8 @@ class PendingBitcoinTransaction with PendingTransaction { final Map? publicKeys; Future Function()? commitOverride; + Uint8List? unsignedPsbt; + @override String get id => idOverride ?? _tx.txId(); @@ -78,9 +83,11 @@ class PendingBitcoinTransaction with PendingTransaction { try { final change = _tx.outputs.firstWhere((out) => out.isChange); if (changeAddressOverride != null) { - return PendingChange(changeAddressOverride!, BtcUtils.fromSatoshi(change.amount)); + return PendingChange( + changeAddressOverride!, BtcUtils.fromSatoshi(change.amount)); } - return PendingChange(change.scriptPubKey.toAddress(), BtcUtils.fromSatoshi(change.amount)); + return PendingChange( + change.scriptPubKey.toAddress(), BtcUtils.fromSatoshi(change.amount)); } catch (_) { return null; } @@ -129,12 +136,14 @@ class PendingBitcoinTransaction with PendingTransaction { Future _ltcCommit() async { try { - final resp = await CwMweb.broadcast(BroadcastRequest(rawTx: BytesUtils.fromHexString(hex))); + final resp = await CwMweb.broadcast( + BroadcastRequest(rawTx: BytesUtils.fromHexString(hex))); idOverride = resp.txid; } on GrpcError catch (e) { throw BitcoinTransactionCommitFailed(errorMessage: e.message); } catch (e) { - throw BitcoinTransactionCommitFailed(errorMessage: "Unknown error: ${e.toString()}"); + throw BitcoinTransactionCommitFailed( + errorMessage: "Unknown error: ${e.toString()}"); } } @@ -153,7 +162,8 @@ class PendingBitcoinTransaction with PendingTransaction { _listeners.forEach((listener) => listener(transactionInfo())); } - void addListener(void Function(ElectrumTransactionInfo transaction) listener) => + void addListener( + void Function(ElectrumTransactionInfo transaction) listener) => _listeners.add(listener); ElectrumTransactionInfo transactionInfo() => ElectrumTransactionInfo(type, @@ -168,10 +178,10 @@ class PendingBitcoinTransaction with PendingTransaction { inputAddresses: _tx.inputs.map((input) => input.txId).toList(), outputAddresses: outputAddresses, fee: fee); - + @override Future commitUR() { - var sourceBytes = Uint8List.fromList(utf8.encode(hex)); + var sourceBytes = unsignedPsbt!; var cborEncoder = CBOREncoder(); cborEncoder.encodeBytes(sourceBytes); var ur = UR("psbt", cborEncoder.getBytes());