Browse Source

qt send: use bolt11 fallback addr even if LN is disabled

Given a wallet with LN disabled,
and a bolt11 invoice (or a bip21 uri that only contains bolt11 but lacks a top-level address),
if the bolt11 invoice includes a fallback address,
we would previously just error "Lightning is disabled".

Now we offer the user to pay on-chain using the fallback address.

closes https://github.com/spesmilo/electrum/issues/8047
patch-4
SomberNight 2 years ago
parent
commit
df2d0f4e1f
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 37
      electrum/gui/qt/send_tab.py
  2. 6
      electrum/invoices.py

37
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):

6
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

Loading…
Cancel
Save