improve channel_funding_sat suggestion. add min_amount parameter to new_channel_dialog
This commit is contained in:
@@ -392,9 +392,9 @@ class ChannelsList(MyTreeView):
|
||||
vbox.addLayout(Buttons(OkButton(d)))
|
||||
d.exec_()
|
||||
|
||||
def new_channel_dialog(self, *, amount_sat=None):
|
||||
def new_channel_dialog(self, *, amount_sat=None, min_amount_sat=None):
|
||||
from .new_channel_dialog import NewChannelDialog
|
||||
d = NewChannelDialog(self.parent, amount_sat)
|
||||
d = NewChannelDialog(self.parent, amount_sat, min_amount_sat)
|
||||
return d.run()
|
||||
|
||||
|
||||
|
||||
@@ -1742,7 +1742,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
|
||||
lightning_needed += (lightning_needed // 20) # operational safety margin
|
||||
coins = self.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, channel_funding_sat = self.wallet.can_pay_with_new_channel(amount_sat, 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)
|
||||
can_rebalance = self.wallet.lnworker.suggest_rebalance_to_send(amount_sat)
|
||||
choices = {}
|
||||
@@ -1784,7 +1784,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
|
||||
elif r == 1:
|
||||
self.pay_onchain_dialog(coins, invoice.get_outputs())
|
||||
elif r == 2:
|
||||
self.channels_list.new_channel_dialog(amount_sat=channel_funding_sat)
|
||||
amount_sat, min_amount_sat = can_pay_with_new_channel
|
||||
self.channels_list.new_channel_dialog(amount_sat=amount_sat, min_amount_sat=min_amount_sat)
|
||||
elif r == 3:
|
||||
chan, swap_recv_amount_sat = can_pay_with_swap
|
||||
self.run_swap_dialog(is_reverse=False, recv_amount_sat=swap_recv_amount_sat, channels=[chan])
|
||||
|
||||
@@ -22,7 +22,7 @@ if TYPE_CHECKING:
|
||||
|
||||
class NewChannelDialog(WindowModalDialog):
|
||||
|
||||
def __init__(self, window: 'ElectrumWindow', amount_sat: Optional[int] = None):
|
||||
def __init__(self, window: 'ElectrumWindow', amount_sat: Optional[int] = None, min_amount_sat: Optional[int] = None):
|
||||
WindowModalDialog.__init__(self, window, _('Open Channel'))
|
||||
self.window = window
|
||||
self.network = window.network
|
||||
@@ -30,7 +30,13 @@ class NewChannelDialog(WindowModalDialog):
|
||||
self.lnworker = self.window.wallet.lnworker
|
||||
self.trampolines = hardcoded_trampoline_nodes()
|
||||
self.trampoline_names = list(self.trampolines.keys())
|
||||
self.min_amount_sat = min_amount_sat or 10_000
|
||||
vbox = QVBoxLayout(self)
|
||||
msg = _('Choose a remote node and an amount to fund the channel.')
|
||||
if min_amount_sat:
|
||||
# only displayed if min_amount_sat is passed as parameter
|
||||
msg += '\n' + _('You need to put at least') + ': ' + self.window.format_amount_and_units(self.min_amount_sat)
|
||||
vbox.addWidget(WWLabel(msg))
|
||||
if self.network.channel_db:
|
||||
vbox.addWidget(QLabel(_('Enter Remote Node ID or connection string or invoice')))
|
||||
self.remote_nodeid = QLineEdit()
|
||||
@@ -38,12 +44,13 @@ class NewChannelDialog(WindowModalDialog):
|
||||
self.suggest_button = QPushButton(self, text=_('Suggest Peer'))
|
||||
self.suggest_button.clicked.connect(self.on_suggest)
|
||||
else:
|
||||
vbox.addWidget(QLabel(_('Choose a trampoline node to open a channel with')))
|
||||
self.trampoline_combo = QComboBox()
|
||||
self.trampoline_combo.addItems(self.trampoline_names)
|
||||
self.trampoline_combo.setCurrentIndex(1)
|
||||
self.amount_e = BTCAmountEdit(self.window.get_decimal_point)
|
||||
self.amount_e.setAmount(amount_sat)
|
||||
self.min_button = EnterButton(_("Min"), self.spend_min)
|
||||
self.min_button.setEnabled(bool(self.min_amount_sat))
|
||||
self.max_button = EnterButton(_("Max"), self.spend_max)
|
||||
self.max_button.setFixedWidth(100)
|
||||
self.max_button.setCheckable(True)
|
||||
@@ -56,12 +63,13 @@ class NewChannelDialog(WindowModalDialog):
|
||||
h.addWidget(self.remote_nodeid, 0, 1, 1, 4)
|
||||
h.addWidget(self.suggest_button, 0, 5)
|
||||
else:
|
||||
h.addWidget(QLabel(_('Trampoline')), 0, 0)
|
||||
h.addWidget(QLabel(_('Remote Node')), 0, 0)
|
||||
h.addWidget(self.trampoline_combo, 0, 1, 1, 4)
|
||||
h.addWidget(QLabel('Amount'), 2, 0)
|
||||
h.addWidget(self.amount_e, 2, 1)
|
||||
h.addWidget(self.max_button, 2, 2)
|
||||
h.addWidget(self.clear_button, 2, 3)
|
||||
h.addWidget(self.min_button, 2, 2)
|
||||
h.addWidget(self.max_button, 2, 3)
|
||||
h.addWidget(self.clear_button, 2, 4)
|
||||
vbox.addLayout(h)
|
||||
vbox.addStretch()
|
||||
ok_button = OkButton(self)
|
||||
@@ -89,6 +97,10 @@ class NewChannelDialog(WindowModalDialog):
|
||||
self.max_button.setChecked(False)
|
||||
self.max_button.repaint() # macOS hack for #6269
|
||||
|
||||
def spend_min(self):
|
||||
self.max_button.setChecked(False)
|
||||
self.amount_e.setAmount(self.min_amount_sat)
|
||||
|
||||
def spend_max(self):
|
||||
self.amount_e.setFrozen(self.max_button.isChecked())
|
||||
if not self.max_button.isChecked():
|
||||
@@ -116,12 +128,17 @@ class NewChannelDialog(WindowModalDialog):
|
||||
funding_sat = '!'
|
||||
else:
|
||||
funding_sat = self.amount_e.get_amount()
|
||||
if not funding_sat:
|
||||
return
|
||||
if self.min_amount_sat and funding_sat < self.min_amount_sat:
|
||||
self.window.show_error(_('Amount too low'))
|
||||
return
|
||||
if self.network.channel_db:
|
||||
connect_str = str(self.remote_nodeid.text()).strip()
|
||||
else:
|
||||
name = self.trampoline_names[self.trampoline_combo.currentIndex()]
|
||||
connect_str = str(self.trampolines[name])
|
||||
if not connect_str or not funding_sat:
|
||||
if not connect_str:
|
||||
return
|
||||
self.window.open_channel(connect_str, funding_sat, 0)
|
||||
return True
|
||||
|
||||
@@ -1067,6 +1067,29 @@ class LNWallet(LNWorker):
|
||||
tx.set_rbf(False)
|
||||
return tx
|
||||
|
||||
def suggest_funding_amount(self, amount_to_pay, coins):
|
||||
""" wether we can pay amount_sat after opening a new channel"""
|
||||
num_sats_can_send = int(self.num_sats_can_send())
|
||||
lightning_needed = amount_to_pay - num_sats_can_send
|
||||
assert lightning_needed > 0
|
||||
min_funding_sat = lightning_needed + (lightning_needed // 20) + 1000 # safety margin
|
||||
min_funding_sat = max(min_funding_sat, 100_000) # at least 1mBTC
|
||||
if min_funding_sat > LN_MAX_FUNDING_SAT:
|
||||
return
|
||||
try:
|
||||
self.mktx_for_open_channel(coins=coins, funding_sat=min_funding_sat, node_id=bytes(32), fee_est=None)
|
||||
funding_sat = min_funding_sat
|
||||
except NotEnoughFunds:
|
||||
return
|
||||
# if available, suggest twice that amount:
|
||||
if 2 * min_funding_sat <= LN_MAX_FUNDING_SAT:
|
||||
try:
|
||||
self.mktx_for_open_channel(coins=coins, funding_sat=2*min_funding_sat, node_id=bytes(32), fee_est=None)
|
||||
funding_sat = 2 * min_funding_sat
|
||||
except NotEnoughFunds:
|
||||
pass
|
||||
return funding_sat, min_funding_sat
|
||||
|
||||
def open_channel(self, *, connect_str: str, funding_tx: PartialTransaction,
|
||||
funding_sat: int, push_amt_sat: int, password: str = None) -> Tuple[Channel, PartialTransaction]:
|
||||
if funding_sat > LN_MAX_FUNDING_SAT:
|
||||
|
||||
@@ -1342,22 +1342,6 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
|
||||
return False
|
||||
return True
|
||||
|
||||
def can_pay_with_new_channel(self, amount_sat, coins=None):
|
||||
""" wether we can pay amount_sat after opening a new channel"""
|
||||
if self.lnworker is None:
|
||||
return False, None
|
||||
num_sats_can_send = int(self.lnworker.num_sats_can_send())
|
||||
if amount_sat <= num_sats_can_send:
|
||||
return True, None
|
||||
lightning_needed = amount_sat - num_sats_can_send
|
||||
lightning_needed += (lightning_needed // 20) # operational safety margin
|
||||
channel_funding_sat = lightning_needed + 1000 # channel reserves safety margin
|
||||
try:
|
||||
self.lnworker.mktx_for_open_channel(coins=coins, funding_sat=channel_funding_sat, node_id=bytes(32), fee_est=None)
|
||||
except NotEnoughFunds:
|
||||
return False, None
|
||||
return True, channel_funding_sat
|
||||
|
||||
def make_unsigned_transaction(
|
||||
self, *,
|
||||
coins: Sequence[PartialTxInput],
|
||||
|
||||
Reference in New Issue
Block a user