qml: when opening channel, validate and show user feedback if amount outside acceptable range
This commit is contained in:
@@ -201,7 +201,6 @@ ElDialog {
|
|||||||
if (activeFocus) {
|
if (activeFocus) {
|
||||||
channelopener.amount.isMax = checked
|
channelopener.amount.isMax = checked
|
||||||
if (checked) {
|
if (checked) {
|
||||||
maxAmountMessage.text = ''
|
|
||||||
channelopener.updateMaxAmount()
|
channelopener.updateMaxAmount()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -232,11 +231,12 @@ ElDialog {
|
|||||||
Item { visible: Daemon.fx.enabled ; height: 1; width: 1 }
|
Item { visible: Daemon.fx.enabled ; height: 1; width: 1 }
|
||||||
|
|
||||||
InfoTextArea {
|
InfoTextArea {
|
||||||
|
id: warning
|
||||||
Layout.topMargin: constants.paddingMedium
|
Layout.topMargin: constants.paddingMedium
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.columnSpan: 3
|
Layout.columnSpan: 3
|
||||||
id: maxAmountMessage
|
text: channelopener.warning
|
||||||
visible: is_max.checked && text
|
visible: text
|
||||||
compact: true
|
compact: true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,9 +321,6 @@ ElDialog {
|
|||||||
// TODO: handle incomplete TX
|
// TODO: handle incomplete TX
|
||||||
root.close()
|
root.close()
|
||||||
}
|
}
|
||||||
onMaxAmountMessage: (message) => {
|
|
||||||
maxAmountMessage.text = message
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FontMetrics {
|
FontMetrics {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
|
|||||||
from electrum.i18n import _
|
from electrum.i18n import _
|
||||||
from electrum.gui import messages
|
from electrum.gui import messages
|
||||||
from electrum.util import bfh
|
from electrum.util import bfh
|
||||||
|
from electrum.lnutil import MIN_FUNDING_SAT
|
||||||
from electrum.lntransport import extract_nodeid, ConnStringFormatError
|
from electrum.lntransport import extract_nodeid, ConnStringFormatError
|
||||||
from electrum.bitcoin import DummyAddress
|
from electrum.bitcoin import DummyAddress
|
||||||
from electrum.lnworker import hardcoded_trampoline_nodes
|
from electrum.lnworker import hardcoded_trampoline_nodes
|
||||||
@@ -31,7 +32,6 @@ class QEChannelOpener(QObject, AuthMixin):
|
|||||||
channelOpenError = pyqtSignal([str], arguments=['message'])
|
channelOpenError = pyqtSignal([str], arguments=['message'])
|
||||||
channelOpenSuccess = pyqtSignal([str, bool, int, bool],
|
channelOpenSuccess = pyqtSignal([str, bool, int, bool],
|
||||||
arguments=['cid', 'has_onchain_backup', 'min_depth', 'tx_complete'])
|
arguments=['cid', 'has_onchain_backup', 'min_depth', 'tx_complete'])
|
||||||
maxAmountMessage = pyqtSignal([str], arguments=['message'])
|
|
||||||
|
|
||||||
dataChanged = pyqtSignal() # generic notify signal
|
dataChanged = pyqtSignal() # generic notify signal
|
||||||
|
|
||||||
@@ -44,6 +44,8 @@ class QEChannelOpener(QObject, AuthMixin):
|
|||||||
self._valid = False
|
self._valid = False
|
||||||
self._opentx = None
|
self._opentx = None
|
||||||
self._txdetails = None
|
self._txdetails = None
|
||||||
|
self._warning = ''
|
||||||
|
self._determine_max_message = None
|
||||||
|
|
||||||
self._finalizer = None
|
self._finalizer = None
|
||||||
self._node_pubkey = None
|
self._node_pubkey = None
|
||||||
@@ -92,6 +94,21 @@ class QEChannelOpener(QObject, AuthMixin):
|
|||||||
def valid(self):
|
def valid(self):
|
||||||
return self._valid
|
return self._valid
|
||||||
|
|
||||||
|
def setValid(self, is_valid):
|
||||||
|
if self._valid != is_valid:
|
||||||
|
self._valid = is_valid
|
||||||
|
self.validChanged.emit()
|
||||||
|
|
||||||
|
warningChanged = pyqtSignal()
|
||||||
|
@pyqtProperty(str, notify=warningChanged)
|
||||||
|
def warning(self):
|
||||||
|
return self._warning
|
||||||
|
|
||||||
|
def setWarning(self, warning):
|
||||||
|
if self._warning != warning:
|
||||||
|
self._warning = warning
|
||||||
|
self.warningChanged.emit()
|
||||||
|
|
||||||
finalizerChanged = pyqtSignal()
|
finalizerChanged = pyqtSignal()
|
||||||
@pyqtProperty(QETxFinalizer, notify=finalizerChanged)
|
@pyqtProperty(QETxFinalizer, notify=finalizerChanged)
|
||||||
def finalizer(self):
|
def finalizer(self):
|
||||||
@@ -106,10 +123,9 @@ class QEChannelOpener(QObject, AuthMixin):
|
|||||||
def trampolineNodeNames(self):
|
def trampolineNodeNames(self):
|
||||||
return list(hardcoded_trampoline_nodes().keys())
|
return list(hardcoded_trampoline_nodes().keys())
|
||||||
|
|
||||||
# FIXME min channel funding amount
|
|
||||||
# FIXME have requested funding amount
|
# FIXME have requested funding amount
|
||||||
def validate(self):
|
def validate(self):
|
||||||
"""side-effects: sets self._valid, self._node_pubkey, self._connect_str_resolved"""
|
"""side-effects: sets self._node_pubkey, self._connect_str_resolved"""
|
||||||
connect_str_valid = False
|
connect_str_valid = False
|
||||||
if self._connect_str:
|
if self._connect_str:
|
||||||
self._logger.debug(f'checking if {self._connect_str=!r} is valid')
|
self._logger.debug(f'checking if {self._connect_str=!r} is valid')
|
||||||
@@ -129,19 +145,36 @@ class QEChannelOpener(QObject, AuthMixin):
|
|||||||
self._connect_str_resolved = self._connect_str
|
self._connect_str_resolved = self._connect_str
|
||||||
connect_str_valid = True
|
connect_str_valid = True
|
||||||
|
|
||||||
|
self.setWarning('')
|
||||||
|
|
||||||
if not connect_str_valid:
|
if not connect_str_valid:
|
||||||
self._valid = False
|
self.setValid(False)
|
||||||
self.validChanged.emit()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
self._logger.debug(f'amount={self._amount}')
|
self._logger.debug(f'amount={self._amount}')
|
||||||
if not self._amount or not (self._amount.satsInt > 0 or self._amount.isMax):
|
if not self._amount or not (self._amount.satsInt > 0 or self._amount.isMax):
|
||||||
self._valid = False
|
self.setValid(False)
|
||||||
self.validChanged.emit()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
self._valid = True
|
# for MAX, estimate is assumed to be calculated and set in self._amount.satsInt
|
||||||
self.validChanged.emit()
|
if self._amount.satsInt < MIN_FUNDING_SAT:
|
||||||
|
message = _('Minimum required amount: {}').format(
|
||||||
|
self._wallet.wallet.config.format_amount_and_units(MIN_FUNDING_SAT)
|
||||||
|
)
|
||||||
|
if self._amount.isMax and self._determine_max_message:
|
||||||
|
message += '\n' + self._determine_max_message
|
||||||
|
self.setWarning(message)
|
||||||
|
self.setValid(False)
|
||||||
|
return
|
||||||
|
|
||||||
|
if self._amount.satsInt > self._wallet.wallet.config.LIGHTNING_MAX_FUNDING_SAT:
|
||||||
|
self.setWarning(_('Amount is above maximum channel size: {}').format(
|
||||||
|
self._wallet.wallet.config.format_amount_and_units(self._wallet.wallet.config.LIGHTNING_MAX_FUNDING_SAT)
|
||||||
|
))
|
||||||
|
self.setValid(False)
|
||||||
|
return
|
||||||
|
|
||||||
|
self.setValid(True)
|
||||||
|
|
||||||
@pyqtSlot(str, result=bool)
|
@pyqtSlot(str, result=bool)
|
||||||
def validateConnectString(self, connect_str):
|
def validateConnectString(self, connect_str):
|
||||||
@@ -252,13 +285,8 @@ class QEChannelOpener(QObject, AuthMixin):
|
|||||||
node_id=dummy_nodeid,
|
node_id=dummy_nodeid,
|
||||||
fee_policy=fee_policy)
|
fee_policy=fee_policy)
|
||||||
|
|
||||||
amount, message = self._wallet.determine_max(mktx=make_tx)
|
amount, self._determine_max_message = self._wallet.determine_max(mktx=make_tx)
|
||||||
if amount is None:
|
self._amount.satsInt = amount if amount else 0
|
||||||
self._amount.isMax = False
|
|
||||||
else:
|
|
||||||
self._amount.satsInt = amount
|
|
||||||
if message:
|
|
||||||
self.maxAmountMessage.emit(message)
|
|
||||||
finally:
|
finally:
|
||||||
self._updating_max = False
|
self._updating_max = False
|
||||||
self.validate()
|
self.validate()
|
||||||
|
|||||||
Reference in New Issue
Block a user