Merge pull request #10128 from f321x/fix_4111

fix: psbt_nostr: don't save tx without txid
This commit is contained in:
ghost43
2025-08-18 16:30:16 +00:00
committed by GitHub
5 changed files with 27 additions and 15 deletions

View File

@@ -278,6 +278,7 @@ class CosignerWallet(Logger):
on_failure: Callable[[str], None] = None,
on_success: Callable[[], None] = None
) -> None:
assert tx.txid(), "Shouldn't allow to save tx without txid"
try:
# TODO: adding tx should be handled more gracefully here:
# 1) don't replace tx with same tx with less signatures

View File

@@ -48,7 +48,7 @@ class QReceiveSignalObject(QObject):
QObject.__init__(self)
self._plugin = plugin
cosignerReceivedPsbt = pyqtSignal(str, str, str, str)
cosignerReceivedPsbt = pyqtSignal(str, str, str, str, bool)
sendPsbtFailed = pyqtSignal(str, arguments=['reason'])
sendPsbtSuccess = pyqtSignal()
@@ -138,7 +138,8 @@ class QmlCosignerWallet(EventListener, CosignerWallet):
def on_event_psbt_nostr_received(self, wallet, pubkey, event_id, tx: 'PartialTransaction', label: str):
if self.wallet == wallet:
self.tx = tx
self.plugin.so.cosignerReceivedPsbt.emit(pubkey, event_id, tx.serialize(), label)
can_be_saved = tx.txid() is not None
self.plugin.so.cosignerReceivedPsbt.emit(pubkey, event_id, tx.serialize(), label, can_be_saved)
def close(self):
super().close()
@@ -173,5 +174,5 @@ class QmlCosignerWallet(EventListener, CosignerWallet):
def reject_psbt(self, event_id):
self.mark_pending_event_rcvd(event_id)
def on_add_fail(self):
self.logger.error('failed to add tx to wallet')
def on_add_fail(self, error_msg: str):
self.logger.error(f'failed to add tx to wallet: {error_msg}')

View File

@@ -17,6 +17,7 @@ ElDialog {
}
property string tx_label
property bool can_be_saved
property int choice: PsbtReceiveDialog.Choice.None
// TODO: it might be better to defer popup until no dialogs are shown
@@ -81,6 +82,7 @@ ElDialog {
Layout.preferredWidth: 1
text: qsTr('Save to Wallet')
icon.source: Qt.resolvedUrl('../../../gui/icons/wallet.png')
visible: dialog.can_be_saved
onClicked: {
choice = PsbtReceiveDialog.Choice.Save
doAccept()

View File

@@ -7,9 +7,10 @@ import "../../../gui/qml/components/controls"
Item {
Connections {
target: AppController ? AppController.plugin('psbt_nostr') : null
function onCosignerReceivedPsbt(pubkey, event, tx, label) {
function onCosignerReceivedPsbt(pubkey, event, tx, label, can_be_saved) {
var dialog = psbtReceiveDialog.createObject(app, {
tx_label: label
tx_label: label,
can_be_saved: can_be_saved
})
dialog.accepted.connect(function () {
if (dialog.choice == PsbtReceiveDialog.Choice.Open) {

View File

@@ -102,7 +102,8 @@ class QtCosignerWallet(EventListener, CosignerWallet):
self.obj.cosignerReceivedPsbt.emit(*args) # put on UI thread via signal
def send_to_cosigners(self, tx: Union['Transaction', 'PartialTransaction'], label: str):
self.add_transaction_to_wallet(tx, label=label, on_failure=self.on_add_fail)
if tx.txid():
self.add_transaction_to_wallet(tx, label=label, on_failure=self.on_add_fail)
self.send_psbt(tx, label)
def do_send(self, messages: List[Tuple[str, dict]], txid: Optional[str] = None):
@@ -120,8 +121,10 @@ class QtCosignerWallet(EventListener, CosignerWallet):
except Exception as e:
self.window.show_error(str(e))
return
self.window.show_message(
_("Your transaction was sent to your cosigners via Nostr.") + '\n\n' + txid)
message = _("Your transaction was sent to your cosigners via Nostr.")
if txid:
message += '\n\n' + txid
self.window.show_message(message)
def on_receive(self, pubkey, event_id, tx, label):
msg = '<br/>'.join([
@@ -129,13 +132,17 @@ class QtCosignerWallet(EventListener, CosignerWallet):
_("A transaction was received from your cosigner with label: <br/><big>{}</big><br/>").format(label),
_("Do you want to open it now?")
])
result = self.window.show_message(msg, rich_text=True, icon=QMessageBox.Icon.Question, buttons=[
QMessageBox.StandardButton.Open,
(QPushButton('Discard'), QMessageBox.ButtonRole.DestructiveRole, 100),
(QPushButton('Save to wallet'), QMessageBox.ButtonRole.AcceptRole, 101)]
)
buttons = [
QMessageBox.StandardButton.Open,
(QPushButton('Discard'), QMessageBox.ButtonRole.DestructiveRole, 100),
]
if tx.txid(): # cannot add tx without txid to wallet history (e.g. unsigned legacy tx)
buttons.append(
(QPushButton('Save to wallet'), QMessageBox.ButtonRole.AcceptRole, 101) # type: ignore
)
result = self.window.show_message(msg, rich_text=True, icon=QMessageBox.Icon.Question, buttons=buttons)
if result == QMessageBox.StandardButton.Open:
if label:
if label and tx.txid():
self.wallet.set_label(tx.txid(), label)
show_transaction(tx, parent=self.window, prompt_if_unsaved=True, on_closed=partial(self.on_tx_dialog_closed, event_id))
else: