Skip to content

Commit 60282c0

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 f74efe8 commit 60282c0

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

@@ -71,7 +72,7 @@ ElDialog {
7172
FlatButton {
7273
Layout.fillWidth: true
7374
Layout.preferredWidth: 1
74-
enabled: !invoiceParser.busy
75+
enabled: !invoiceParser.busy && !piResolver.busy
7576
icon.source: '../../icons/copy_bw.png'
7677
text: qsTr('Paste')
7778
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
}
@@ -61,7 +61,7 @@ Item {
6161
})
6262
dialog.open()
6363
} else {
64-
invoiceParser.recipient = data
64+
piResolver.recipient = data
6565
}
6666
//scanner.destroy() // TODO
6767
})
@@ -361,7 +361,7 @@ Item {
361361
Layout.preferredWidth: 1
362362
icon.source: '../../icons/tab_send.png'
363363
text: qsTr('Send')
364-
enabled: !invoiceParser.busy
364+
enabled: !invoiceParser.busy && !piResolver.busy && !requestDetails.busy
365365
onClicked: openSendDialog()
366366
onPressAndHold: {
367367
Config.userKnowsPressAndHold = true
@@ -372,6 +372,45 @@ Item {
372372
}
373373
}
374374

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

@@ -464,7 +498,7 @@ Item {
464498
function onWalletLoaded() {
465499
infobanner.hide() // start hidden when switching wallets
466500
if (_intentUri) {
467-
invoiceParser.recipient = _intentUri
501+
piResolver.recipient = _intentUri
468502
_intentUri = ''
469503
}
470504
}

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, QEBytes
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)