diff --git a/electrum/plugins/psbt_nostr/psbt_nostr.py b/electrum/plugins/psbt_nostr/psbt_nostr.py index b084c0e41..de085bf8f 100644 --- a/electrum/plugins/psbt_nostr/psbt_nostr.py +++ b/electrum/plugins/psbt_nostr/psbt_nostr.py @@ -278,6 +278,7 @@ class CosignerWallet(Logger): on_failure: Callable = None, on_success: Callable = 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 diff --git a/electrum/plugins/psbt_nostr/qml.py b/electrum/plugins/psbt_nostr/qml.py index 7275fc382..3ad7ec158 100644 --- a/electrum/plugins/psbt_nostr/qml.py +++ b/electrum/plugins/psbt_nostr/qml.py @@ -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}') diff --git a/electrum/plugins/psbt_nostr/qml/PsbtReceiveDialog.qml b/electrum/plugins/psbt_nostr/qml/PsbtReceiveDialog.qml index 19d1352e4..286324ff8 100644 --- a/electrum/plugins/psbt_nostr/qml/PsbtReceiveDialog.qml +++ b/electrum/plugins/psbt_nostr/qml/PsbtReceiveDialog.qml @@ -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() diff --git a/electrum/plugins/psbt_nostr/qml/main.qml b/electrum/plugins/psbt_nostr/qml/main.qml index 2c2d5f9d6..3990738f3 100644 --- a/electrum/plugins/psbt_nostr/qml/main.qml +++ b/electrum/plugins/psbt_nostr/qml/main.qml @@ -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) { diff --git a/electrum/plugins/psbt_nostr/qt.py b/electrum/plugins/psbt_nostr/qt.py index dc9f86f71..eee328570 100644 --- a/electrum/plugins/psbt_nostr/qt.py +++ b/electrum/plugins/psbt_nostr/qt.py @@ -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 = '
'.join([ @@ -129,13 +132,17 @@ class QtCosignerWallet(EventListener, CosignerWallet): _("A transaction was received from your cosigner with label:
{}
").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: