diff --git a/electrum/gui/qml/components/InvoiceDialog.qml b/electrum/gui/qml/components/InvoiceDialog.qml index aa89d1d97..80bb7a535 100644 --- a/electrum/gui/qml/components/InvoiceDialog.qml +++ b/electrum/gui/qml/components/InvoiceDialog.qml @@ -487,10 +487,6 @@ ElDialog { if (amountMax.checked) invoice.amountOverride.isMax = true } - if (!invoice.isSaved) { - // save invoice if newly parsed - invoice.saveInvoice() - } doPay() // only signal here } } @@ -506,9 +502,6 @@ ElDialog { } if (payImmediately) { if (invoice.canPay) { - if (!invoice.isSaved) { - invoice.saveInvoice() - } doPay() } } diff --git a/electrum/gui/qml/components/WalletMainView.qml b/electrum/gui/qml/components/WalletMainView.qml index e17b4efae..50d13c5b7 100644 --- a/electrum/gui/qml/components/WalletMainView.qml +++ b/electrum/gui/qml/components/WalletMainView.qml @@ -114,6 +114,7 @@ Item { }) var canComplete = !Daemon.currentWallet.isWatchOnly && Daemon.currentWallet.canSignWithoutCosigner dialog.accepted.connect(function() { + invoice.saveInvoice() if (!canComplete) { if (Daemon.currentWallet.isWatchOnly) { dialog.finalizer.saveOrShow() diff --git a/electrum/gui/qml/qeinvoice.py b/electrum/gui/qml/qeinvoice.py index 061c2aca1..cf796f725 100644 --- a/electrum/gui/qml/qeinvoice.py +++ b/electrum/gui/qml/qeinvoice.py @@ -1,3 +1,4 @@ +import copy import threading from enum import IntEnum from typing import Optional, Dict, Any @@ -213,14 +214,11 @@ class QEInvoice(QObject, QtEventListener): @key.setter def key(self, key): - if self._key != key: - self._key = key - if self._effectiveInvoice and self._effectiveInvoice.get_id() == key: - return - invoice = self._wallet.wallet.get_invoice(key) - self._logger.debug(f'invoice from key {key}: {repr(invoice)}') - self.set_effective_invoice(invoice) - self.keyChanged.emit() + self._key = key + invoice = copy.copy(self._wallet.wallet.get_invoice(key)) # copy, so any mutations stay out of wallet invoice list + self._logger.debug(f'invoice from key {key}: {repr(invoice)}') + self.set_effective_invoice(invoice) + self.keyChanged.emit() userinfoChanged = pyqtSignal() @pyqtProperty(str, notify=userinfoChanged) @@ -386,12 +384,13 @@ class QEInvoice(QObject, QtEventListener): if self.invoiceType != QEInvoice.Type.LightningInvoice: raise Exception('payLightningInvoice can only pay lightning invoices') + amount_msat = None if self.amount.isEmpty: if self.amountOverride.isEmpty: raise Exception('can not pay 0 amount') - self._effectiveInvoice.set_amount_msat(self.amountOverride.satsInt * 1000) + amount_msat = self.amountOverride.satsInt * 1000 - self._wallet.pay_lightning_invoice(self._effectiveInvoice) + self._wallet.pay_lightning_invoice(self._effectiveInvoice, amount_msat) def get_max_spendable_onchain(self): spendable = self._wallet.confirmedBalance.satsInt @@ -505,6 +504,7 @@ class QEInvoiceParser(QEInvoice): self._logger.debug('setValidLightningInvoice') if not invoice.is_lightning(): raise Exception('unexpected Onchain invoice') + self._key = invoice.get_id() self.set_effective_invoice(invoice) def setValidLNURLPayRequest(self): @@ -707,6 +707,6 @@ class QEInvoiceParser(QEInvoice): self.canSave = False self._wallet.wallet.save_invoice(self._effectiveInvoice) - self.key = self._effectiveInvoice.get_id() - self._wallet.invoiceModel.addInvoice(self.key) - self.invoiceSaved.emit(self.key) + self._key = self._effectiveInvoice.get_id() + self._wallet.invoiceModel.addInvoice(self._key) + self.invoiceSaved.emit(self._key) diff --git a/electrum/gui/qml/qeinvoicelistmodel.py b/electrum/gui/qml/qeinvoicelistmodel.py index f727a8ebf..a7825d276 100644 --- a/electrum/gui/qml/qeinvoicelistmodel.py +++ b/electrum/gui/qml/qeinvoicelistmodel.py @@ -132,7 +132,7 @@ class QEAbstractInvoiceListModel(QAbstractListModel): item['address'] = '' item['date'] = format_time(item['timestamp']) item['amount'] = QEAmount(from_invoice=invoice) - item['onchain_fallback'] = invoice.is_lightning() and invoice.get_address() + item['onchain_fallback'] = invoice.is_lightning() and bool(invoice.get_address()) return item diff --git a/electrum/gui/qml/qewallet.py b/electrum/gui/qml/qewallet.py index e35d16b6d..a279d21f8 100644 --- a/electrum/gui/qml/qewallet.py +++ b/electrum/gui/qml/qewallet.py @@ -656,8 +656,23 @@ class QEWallet(AuthMixin, QObject, QtEventListener): self.paymentAuthRejected.emit() @auth_protect(message=_('Pay lightning invoice?'), reject='ln_auth_rejected') - def pay_lightning_invoice(self, invoice: 'Invoice'): - amount_msat = invoice.get_amount_msat() + def pay_lightning_invoice(self, invoice: 'Invoice', amount_msat: int = None): + # at this point, the user confirmed the payment, potentially with an override amount. + # we save the invoice with the override amount if there was no amount defined in the invoice. + # (this is similar to what the desktop client does) + # + # Note: amount_msat can be greater than the invoice-specified amount. This is validated and handled + # in lnworker.pay_invoice() + if amount_msat is not None: + assert type(amount_msat) is int + if invoice.get_amount_msat() is None: + invoice.set_amount_msat(amount_msat) + else: + amount_msat = invoice.get_amount_msat() + + self.wallet.save_invoice(invoice) + if self._invoiceModel: + self._invoiceModel.initModel() def pay_thread(): try: