Qt: add bolt11_fallback and bip21_lightning options to preferences
This commit is contained in:
@@ -1268,11 +1268,11 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
|
|||||||
|
|
||||||
def show_receive_request(self, req):
|
def show_receive_request(self, req):
|
||||||
addr = req.get_address() or ''
|
addr = req.get_address() or ''
|
||||||
URI = req.get_bip21_URI() if addr else ''
|
|
||||||
lnaddr = req.lightning_invoice or ''
|
|
||||||
can_receive_lightning = self.wallet.lnworker and req.get_amount_sat() <= self.wallet.lnworker.num_sats_can_receive()
|
can_receive_lightning = self.wallet.lnworker and req.get_amount_sat() <= self.wallet.lnworker.num_sats_can_receive()
|
||||||
if not can_receive_lightning:
|
lnaddr = req.lightning_invoice if can_receive_lightning else None
|
||||||
lnaddr = ''
|
bip21_lightning = lnaddr if self.config.get('bip21_lightning', False) else None
|
||||||
|
URI = req.get_bip21_URI(lightning=bip21_lightning)
|
||||||
|
lnaddr = lnaddr or ''
|
||||||
icon_name = "lightning.png" if can_receive_lightning else "lightning_disconnected.png"
|
icon_name = "lightning.png" if can_receive_lightning else "lightning_disconnected.png"
|
||||||
self.receive_tabs.setTabIcon(2, read_QIcon(icon_name))
|
self.receive_tabs.setTabIcon(2, read_QIcon(icon_name))
|
||||||
# encode lightning invoices as uppercase so QR encoding can use
|
# encode lightning invoices as uppercase so QR encoding can use
|
||||||
@@ -1673,7 +1673,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
|
|||||||
choices = {}
|
choices = {}
|
||||||
if can_pay_onchain:
|
if can_pay_onchain:
|
||||||
msg = ''.join([
|
msg = ''.join([
|
||||||
_('Pay this invoice onchain'), '\n',
|
_('Pay onchain'), '\n',
|
||||||
_('Funds will be sent to the invoice fallback address.')
|
_('Funds will be sent to the invoice fallback address.')
|
||||||
])
|
])
|
||||||
choices[0] = msg
|
choices[0] = msg
|
||||||
@@ -1694,7 +1694,6 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
|
|||||||
msg = _('You cannot pay that invoice using Lightning.')
|
msg = _('You cannot pay that invoice using Lightning.')
|
||||||
if self.wallet.lnworker.channels:
|
if self.wallet.lnworker.channels:
|
||||||
msg += '\n' + _('Your channels can send {}.').format(self.format_amount(num_sats_can_send) + self.base_unit())
|
msg += '\n' + _('Your channels can send {}.').format(self.format_amount(num_sats_can_send) + self.base_unit())
|
||||||
|
|
||||||
r = self.query_choice(msg, choices)
|
r = self.query_choice(msg, choices)
|
||||||
if r is not None:
|
if r is not None:
|
||||||
self.save_pending_invoice()
|
self.save_pending_invoice()
|
||||||
@@ -2162,6 +2161,10 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
|
|||||||
amount = out.get('amount')
|
amount = out.get('amount')
|
||||||
label = out.get('label')
|
label = out.get('label')
|
||||||
message = out.get('message')
|
message = out.get('message')
|
||||||
|
lightning = out.get('lightning')
|
||||||
|
if lightning:
|
||||||
|
self.set_ln_invoice(lightning)
|
||||||
|
return
|
||||||
# use label as description (not BIP21 compliant)
|
# use label as description (not BIP21 compliant)
|
||||||
if label and not message:
|
if label and not message:
|
||||||
message = label
|
message = label
|
||||||
|
|||||||
@@ -97,6 +97,21 @@ class SettingsDialog(WindowModalDialog):
|
|||||||
self.window.refresh_tabs()
|
self.window.refresh_tabs()
|
||||||
nz.valueChanged.connect(on_nz)
|
nz.valueChanged.connect(on_nz)
|
||||||
|
|
||||||
|
# invoices
|
||||||
|
bolt11_fallback_cb = QCheckBox(_('Add on-chain fallback to lightning invoices'))
|
||||||
|
bolt11_fallback_cb.setChecked(bool(self.config.get('bolt11_fallback', True)))
|
||||||
|
bolt11_fallback_cb.setToolTip(_('Add fallback addresses to BOLT11 lightning invoices.'))
|
||||||
|
def on_bolt11_fallback(x):
|
||||||
|
self.config.set_key('bolt11_fallback', bool(x))
|
||||||
|
bolt11_fallback_cb.stateChanged.connect(on_bolt11_fallback)
|
||||||
|
|
||||||
|
bip21_lightning_cb = QCheckBox(_('Add lightning invoice to bitcoin URIs'))
|
||||||
|
bip21_lightning_cb.setChecked(bool(self.config.get('bip21_lightning', False)))
|
||||||
|
bip21_lightning_cb.setToolTip(_('This may create larger qr codes.'))
|
||||||
|
def on_bip21_lightning(x):
|
||||||
|
self.config.set_key('bip21_lightning', bool(x))
|
||||||
|
bip21_lightning_cb.stateChanged.connect(on_bip21_lightning)
|
||||||
|
|
||||||
use_rbf = bool(self.config.get('use_rbf', True))
|
use_rbf = bool(self.config.get('use_rbf', True))
|
||||||
use_rbf_cb = QCheckBox(_('Use Replace-By-Fee'))
|
use_rbf_cb = QCheckBox(_('Use Replace-By-Fee'))
|
||||||
use_rbf_cb.setChecked(use_rbf)
|
use_rbf_cb.setChecked(use_rbf)
|
||||||
@@ -483,6 +498,9 @@ class SettingsDialog(WindowModalDialog):
|
|||||||
gui_widgets.append((nz_label, nz))
|
gui_widgets.append((nz_label, nz))
|
||||||
gui_widgets.append((msat_cb, None))
|
gui_widgets.append((msat_cb, None))
|
||||||
gui_widgets.append((thousandsep_cb, None))
|
gui_widgets.append((thousandsep_cb, None))
|
||||||
|
invoices_widgets = []
|
||||||
|
invoices_widgets.append((bolt11_fallback_cb, None))
|
||||||
|
invoices_widgets.append((bip21_lightning_cb, None))
|
||||||
tx_widgets = []
|
tx_widgets = []
|
||||||
tx_widgets.append((usechange_cb, None))
|
tx_widgets.append((usechange_cb, None))
|
||||||
tx_widgets.append((use_rbf_cb, None))
|
tx_widgets.append((use_rbf_cb, None))
|
||||||
@@ -513,6 +531,7 @@ class SettingsDialog(WindowModalDialog):
|
|||||||
|
|
||||||
tabs_info = [
|
tabs_info = [
|
||||||
(gui_widgets, _('Appearance')),
|
(gui_widgets, _('Appearance')),
|
||||||
|
(invoices_widgets, _('Invoices')),
|
||||||
(tx_widgets, _('Transactions')),
|
(tx_widgets, _('Transactions')),
|
||||||
(lightning_widgets, _('Lightning')),
|
(lightning_widgets, _('Lightning')),
|
||||||
(fiat_widgets, _('Fiat')),
|
(fiat_widgets, _('Fiat')),
|
||||||
|
|||||||
@@ -157,12 +157,21 @@ class Invoice(StoredObject):
|
|||||||
return None
|
return None
|
||||||
return int(amount_msat / 1000)
|
return int(amount_msat / 1000)
|
||||||
|
|
||||||
def get_bip21_URI(self):
|
def get_bip21_URI(self, lightning=None):
|
||||||
from electrum.util import create_bip21_uri
|
from electrum.util import create_bip21_uri
|
||||||
addr = self.get_address()
|
addr = self.get_address()
|
||||||
amount = int(self.get_amount_sat())
|
amount = int(self.get_amount_sat())
|
||||||
message = self.message
|
message = self.message
|
||||||
uri = create_bip21_uri(addr, amount, message)
|
extra = {}
|
||||||
|
if self.time and self.exp:
|
||||||
|
extra['time'] = str(self.time)
|
||||||
|
extra['exp'] = str(self.exp)
|
||||||
|
# only if we can receive
|
||||||
|
if lightning:
|
||||||
|
extra['lightning'] = lightning
|
||||||
|
if not addr and lightning:
|
||||||
|
return "bitcoin:?lightning="+lightning
|
||||||
|
uri = create_bip21_uri(addr, amount, message, extra_query_params=extra)
|
||||||
return str(uri)
|
return str(uri)
|
||||||
|
|
||||||
@lightning_invoice.validator
|
@lightning_invoice.validator
|
||||||
|
|||||||
@@ -942,6 +942,7 @@ def parse_URI(uri: str, on_pr: Callable = None, *, loop=None) -> dict:
|
|||||||
"""Raises InvalidBitcoinURI on malformed URI."""
|
"""Raises InvalidBitcoinURI on malformed URI."""
|
||||||
from . import bitcoin
|
from . import bitcoin
|
||||||
from .bitcoin import COIN, TOTAL_COIN_SUPPLY_LIMIT_IN_BTC
|
from .bitcoin import COIN, TOTAL_COIN_SUPPLY_LIMIT_IN_BTC
|
||||||
|
from .lnaddr import lndecode
|
||||||
|
|
||||||
if not isinstance(uri, str):
|
if not isinstance(uri, str):
|
||||||
raise InvalidBitcoinURI(f"expected string, not {repr(uri)}")
|
raise InvalidBitcoinURI(f"expected string, not {repr(uri)}")
|
||||||
@@ -1004,6 +1005,17 @@ def parse_URI(uri: str, on_pr: Callable = None, *, loop=None) -> dict:
|
|||||||
out['sig'] = bh2u(bitcoin.base_decode(out['sig'], base=58))
|
out['sig'] = bh2u(bitcoin.base_decode(out['sig'], base=58))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise InvalidBitcoinURI(f"failed to parse 'sig' field: {repr(e)}") from e
|
raise InvalidBitcoinURI(f"failed to parse 'sig' field: {repr(e)}") from e
|
||||||
|
if 'lightning' in out:
|
||||||
|
try:
|
||||||
|
lnaddr = lndecode(out['lightning'])
|
||||||
|
amount_sat = out.get('amount')
|
||||||
|
if amount:
|
||||||
|
assert int(lnaddr.get_amount_sat()) == amount_sat
|
||||||
|
address = out.get('address')
|
||||||
|
if address:
|
||||||
|
assert lnaddr.get_fallback_address() == address
|
||||||
|
except Exception as e:
|
||||||
|
raise InvalidBitcoinURI(f"Inconsistent lightning field: {repr(e)}") from e
|
||||||
|
|
||||||
r = out.get('r')
|
r = out.get('r')
|
||||||
sig = out.get('sig')
|
sig = out.get('sig')
|
||||||
|
|||||||
@@ -2348,7 +2348,8 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
|
|||||||
amount_sat = amount_sat or 0
|
amount_sat = amount_sat or 0
|
||||||
exp_delay = exp_delay or 0
|
exp_delay = exp_delay or 0
|
||||||
timestamp = int(time.time())
|
timestamp = int(time.time())
|
||||||
lightning_invoice = self.lnworker.add_request(amount_sat, message, exp_delay) if lightning else None
|
fallback_address = address if self.config.get('bolt11_fallback', True) else None
|
||||||
|
lightning_invoice = self.lnworker.add_request(amount_sat, message, exp_delay, fallback_address) if lightning else None
|
||||||
outputs = [ PartialTxOutput.from_address_and_value(address, amount_sat)] if address else []
|
outputs = [ PartialTxOutput.from_address_and_value(address, amount_sat)] if address else []
|
||||||
height = self.get_local_height()
|
height = self.get_local_height()
|
||||||
req = Invoice(
|
req = Invoice(
|
||||||
|
|||||||
Reference in New Issue
Block a user