add zeroconf handling to qt gui
This commit is contained in:
@@ -98,6 +98,8 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
||||
self.receive_help_text.setLayout(QHBoxLayout())
|
||||
self.receive_rebalance_button = QPushButton('Rebalance')
|
||||
self.receive_rebalance_button.suggestion = None
|
||||
self.receive_zeroconf_button = QPushButton(_('Accept'))
|
||||
self.receive_zeroconf_button.clicked.connect(self.on_accept_zeroconf)
|
||||
|
||||
def on_receive_rebalance():
|
||||
if self.receive_rebalance_button.suggestion:
|
||||
@@ -115,6 +117,7 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
||||
buttons = QHBoxLayout()
|
||||
buttons.addWidget(self.receive_rebalance_button)
|
||||
buttons.addWidget(self.receive_swap_button)
|
||||
buttons.addWidget(self.receive_zeroconf_button)
|
||||
vbox = QVBoxLayout()
|
||||
vbox.addWidget(self.receive_help_text)
|
||||
vbox.addLayout(buttons)
|
||||
@@ -236,26 +239,37 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
||||
self.ln_help = help_texts.ln_help
|
||||
can_rebalance = help_texts.can_rebalance()
|
||||
can_swap = help_texts.can_swap()
|
||||
can_zeroconf = help_texts.can_zeroconf()
|
||||
self.receive_rebalance_button.suggestion = help_texts.ln_rebalance_suggestion
|
||||
self.receive_swap_button.suggestion = help_texts.ln_swap_suggestion
|
||||
self.receive_rebalance_button.setVisible(can_rebalance)
|
||||
self.receive_swap_button.setVisible(can_swap)
|
||||
self.receive_rebalance_button.setEnabled(can_rebalance and self.window.num_tasks() == 0)
|
||||
self.receive_swap_button.setEnabled(can_swap and self.window.num_tasks() == 0)
|
||||
self.receive_zeroconf_button.setVisible(can_zeroconf)
|
||||
self.receive_zeroconf_button.setEnabled(can_zeroconf)
|
||||
text, data, help_text, title = self.get_tab_data()
|
||||
self.receive_e.setText(text)
|
||||
self.receive_qr.setData(data)
|
||||
self.receive_help_text.setText(help_text)
|
||||
for w in [self.receive_e, self.receive_qr]:
|
||||
w.setEnabled(bool(text) and not help_text)
|
||||
w.setEnabled(bool(text) and (not help_text or can_zeroconf))
|
||||
w.setToolTip(help_text)
|
||||
# macOS hack (similar to #4777)
|
||||
self.receive_e.repaint()
|
||||
# always show
|
||||
if can_zeroconf:
|
||||
# show the help message if zeroconf so user can first accept it and still sees the invoice
|
||||
# after accepting
|
||||
self.receive_widget.show_help()
|
||||
self.receive_widget.setVisible(True)
|
||||
self.toggle_qr_button.setEnabled(True)
|
||||
self.update_receive_qr_window()
|
||||
|
||||
def on_accept_zeroconf(self):
|
||||
self.receive_zeroconf_button.setVisible(False)
|
||||
self.update_receive_widgets()
|
||||
|
||||
def get_tab_data(self):
|
||||
if self.URI:
|
||||
out = self.URI, self.URI, self.URI_help, _('Bitcoin URI')
|
||||
@@ -374,9 +388,12 @@ class ReceiveWidget(QWidget):
|
||||
self.textedit.setVisible(not is_qr)
|
||||
self.qr.setVisible(is_qr)
|
||||
else:
|
||||
self.help_widget.setVisible(True)
|
||||
self.textedit.setVisible(False)
|
||||
self.qr.setVisible(False)
|
||||
self.show_help()
|
||||
|
||||
def show_help(self):
|
||||
self.help_widget.setVisible(True)
|
||||
self.textedit.setVisible(False)
|
||||
self.qr.setVisible(False)
|
||||
|
||||
def resizeEvent(self, e):
|
||||
# keep square aspect ratio when resized
|
||||
|
||||
@@ -53,6 +53,7 @@ from .i18n import _
|
||||
from .bip32 import BIP32Node, convert_bip32_intpath_to_strpath, convert_bip32_strpath_to_intpath
|
||||
from .crypto import sha256
|
||||
from . import util
|
||||
from .lntransport import extract_nodeid
|
||||
from .util import (NotEnoughFunds, UserCancelled, profiler, OldTaskGroup, ignore_exceptions,
|
||||
format_satoshis, format_fee_satoshis, NoDynamicFeeEstimates,
|
||||
WalletFileException, BitcoinException,
|
||||
@@ -60,6 +61,7 @@ from .util import (NotEnoughFunds, UserCancelled, profiler, OldTaskGroup, ignore
|
||||
Fiat, bfh, TxMinedInfo, quantize_feerate, OrderedDictWithIndex)
|
||||
from .simple_config import SimpleConfig
|
||||
from .fee_policy import FeePolicy, FixedFeePolicy, FeeMethod, FEE_RATIO_HIGH_WARNING, FEERATE_WARNING_HIGH_FEE
|
||||
from .lnutil import MIN_FUNDING_SAT
|
||||
from .bitcoin import COIN, TYPE_ADDRESS
|
||||
from .bitcoin import is_address, address_to_script, is_minikey, relayfee, dust_threshold
|
||||
from .bitcoin import DummyAddress, DummyAddressUsedInTxException
|
||||
@@ -346,6 +348,7 @@ class ReceiveRequestHelp(NamedTuple):
|
||||
|
||||
ln_swap_suggestion: Optional[Any] = None
|
||||
ln_rebalance_suggestion: Optional[Any] = None
|
||||
ln_zeroconf_suggestion: bool = False
|
||||
|
||||
def can_swap(self) -> bool:
|
||||
return bool(self.ln_swap_suggestion)
|
||||
@@ -353,6 +356,9 @@ class ReceiveRequestHelp(NamedTuple):
|
||||
def can_rebalance(self) -> bool:
|
||||
return bool(self.ln_rebalance_suggestion)
|
||||
|
||||
def can_zeroconf(self) -> bool:
|
||||
return self.ln_zeroconf_suggestion
|
||||
|
||||
|
||||
class TxWalletDelta(NamedTuple):
|
||||
is_relevant: bool # "related to wallet?"
|
||||
@@ -3250,12 +3256,19 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
ln_is_error = False
|
||||
ln_swap_suggestion = None
|
||||
ln_rebalance_suggestion = None
|
||||
ln_zeroconf_suggestion = False
|
||||
URI = self.get_request_URI(req) or ''
|
||||
lightning_has_channels = (
|
||||
self.lnworker and len([chan for chan in self.lnworker.channels.values() if chan.is_open()]) > 0
|
||||
)
|
||||
lightning_online = self.lnworker and self.lnworker.num_peers() > 0
|
||||
can_receive_lightning = self.lnworker and amount_sat <= self.lnworker.num_sats_can_receive()
|
||||
try:
|
||||
zeroconf_nodeid = extract_nodeid(self.config.ZEROCONF_TRUSTED_NODE)[0]
|
||||
except Exception:
|
||||
zeroconf_nodeid = None
|
||||
can_get_zeroconf_channel = (self.lnworker and self.config.ACCEPT_ZEROCONF_CHANNELS
|
||||
and zeroconf_nodeid in self.lnworker.peers)
|
||||
status = self.get_invoice_status(req)
|
||||
|
||||
if status == PR_EXPIRED:
|
||||
@@ -3281,21 +3294,33 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
address_help = URI_help = (_("This address has already been used. "
|
||||
"For better privacy, do not reuse it for new payments."))
|
||||
if req.is_lightning():
|
||||
if not lightning_has_channels:
|
||||
if not lightning_has_channels and not can_get_zeroconf_channel:
|
||||
ln_is_error = True
|
||||
ln_help = _("You must have an open Lightning channel to receive payments.")
|
||||
elif not lightning_online:
|
||||
ln_is_error = True
|
||||
ln_help = _('You must be online to receive Lightning payments.')
|
||||
elif not can_receive_lightning:
|
||||
ln_is_error = True
|
||||
elif not can_receive_lightning or (amount_sat <= 0 and not lightning_has_channels):
|
||||
ln_rebalance_suggestion = self.lnworker.suggest_rebalance_to_receive(amount_sat)
|
||||
ln_swap_suggestion = self.lnworker.suggest_swap_to_receive(amount_sat)
|
||||
ln_help = _('You do not have the capacity to receive this amount with Lightning.')
|
||||
if bool(ln_rebalance_suggestion):
|
||||
ln_help += '\n\n' + _('You may have that capacity if you rebalance your channels.')
|
||||
elif bool(ln_swap_suggestion):
|
||||
ln_help += '\n\n' + _('You may have that capacity if you swap some of your funds.')
|
||||
# prefer to use swaps over JIT channels if possible
|
||||
if can_get_zeroconf_channel and not bool(ln_rebalance_suggestion) and not bool(ln_swap_suggestion):
|
||||
if amount_sat < MIN_FUNDING_SAT:
|
||||
ln_is_error = True
|
||||
ln_help = (_('Cannot receive this payment. Request at least {} '
|
||||
'to purchase a Lightning channel from your service provider.')
|
||||
.format(self.config.format_amount_and_units(amount_sat=MIN_FUNDING_SAT)))
|
||||
else:
|
||||
ln_zeroconf_suggestion = True
|
||||
ln_help = _(f'Receiving this payment will purchase a payment channel from your '
|
||||
f'service provider. Service fees are deducted from the incoming payment.')
|
||||
else:
|
||||
ln_is_error = True
|
||||
ln_help = _('You do not have the capacity to receive this amount with Lightning.')
|
||||
if bool(ln_rebalance_suggestion):
|
||||
ln_help += '\n\n' + _('You may have that capacity if you rebalance your channels.')
|
||||
elif bool(ln_swap_suggestion):
|
||||
ln_help += '\n\n' + _('You may have that capacity if you swap some of your funds.')
|
||||
# for URI that has LN part but no onchain part, copy error:
|
||||
if not addr and ln_is_error:
|
||||
URI_is_error = ln_is_error
|
||||
@@ -3309,6 +3334,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
ln_is_error=ln_is_error,
|
||||
ln_rebalance_suggestion=ln_rebalance_suggestion,
|
||||
ln_swap_suggestion=ln_swap_suggestion,
|
||||
ln_zeroconf_suggestion=ln_zeroconf_suggestion
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user