diff --git a/electrum/gui/qt/send_tab.py b/electrum/gui/qt/send_tab.py index 4d09ba58a..6294d1d50 100644 --- a/electrum/gui/qt/send_tab.py +++ b/electrum/gui/qt/send_tab.py @@ -483,7 +483,7 @@ class SendTab(QWidget, MessageBoxMixin, Logger): self.amount_e.textEdited.emit("") self.window.show_send_tab() - def read_invoice(self): + def read_invoice(self) -> Optional[Invoice]: if self.check_send_tab_payto_line_and_show_errors(): return try: @@ -491,9 +491,6 @@ class SendTab(QWidget, MessageBoxMixin, Logger): invoice_str = self.payto_e.lightning_invoice if not invoice_str: return - if not self.wallet.has_lightning(): - self.show_error(_('Lightning is disabled')) - return invoice = Invoice.from_bech32(invoice_str) if invoice.amount_msat is None: amount_sat = self.amount_e.get_amount() @@ -502,6 +499,9 @@ class SendTab(QWidget, MessageBoxMixin, Logger): else: self.show_error(_('No amount')) return + if not self.wallet.has_lightning() and not invoice.can_be_paid_onchain(): + self.show_error(_('Lightning is disabled')) + return return invoice else: outputs = self.read_outputs() @@ -646,19 +646,22 @@ class SendTab(QWidget, MessageBoxMixin, Logger): def pay_lightning_invoice(self, invoice: Invoice): amount_sat = invoice.get_amount_sat() - key = invoice.get_id() if amount_sat is None: raise Exception("missing amount for LN invoice") - if not self.wallet.lnworker.can_pay_invoice(invoice): - num_sats_can_send = int(self.wallet.lnworker.num_sats_can_send()) - lightning_needed = amount_sat - num_sats_can_send - lightning_needed += (lightning_needed // 20) # operational safety margin + # note: lnworker might be None if LN is disabled, + # in which case we should still offer the user to pay onchain. + lnworker = self.wallet.lnworker + if lnworker is None or not lnworker.can_pay_invoice(invoice): coins = self.window.get_coins(nonlocal_only=True) - can_pay_onchain = invoice.get_address() and self.wallet.can_pay_onchain(invoice.get_outputs(), coins=coins) - can_pay_with_new_channel = self.wallet.lnworker.suggest_funding_amount(amount_sat, coins=coins) - can_pay_with_swap = self.wallet.lnworker.suggest_swap_to_send(amount_sat, coins=coins) - rebalance_suggestion = self.wallet.lnworker.suggest_rebalance_to_send(amount_sat) - can_rebalance = bool(rebalance_suggestion) and self.window.num_tasks() == 0 + can_pay_onchain = invoice.can_be_paid_onchain() and self.wallet.can_pay_onchain(invoice.get_outputs(), coins=coins) + can_pay_with_new_channel = False + can_pay_with_swap = False + can_rebalance = False + if lnworker: + can_pay_with_new_channel = lnworker.suggest_funding_amount(amount_sat, coins=coins) + can_pay_with_swap = lnworker.suggest_swap_to_send(amount_sat, coins=coins) + rebalance_suggestion = lnworker.suggest_rebalance_to_send(amount_sat) + can_rebalance = bool(rebalance_suggestion) and self.window.num_tasks() == 0 choices = {} if can_rebalance: msg = ''.join([ @@ -685,7 +688,8 @@ class SendTab(QWidget, MessageBoxMixin, Logger): ]) choices[3] = msg msg = _('You cannot pay that invoice using Lightning.') - if self.wallet.lnworker.channels: + if lnworker and lnworker.channels: + num_sats_can_send = int(lnworker.num_sats_can_send()) msg += '\n' + _('Your channels can send {}.').format(self.format_amount(num_sats_can_send) + ' ' + self.base_unit()) if not choices: self.window.show_error(msg) @@ -706,13 +710,14 @@ class SendTab(QWidget, MessageBoxMixin, Logger): self.pay_onchain_dialog(coins, invoice.get_outputs()) return + assert lnworker is not None # FIXME this is currently lying to user as we truncate to satoshis amount_msat = invoice.get_amount_msat() msg = _("Pay lightning invoice?") + '\n\n' + _("This will send {}?").format(self.format_amount_and_units(Decimal(amount_msat)/1000)) if not self.question(msg): return self.save_pending_invoice() - coro = self.wallet.lnworker.pay_invoice(invoice.lightning_invoice, amount_msat=amount_msat) + coro = lnworker.pay_invoice(invoice.lightning_invoice, amount_msat=amount_msat) self.window.run_coroutine_from_thread(coro, _('Sending payment')) def broadcast_transaction(self, tx: Transaction): diff --git a/electrum/invoices.py b/electrum/invoices.py index c7308f206..28f9d11ae 100644 --- a/electrum/invoices.py +++ b/electrum/invoices.py @@ -136,6 +136,12 @@ class Invoice(StoredObject): outputs = self.outputs return outputs + def can_be_paid_onchain(self) -> bool: + if self.is_lightning(): + return bool(self._lnaddr.get_fallback_address()) + else: + return True + def get_expiration_date(self): # 0 means never return self.exp + self.time if self.exp else 0