Browse Source

qml: properly suggest paying bolt11 invoice onchain if insufficient LN balance.

Also, if fallback address is present, don't warn on bolt11 and no ln channels.
master
Sander van Grieken 2 years ago
parent
commit
0a804607a4
  1. 59
      electrum/gui/qml/components/WalletMainView.qml
  2. 18
      electrum/gui/qml/qeinvoice.py

59
electrum/gui/qml/components/WalletMainView.qml

@ -63,6 +63,29 @@ Item {
dialog.open() dialog.open()
} }
function payOnchain() {
var dialog = confirmPaymentDialog.createObject(mainView, {
address: invoice.address,
satoshis: invoice.amountOverride.isEmpty
? invoice.amount
: invoice.amountOverride,
message: invoice.message
})
var canComplete = !Daemon.currentWallet.isWatchOnly && Daemon.currentWallet.canSignWithoutCosigner
dialog.accepted.connect(function() {
if (!canComplete) {
if (Daemon.currentWallet.isWatchOnly) {
dialog.finalizer.saveOrShow()
} else {
dialog.finalizer.sign()
}
} else {
dialog.finalizer.signAndSend()
}
})
dialog.open()
}
property QtObject menu: Menu { property QtObject menu: Menu {
id: menu id: menu
@ -327,29 +350,23 @@ Item {
height: parent.height height: parent.height
onDoPay: { onDoPay: {
if (invoice.invoiceType == Invoice.OnchainInvoice var lninvoiceButPayOnchain = false
|| (invoice.invoiceType == Invoice.LightningInvoice if (invoice.invoiceType == Invoice.LightningInvoice && invoice.address) {
&& invoice.amountOverride.isEmpty // ln invoice with fallback
? invoice.amount.satsInt > Daemon.currentWallet.lightningCanSend var amountToSend = invoice.amountOverride.isEmpty
: invoice.amountOverride.satsInt > Daemon.currentWallet.lightningCanSend ? invoice.amount.satsInt
)) : invoice.amountOverride.satsInt
{ if (amountToSend > Daemon.currentWallet.lightningCanSend.satsInt) {
var dialog = confirmPaymentDialog.createObject(mainView, { lninvoiceButPayOnchain = true
address: invoice.address, }
satoshis: invoice.amountOverride.isEmpty ? invoice.amount : invoice.amountOverride, }
message: invoice.message if (invoice.invoiceType == Invoice.OnchainInvoice || lninvoiceButPayOnchain) {
var dialog = app.messageDialog.createObject(mainView, {
title: qsTr('Insufficient balance to pay over Lightning. Pay on-chain instead?'),
yesno: true
}) })
var canComplete = !Daemon.currentWallet.isWatchOnly && Daemon.currentWallet.canSignWithoutCosigner
dialog.accepted.connect(function() { dialog.accepted.connect(function() {
if (!canComplete) { payOnchain()
if (Daemon.currentWallet.isWatchOnly) {
dialog.finalizer.saveOrShow()
} else {
dialog.finalizer.sign()
}
} else {
dialog.finalizer.signAndSend()
}
}) })
dialog.open() dialog.open()
} else if (invoice.invoiceType == Invoice.LightningInvoice) { } else if (invoice.invoiceType == Invoice.LightningInvoice) {

18
electrum/gui/qml/qeinvoice.py

@ -1,6 +1,4 @@
import threading from typing import Optional, Dict, Any
from typing import TYPE_CHECKING, Optional, Dict, Any
import asyncio
from urllib.parse import urlparse from urllib.parse import urlparse
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, Q_ENUMS, QTimer from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, Q_ENUMS, QTimer
@ -9,16 +7,11 @@ from electrum.i18n import _
from electrum.logging import get_logger from electrum.logging import get_logger
from electrum.invoices import (Invoice, PR_UNPAID, PR_EXPIRED, PR_UNKNOWN, PR_PAID, PR_INFLIGHT, from electrum.invoices import (Invoice, PR_UNPAID, PR_EXPIRED, PR_UNKNOWN, PR_PAID, PR_INFLIGHT,
PR_FAILED, PR_ROUTING, PR_UNCONFIRMED, PR_BROADCASTING, PR_BROADCAST, LN_EXPIRY_NEVER) PR_FAILED, PR_ROUTING, PR_UNCONFIRMED, PR_BROADCASTING, PR_BROADCAST, LN_EXPIRY_NEVER)
from electrum.lnaddr import LnInvoiceException
from electrum.transaction import PartialTxOutput, TxOutput from electrum.transaction import PartialTxOutput, TxOutput
from electrum.util import InvoiceError, get_asyncio_loop from electrum.lnutil import format_short_channel_id
from electrum.lnutil import format_short_channel_id, IncompatibleOrInsaneFeatures
from electrum.lnurl import decode_lnurl, request_lnurl, callback_lnurl
from electrum.bitcoin import COIN from electrum.bitcoin import COIN
from electrum.paymentrequest import PaymentRequest from electrum.paymentrequest import PaymentRequest
from electrum.payment_identifier import (maybe_extract_lightning_payment_identifier, from electrum.payment_identifier import (PaymentIdentifier, PaymentIdentifierState, PaymentIdentifierType)
PaymentIdentifier, PaymentIdentifierState, PaymentIdentifierType)
from electrum.bip21 import parse_bip21_URI, InvalidBitcoinURI
from .qetypes import QEAmount from .qetypes import QEAmount
from .qewallet import QEWallet from .qewallet import QEWallet
from .util import status_update_timer_interval, QtEventListener, event_listener from .util import status_update_timer_interval, QtEventListener, event_listener
@ -392,6 +385,7 @@ class QEInvoice(QObject, QtEventListener):
def get_max_spendable_lightning(self): def get_max_spendable_lightning(self):
return self._wallet.wallet.lnworker.num_sats_can_send() if self._wallet.wallet.lnworker else 0 return self._wallet.wallet.lnworker.num_sats_can_send() if self._wallet.wallet.lnworker else 0
class QEInvoiceParser(QEInvoice): class QEInvoiceParser(QEInvoice):
_logger = get_logger(__name__) _logger = get_logger(__name__)
@ -530,10 +524,9 @@ class QEInvoiceParser(QEInvoice):
self.validationError.emit('no_lightning', self.validationError.emit('no_lightning',
_('Detected valid Lightning invoice, but Lightning not enabled for wallet and no fallback address found.')) _('Detected valid Lightning invoice, but Lightning not enabled for wallet and no fallback address found.'))
return return
if self._wallet.wallet.lnworker and not self._wallet.wallet.lnworker.channels: if self._wallet.wallet.lnworker and not self._wallet.wallet.lnworker.channels and not lninvoice.get_address():
self.validationWarning.emit('no_channels', self.validationWarning.emit('no_channels',
_('Detected valid Lightning invoice, but there are no open channels')) _('Detected valid Lightning invoice, but there are no open channels'))
self.setValidLightningInvoice(lninvoice) self.setValidLightningInvoice(lninvoice)
self.validationSuccess.emit() self.validationSuccess.emit()
elif self._pi.type == PaymentIdentifierType.BIP21: elif self._pi.type == PaymentIdentifierType.BIP21:
@ -544,7 +537,6 @@ class QEInvoiceParser(QEInvoice):
else: else:
self._validateRecipient_bip21_onchain(self._pi.bip21) self._validateRecipient_bip21_onchain(self._pi.bip21)
def _validateRecipient_bip21_onchain(self, bip21: Dict[str, Any]) -> None: def _validateRecipient_bip21_onchain(self, bip21: Dict[str, Any]) -> None:
if 'amount' not in bip21: if 'amount' not in bip21:
amount = 0 amount = 0

Loading…
Cancel
Save