Skip to content

Commit 6541a7e

Browse files
committed
qml: separate PI resolving from QEInvoiceParser
separates the resolving step from the QEInvoiceParser so the 'recipient' can be resolved first and then either an QEInvoiceParser can be used if it is a sending request that has been resolved (invoice, address, lnurlp, ...), or RequestDetails can be used if the resolved 'recipient' turns out to be a voucher/LNURLW string.
1 parent ae310ad commit 6541a7e

File tree

8 files changed

+287
-160
lines changed

8 files changed

+287
-160
lines changed

electrum/gui/qml/components/LnurlWithdrawRequestDialog.qml

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@ ElDialog {
1313
title: qsTr('LNURL Withdraw request')
1414
iconSource: '../../../icons/link.png'
1515

16-
property InvoiceParser invoiceParser
16+
property Wallet wallet: Daemon.currentWallet
17+
property RequestDetails requestDetails
1718

1819
padding: 0
1920

20-
property int walletCanReceive: invoiceParser.wallet.lightningCanReceive.satsInt
21-
property int providerMinWithdrawable: parseInt(invoiceParser.lnurlData['min_withdrawable_sat'])
22-
property int providerMaxWithdrawable: parseInt(invoiceParser.lnurlData['max_withdrawable_sat'])
21+
property int walletCanReceive: 0
22+
property int providerMinWithdrawable: parseInt(requestDetails.lnurlData['min_withdrawable_sat'])
23+
property int providerMaxWithdrawable: parseInt(requestDetails.lnurlData['max_withdrawable_sat'])
2324
property int effectiveMinWithdrawable: Math.max(providerMinWithdrawable, 1)
2425
property int effectiveMaxWithdrawable: Math.min(providerMaxWithdrawable, walletCanReceive)
2526
property bool insufficientLiquidity: effectiveMinWithdrawable > walletCanReceive
@@ -30,6 +31,12 @@ ElDialog {
3031
amountBtc.textAsSats.satsInt <= dialog.effectiveMaxWithdrawable
3132
property bool valid: amountValid
3233

34+
Component.onCompleted: {
35+
// Initialize walletCanReceive (instead of binding wallet.lightningCanReceive.satsInt)
36+
// to prevent binding loop if wallet.lightningCanReceive.satsInt changes
37+
walletCanReceive = wallet.lightningCanReceive.satsInt
38+
}
39+
3340
ColumnLayout {
3441
width: parent.width
3542

@@ -89,17 +96,17 @@ ElDialog {
8996
}
9097
Label {
9198
Layout.fillWidth: true
92-
text: invoiceParser.lnurlData['domain']
99+
text: requestDetails.lnurlData['domain']
93100
}
94101
Label {
95102
text: qsTr('Description')
96103
color: Material.accentColor
97-
visible: invoiceParser.lnurlData['default_description']
104+
visible: requestDetails.lnurlData['default_description']
98105
}
99106
Label {
100107
Layout.fillWidth: true
101-
text: invoiceParser.lnurlData['default_description']
102-
visible: invoiceParser.lnurlData['default_description']
108+
text: requestDetails.lnurlData['default_description']
109+
visible: requestDetails.lnurlData['default_description']
103110
wrapMode: Text.Wrap
104111
}
105112

@@ -117,9 +124,6 @@ ElDialog {
117124
enabled: !dialog.insufficientLiquidity && (dialog.providerMinWithdrawable != dialog.providerMaxWithdrawable)
118125
color: Material.foreground // override gray-out on disabled
119126
fiatfield: amountFiat
120-
onTextAsSatsChanged: {
121-
invoiceParser.amountOverride = textAsSats
122-
}
123127
}
124128
Label {
125129
text: Config.baseUnit
@@ -150,12 +154,12 @@ ElDialog {
150154
Layout.fillWidth: true
151155
text: qsTr('Withdraw...')
152156
icon.source: '../../icons/confirmed.png'
153-
enabled: valid
157+
enabled: valid && !requestDetails.busy
154158
onClicked: {
155-
invoiceParser.lnurlRequestWithdrawal()
156-
dialog.close()
159+
var satsAmount = amountBtc.textAsSats.satsInt;
160+
requestDetails.lnurlRequestWithdrawal(satsAmount);
161+
dialog.close();
157162
}
158163
}
159164
}
160-
161165
}

electrum/gui/qml/components/SendDialog.qml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ ElDialog {
1212
id: dialog
1313

1414
property InvoiceParser invoiceParser
15+
property PIResolver piResolver
1516

1617
signal txFound(data: string)
1718
signal channelBackupFound(data: string)
@@ -36,7 +37,7 @@ ElDialog {
3637
} else if (Daemon.currentWallet.isValidChannelBackup(data)) {
3738
channelBackupFound(data)
3839
} else {
39-
invoiceParser.recipient = data
40+
piResolver.recipient = data
4041
}
4142
}
4243

@@ -68,7 +69,7 @@ ElDialog {
6869
FlatButton {
6970
Layout.fillWidth: true
7071
Layout.preferredWidth: 1
71-
enabled: !invoiceParser.busy
72+
enabled: !invoiceParser.busy && !piResolver.busy
7273
icon.source: '../../icons/copy_bw.png'
7374
text: qsTr('Paste')
7475
onClicked: {

electrum/gui/qml/components/WalletMainView.qml

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Item {
3636
function openSendDialog() {
3737
// Qt based send dialog if not on android
3838
if (!AppController.isAndroid()) {
39-
_sendDialog = qtSendDialog.createObject(mainView, {invoiceParser: invoiceParser})
39+
_sendDialog = qtSendDialog.createObject(mainView, {invoiceParser: invoiceParser, piResolver: piResolver})
4040
_sendDialog.open()
4141
return
4242
}
@@ -62,7 +62,7 @@ Item {
6262
})
6363
dialog.open()
6464
} else {
65-
invoiceParser.recipient = data
65+
piResolver.recipient = data
6666
}
6767
//scanner.destroy() // TODO
6868
})
@@ -362,7 +362,7 @@ Item {
362362
Layout.preferredWidth: 1
363363
icon.source: '../../icons/tab_send.png'
364364
text: qsTr('Send')
365-
enabled: !invoiceParser.busy
365+
enabled: !invoiceParser.busy && !piResolver.busy && !requestDetails.busy
366366
onClicked: openSendDialog()
367367
onPressAndHold: {
368368
Config.userKnowsPressAndHold = true
@@ -373,6 +373,45 @@ Item {
373373
}
374374
}
375375

376+
PIResolver {
377+
id: piResolver
378+
wallet: Daemon.currentWallet
379+
380+
onResolveError: (code, message) => {
381+
var dialog = app.messageDialog.createObject(app, {
382+
title: qsTr('Error'),
383+
iconSource: Qt.resolvedUrl('../../icons/warning.png'),
384+
text: message
385+
})
386+
dialog.open()
387+
}
388+
389+
Component.onCompleted: {
390+
piResolver.invoiceResolved.connect(invoiceParser.fromResolvedPaymentIdentifier)
391+
piResolver.requestResolved.connect(requestDetails.fromResolvedPaymentIdentifier)
392+
}
393+
}
394+
395+
RequestDetails {
396+
id: requestDetails
397+
wallet: Daemon.currentWallet
398+
onNeedsLNURLUserInput: {
399+
closeSendDialog()
400+
var dialog = lnurlWithdrawDialog.createObject(app, {
401+
requestDetails: requestDetails
402+
})
403+
dialog.open()
404+
}
405+
onLnurlError: (code, message) => {
406+
var dialog = app.messageDialog.createObject(app, {
407+
title: qsTr('Error'),
408+
iconSource: Qt.resolvedUrl('../../icons/warning.png'),
409+
text: message
410+
})
411+
dialog.open()
412+
}
413+
}
414+
376415
Invoice {
377416
id: invoice
378417
wallet: Daemon.currentWallet
@@ -416,17 +455,12 @@ Item {
416455
onInvoiceCreateError: (code, message) => {
417456
console.log(code + ' ' + message)
418457
}
419-
420458
onLnurlRetrieved: {
421459
closeSendDialog()
422460
if (invoiceParser.invoiceType === Invoice.Type.LNURLPayRequest) {
423461
var dialog = lnurlPayDialog.createObject(app, {
424462
invoiceParser: invoiceParser
425463
})
426-
} else if (invoiceParser.invoiceType === Invoice.Type.LNURLWithdrawRequest) {
427-
var dialog = lnurlWithdrawDialog.createObject(app, {
428-
invoiceParser: invoiceParser
429-
})
430464
} else {
431465
console.log("Unsupported LNURL type:", invoiceParser.invoiceType)
432466
return
@@ -456,7 +490,7 @@ Item {
456490
_intentUri = uri
457491
return
458492
}
459-
invoiceParser.recipient = uri
493+
piResolver.recipient = uri
460494
}
461495
}
462496

@@ -465,7 +499,7 @@ Item {
465499
function onWalletLoaded() {
466500
infobanner.hide() // start hidden when switching wallets
467501
if (_intentUri) {
468-
invoiceParser.recipient = _intentUri
502+
piResolver.recipient = _intentUri
469503
_intentUri = ''
470504
}
471505
}

electrum/gui/qml/qeapp.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
from .qefx import QEFX
3434
from .qetxfinalizer import QETxFinalizer, QETxRbfFeeBumper, QETxCpfpFeeBumper, QETxCanceller, QETxSweepFinalizer, FeeSlider
3535
from .qeinvoice import QEInvoice, QEInvoiceParser
36+
from .qepiresolver import QEPIResolver
3637
from .qerequestdetails import QERequestDetails
3738
from .qetypes import QEAmount
3839
from .qeaddressdetails import QEAddressDetails
@@ -439,6 +440,7 @@ def __init__(self, args, *, config: 'SimpleConfig', daemon: 'Daemon', plugins: '
439440
qmlRegisterType(QEQRScanner, 'org.electrum', 1, 0, 'QRScanner')
440441
qmlRegisterType(QEFX, 'org.electrum', 1, 0, 'FX')
441442
qmlRegisterType(QETxFinalizer, 'org.electrum', 1, 0, 'TxFinalizer')
443+
qmlRegisterType(QEPIResolver, 'org.electrum', 1, 0, 'PIResolver')
442444
qmlRegisterType(QEInvoice, 'org.electrum', 1, 0, 'Invoice')
443445
qmlRegisterType(QEInvoiceParser, 'org.electrum', 1, 0, 'InvoiceParser')
444446
qmlRegisterType(QEAddressDetails, 'org.electrum', 1, 0, 'AddressDetails')

0 commit comments

Comments
 (0)