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
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user