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: