def _do_pay_lightning(self, invoice: Invoice, pw) -> None: amount_msat = invoice.get_amount_msat() def pay_thread(): try: coro = self.app.wallet.lnworker.pay_invoice( invoice.lightning_invoice, amount_msat=amount_msat) fut = asyncio.run_coroutine_threadsafe( coro, self.app.network.asyncio_loop) fut.result() except Exception as e: self.app.show_error(repr(e)) self.save_invoice(invoice) threading.Thread(target=pay_thread).start()
def pay_lightning_invoice(self, invoice: Invoice): amount_sat = invoice.get_amount_sat() key = self.wallet.get_key_for_outgoing_invoice(invoice) 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 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 choices = {} if can_rebalance: msg = ''.join([ _('Rebalance existing channels'), '\n', _('Move funds between your channels in order to increase your sending capacity.' ) ]) choices[0] = msg if can_pay_with_new_channel: msg = ''.join([ _('Open a new channel'), '\n', _('You will be able to pay once the channel is open.') ]) choices[1] = msg if can_pay_with_swap: msg = ''.join([ _('Swap onchain funds for lightning funds'), '\n', _('You will be able to pay once the swap is confirmed.') ]) choices[2] = msg if can_pay_onchain: msg = ''.join([ _('Pay onchain'), '\n', _('Funds will be sent to the invoice fallback address.') ]) choices[3] = msg if not choices: raise NotEnoughFunds() msg = _('You cannot pay that invoice using Lightning.') if self.wallet.lnworker.channels: msg += '\n' + _('Your channels can send {}.').format( self.format_amount(num_sats_can_send) + self.base_unit()) r = self.window.query_choice(msg, choices) if r is not None: self.save_pending_invoice() if r == 0: chan1, chan2, delta = rebalance_suggestion self.window.rebalance_dialog(chan1, chan2, amount_sat=delta) elif r == 1: amount_sat, min_amount_sat = can_pay_with_new_channel self.window.channels_list.new_channel_dialog( amount_sat=amount_sat, min_amount_sat=min_amount_sat) elif r == 2: chan, swap_recv_amount_sat = can_pay_with_swap self.window.run_swap_dialog( is_reverse=False, recv_amount_sat=swap_recv_amount_sat, channels=[chan]) elif r == 3: self.pay_onchain_dialog(coins, invoice.get_outputs()) return # 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) self.window.run_coroutine_from_thread(coro, _('Sending payment'))