Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions electrum/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def satoshis(amount):
return int(COIN*to_decimal(amount)) if amount is not None else None


def format_satoshis(x: Union[float, int, Decimal, None]) -> Optional[str]:
def format_satoshis(x: Union[int, Decimal, None]) -> Optional[str]:
"""
input: satoshis as a Number
output: str formatted as bitcoin amount
Expand Down Expand Up @@ -1380,7 +1380,7 @@ async def add_request(self, amount, memo='', expiry=3600, lightning=False, force
else:
addr = None
expiry = int(expiry) if expiry else None
key = wallet.create_request(amount, memo, expiry, addr)
key = wallet.create_request(amount_sat=amount, message=memo, exp_delay=expiry, address=addr)
req = wallet.get_request(key)
return wallet.export_request(req)

Expand Down
4 changes: 2 additions & 2 deletions electrum/gui/qml/components/BalanceDetails.qml
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ Pane {
Layout.preferredWidth: 1
text: qsTr('Lightning swap');
visible: Daemon.currentWallet.isLightning
enabled: Daemon.currentWallet.lightningCanSend.satsInt > 0 || Daemon.currentWallet.lightningCanReceive.satsInt > 0
enabled: !Daemon.currentWallet.lightningCanSend.isEmpty || !Daemon.currentWallet.lightningCanReceive.isEmpty
icon.source: Qt.resolvedUrl('../../icons/update.png')
onClicked: app.startSwap()
}
Expand All @@ -224,7 +224,7 @@ Pane {
Layout.preferredWidth: 1
text: qsTr('Open Channel')
visible: Daemon.currentWallet.isLightning
enabled: Daemon.currentWallet.confirmedBalance.satsInt > 0
enabled: !Daemon.currentWallet.confirmedBalance.isEmpty
onClicked: {
var dialog = openChannelDialog.createObject(rootItem)
dialog.open()
Expand Down
6 changes: 3 additions & 3 deletions electrum/gui/qml/components/Channels.qml
Original file line number Diff line number Diff line change
Expand Up @@ -123,16 +123,16 @@ Pane {
Layout.fillWidth: true
Layout.preferredWidth: 1
text: qsTr('Swap');
enabled: Daemon.currentWallet.lightningCanSend.satsInt > 0 ||
(Daemon.currentWallet.lightningCanReceive.satsInt > 0 && Daemon.currentWallet.confirmedBalance.satsInt > 0)
enabled: !Daemon.currentWallet.lightningCanSend.isEmpty ||
(!Daemon.currentWallet.lightningCanReceive.isEmpty && !Daemon.currentWallet.confirmedBalance.isEmpty)
icon.source: Qt.resolvedUrl('../../icons/update.png')
onClicked: app.startSwap()
}

FlatButton {
Layout.fillWidth: true
Layout.preferredWidth: 1
enabled: Daemon.currentWallet.canHaveLightning && Daemon.currentWallet.confirmedBalance.satsInt > 0
enabled: Daemon.currentWallet.canHaveLightning && !Daemon.currentWallet.confirmedBalance.isEmpty
text: qsTr('Open Channel')
onClicked: {
if (Daemon.currentWallet.channelModel.count == 0) {
Expand Down
12 changes: 6 additions & 6 deletions electrum/gui/qml/components/InvoiceDialog.qml
Original file line number Diff line number Diff line change
Expand Up @@ -230,16 +230,16 @@ ElDialog {
color: readOnly
? Material.accentColor
: Material.foreground
onTextAsSatsChanged: {
onValueChanged: {
if (!amountMax.checked)
invoice.amountOverride.copyFrom(textAsSats)
}
Connections {
target: invoice.amountOverride
function onSatsIntChanged() {
console.log('amountOverride satsIntChanged, sats=' + invoice.amountOverride.satsInt)
function onValueChanged() {
console.log('amountOverride valueChanged, sats=' + invoice.amountOverride.satsStr)
if (amountMax.checked) // amountOverride updated by max amount estimate
amountBtc.text = Config.formatSatsForEditing(invoice.amountOverride.satsInt)
amountBtc.text = Config.formatSatsForEditing(invoice.amountOverride)
}
}
}
Expand Down Expand Up @@ -472,7 +472,7 @@ ElDialog {
enabled: !invoice.isSaved && invoice.canSave
onClicked: {
if (invoice.amount.isEmpty) {
invoice.amountOverride = Config.unitsToSats(amountBtc.text)
invoice.amountOverride = Config.baseunitStrToAmount(amountBtc.text)
if (amountMax.checked)
invoice.amountOverride.isMax = true
}
Expand All @@ -490,7 +490,7 @@ ElDialog {
enabled: invoice.invoiceType != Invoice.Invalid && invoice.canPay
onClicked: {
if (invoice.amount.isEmpty) {
invoice.amountOverride = Config.unitsToSats(amountBtc.text)
invoice.amountOverride = Config.baseunitStrToAmount(amountBtc.text)
if (amountMax.checked)
invoice.amountOverride.isMax = true
}
Expand Down
6 changes: 3 additions & 3 deletions electrum/gui/qml/components/LightningPaymentDetails.qml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Pane {
}

Label {
text: lnpaymentdetails.amount.msatsInt > 0
text: lnpaymentdetails.amount.positive
? qsTr('Amount received')
: qsTr('Amount sent')
color: Material.accentColor
Expand All @@ -64,13 +64,13 @@ Pane {
}

Label {
visible: lnpaymentdetails.amount.msatsInt < 0
visible: !lnpaymentdetails.amount.positive
text: qsTr('Transaction fee')
color: Material.accentColor
}

FormattedAmount {
visible: lnpaymentdetails.amount.msatsInt < 0
visible: !lnpaymentdetails.amount.positive
amount: lnpaymentdetails.fee
timestamp: lnpaymentdetails.timestamp
}
Expand Down
25 changes: 17 additions & 8 deletions electrum/gui/qml/components/LnurlPayRequestDialog.qml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@ ElDialog {
needsSystemBarPadding: false

property bool commentValid: comment.text.length <= invoiceParser.lnurlData['comment_allowed']
property bool amountValid: amountBtc.textAsSats.satsInt >= parseInt(invoiceParser.lnurlData['min_sendable_sat'])
&& amountBtc.textAsSats.satsInt <= parseInt(invoiceParser.lnurlData['max_sendable_sat'])
property bool amountValid: false
property bool valid: commentValid && amountValid

function isValidAmount() {
return amountBtc.textAsSats.gte(invoiceParser.lnurlData['min_sendable_msat'])
&& amountBtc.textAsSats.lte(invoiceParser.lnurlData['max_sendable_msat'])
&& amountBtc.textAsSats.lte(invoiceParser.wallet.lightningCanSend)
}

ColumnLayout {
width: parent.width

Expand All @@ -41,9 +46,11 @@ ElDialog {
Layout.columnSpan: 2
Layout.fillWidth: true
compact: true
visible: invoiceParser.lnurlData['min_sendable_sat'] != invoiceParser.lnurlData['max_sendable_sat']
text: qsTr('Amount must be between %1 and %2 %3').arg(Config.formatSats(invoiceParser.lnurlData['min_sendable_sat'])).arg(Config.formatSats(invoiceParser.lnurlData['max_sendable_sat'])).arg(Config.baseUnit)
backgroundColor: constants.darkerDialogBackground
visible: !invoiceParser.lnurlData['min_sendable_msat'].eq(invoiceParser.lnurlData['max_sendable_msat'])
text: qsTr('Amount must be between %1 and %2 %3')
.arg(Config.formatMilliSats(invoiceParser.lnurlData['min_sendable_msat']))
.arg(Config.formatMilliSats(invoiceParser.lnurlData['max_sendable_msat']))
.arg(Config.baseUnit)
}

Label {
Expand Down Expand Up @@ -74,12 +81,14 @@ ElDialog {
BtcField {
id: amountBtc
Layout.preferredWidth: rootLayout.width /3
text: Config.formatSatsForEditing(invoiceParser.lnurlData['min_sendable_sat'])
enabled: invoiceParser.lnurlData['min_sendable_sat'] != invoiceParser.lnurlData['max_sendable_sat']
text: Config.formatMilliSatsForEditing(invoiceParser.lnurlData['min_sendable_msat'])
enabled: !invoiceParser.lnurlData['min_sendable_msat'].eq(invoiceParser.lnurlData['max_sendable_msat'])
color: Material.foreground // override gray-out on disabled
fiatfield: amountFiat
onTextAsSatsChanged: {
msatPrecision: true
onValueChanged: {
invoiceParser.amountOverride = textAsSats
dialog.amountValid = isValidAmount()
}
}
Label {
Expand Down
77 changes: 49 additions & 28 deletions electrum/gui/qml/components/LnurlWithdrawRequestDialog.qml
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,62 @@ ElDialog {
title: qsTr('LNURL Withdraw request')
iconSource: '../../../icons/link.png'

property var wallet: Daemon.currentWallet // type: Wallet
property var requestDetails // type: RequestDetails
property var requestDetails
property var onemsat: Amount { Component.onCompleted: { msatsInt = 1 } }

padding: 0
needsSystemBarPadding: false

property int walletCanReceive: 0
property int providerMinWithdrawable: parseInt(requestDetails.lnurlData['min_withdrawable_sat'])
property int providerMaxWithdrawable: parseInt(requestDetails.lnurlData['max_withdrawable_sat'])
property int effectiveMinWithdrawable: Math.max(providerMinWithdrawable, 1)
property int effectiveMaxWithdrawable: Math.min(providerMaxWithdrawable, walletCanReceive)
property bool insufficientLiquidity: effectiveMinWithdrawable > walletCanReceive
property bool liquidityWarning: providerMaxWithdrawable > walletCanReceive

property bool amountValid: !dialog.insufficientLiquidity &&
amountBtc.textAsSats.satsInt >= dialog.effectiveMinWithdrawable &&
amountBtc.textAsSats.satsInt <= dialog.effectiveMaxWithdrawable
property var walletCanReceive: Amount {}
property var providerMinWithdrawable: requestDetails.lnurlData['min_withdrawable_msat']
property var providerMaxWithdrawable: requestDetails.lnurlData['max_withdrawable_msat']
property var effectiveMinWithdrawable: onemsat.max(providerMinWithdrawable, onemsat)
property var effectiveMaxWithdrawable: onemsat.min(providerMaxWithdrawable, requestDetails.wallet.lightningCanReceive)
property bool insufficientLiquidity: effectiveMinWithdrawable.gt(requestDetails.wallet.lightningCanReceive)
property bool liquidityWarning: providerMaxWithdrawable.gt(walletCanReceive)
property bool fixedAmount: false

property bool amountValid: isValidAmount()
property bool valid: amountValid

Component.onCompleted: {
dialog.walletCanReceive = wallet.lightningCanReceive.satsInt
updateLimits()
}

function isValidAmount() {
return !dialog.insufficientLiquidity
&& amountBtc.textAsSats.gte(dialog.effectiveMinWithdrawable)
&& amountBtc.textAsSats.lte(dialog.effectiveMaxWithdrawable)
}

function updateLimits() {
dialog.walletCanReceive.copyFrom(requestDetails.wallet.lightningCanReceive)
dialog.effectiveMaxWithdrawable = onemsat.min(dialog.providerMaxWithdrawable, requestDetails.wallet.lightningCanReceive)
dialog.insufficientLiquidity = dialog.effectiveMinWithdrawable.gt(requestDetails.wallet.lightningCanReceive)
dialog.liquidityWarning = dialog.providerMaxWithdrawable.gt(requestDetails.wallet.lightningCanReceive)
dialog.fixedAmount = dialog.providerMinWithdrawable.eq(dialog.providerMaxWithdrawable)
dialog.amountValid = isValidAmount()
}

Connections {
// assign walletCanReceive directly to prevent a binding loop
target: wallet
target: requestDetails.wallet
function onLightningCanReceiveChanged() {
if (!requestDetails.busy) {
// don't assign while busy to prevent the view from changing while receiving
// the incoming payment
dialog.walletCanReceive = wallet.lightningCanReceive.satsInt
updateLimits()
}
}
}

Connections {
target: amountBtc
function onValueChanged() {
dialog.amountValid = isValidAmount()
}
}

ColumnLayout {
width: parent.width
spacing: 0
Expand All @@ -69,10 +90,10 @@ ElDialog {
text: qsTr('Too little incoming liquidity to satisfy this withdrawal request.')
+ '\n\n'
+ qsTr('Can receive: %1')
.arg(Config.formatSats(dialog.walletCanReceive) + ' ' + Config.baseUnit)
.arg(Config.formatMilliSats(dialog.walletCanReceive) + ' ' + Config.baseUnit)
+ '\n'
+ qsTr('Minimum withdrawal amount: %1')
.arg(Config.formatSats(dialog.providerMinWithdrawable) + ' ' + Config.baseUnit)
.arg(Config.formatMilliSats(dialog.providerMinWithdrawable) + ' ' + Config.baseUnit)
+ '\n\n'
+ qsTr('Do a submarine swap in the \'Channels\' tab to get more incoming liquidity.')
iconStyle: InfoTextArea.IconStyle.Error
Expand All @@ -83,10 +104,10 @@ ElDialog {
Layout.columnSpan: 2
Layout.fillWidth: true
compact: true
visible: !dialog.insufficientLiquidity && dialog.providerMinWithdrawable != dialog.providerMaxWithdrawable
visible: !dialog.insufficientLiquidity && !dialog.fixedAmount
text: qsTr('Amount must be between %1 and %2 %3')
.arg(Config.formatSats(dialog.effectiveMinWithdrawable))
.arg(Config.formatSats(dialog.effectiveMaxWithdrawable))
.arg(Config.formatMilliSats(dialog.effectiveMinWithdrawable))
.arg(Config.formatMilliSats(dialog.effectiveMaxWithdrawable))
.arg(Config.baseUnit)
backgroundColor: constants.darkerDialogBackground
}
Expand All @@ -97,8 +118,8 @@ ElDialog {
compact: true
visible: dialog.liquidityWarning && !dialog.insufficientLiquidity
text: qsTr('The maximum withdrawable amount (%1) is larger than what your channels can receive (%2).')
.arg(Config.formatSats(dialog.providerMaxWithdrawable) + ' ' + Config.baseUnit)
.arg(Config.formatSats(dialog.walletCanReceive) + ' ' + Config.baseUnit)
.arg(Config.formatMilliSats(dialog.providerMaxWithdrawable) + ' ' + Config.baseUnit)
.arg(Config.formatMilliSats(dialog.walletCanReceive) + ' ' + Config.baseUnit)
+ ' '
+ qsTr('You may need to do a submarine swap to increase your incoming liquidity.')
iconStyle: InfoTextArea.IconStyle.Warn
Expand Down Expand Up @@ -135,10 +156,11 @@ ElDialog {
BtcField {
id: amountBtc
Layout.preferredWidth: rootLayout.width / 3
text: Config.formatSatsForEditing(dialog.effectiveMaxWithdrawable)
enabled: !dialog.insufficientLiquidity && (dialog.providerMinWithdrawable != dialog.providerMaxWithdrawable)
text: Config.formatMilliSatsForEditing(dialog.effectiveMaxWithdrawable)
enabled: !dialog.insufficientLiquidity && !dialog.fixedAmount
color: Material.foreground // override gray-out on disabled
fiatfield: amountFiat
msatPrecision: true
}
Label {
text: Config.baseUnit
Expand All @@ -154,7 +176,7 @@ ElDialog {
id: amountFiat
Layout.preferredWidth: rootLayout.width / 3
btcfield: amountBtc
enabled: !dialog.insufficientLiquidity && (dialog.providerMinWithdrawable != dialog.providerMaxWithdrawable)
enabled: !dialog.insufficientLiquidity && !dialog.fixedAmount
color: Material.foreground
}
Label {
Expand All @@ -173,8 +195,7 @@ ElDialog {
icon.source: '../../icons/confirmed.png'
enabled: valid && !requestDetails.busy
onClicked: {
var satsAmount = amountBtc.textAsSats.satsInt;
requestDetails.lnurlRequestWithdrawal(satsAmount);
requestDetails.lnurlRequestWithdrawal(amountBtc.textAsSats);
dialog.close();
}
}
Expand Down
6 changes: 3 additions & 3 deletions electrum/gui/qml/components/OpenChannelDialog.qml
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ ElDialog {
id: amountBtc
fiatfield: amountFiat
Layout.preferredWidth: amountFontMetrics.advanceWidth('0') * 14 + leftPadding + rightPadding
onTextAsSatsChanged: {
onValueChanged: {
if (!is_max.checked)
channelopener.amount = amountBtc.textAsSats
}
Expand All @@ -177,9 +177,9 @@ ElDialog {

Connections {
target: channelopener.amount
function onSatsIntChanged() {
function onValueChanged() {
if (is_max.checked) // amount updated by max amount estimate
amountBtc.text = Config.formatSatsForEditing(channelopener.amount.satsInt)
amountBtc.text = Config.formatSatsForEditing(channelopener.amount)
}
}
}
Expand Down
Loading