Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
41e3301
qt: fix weird inheritance tree FeerateEdit, move text render with dec…
accumulator Apr 15, 2026
dfaae70
qml: in QEAmount, keep msat and sat synchronized, and be more strict …
accumulator Apr 17, 2026
23c9428
wallet: kwarg all parameters of wallet.create_request()
accumulator Apr 15, 2026
733a0d1
invoices: add BaseInvoice.get_amount_sat_msat_precision() func
accumulator Apr 16, 2026
4798822
qt: millisat precision request tab, request list, invoice list
accumulator Apr 15, 2026
32d7e1a
lnworker: can_{pay,receive}_invoice millisat precision
accumulator Apr 16, 2026
8b82418
lnurl, pi: use msat precision
accumulator Apr 16, 2026
7a36b8b
qml: millisat precision ReceiveDetailsDialog, QERequestDetails, QEInv…
accumulator Apr 17, 2026
aa78fdc
qml: refactor QEConfig.unitsToSats to QEConfig.baseunitStrToAmount and
accumulator Apr 17, 2026
8a6ba99
qml: only use QEAmount container instead of javascript/qml (q(u))int(64)
accumulator Apr 19, 2026
b93c03a
qml: take can-send into account for lnurlp
accumulator Apr 20, 2026
01db32a
qt: BTCAmountEdit allow dynamically changing precision, disable msat …
accumulator Apr 16, 2026
537a33d
util: format_satoshis_plain: remove TODO, hard-fail on float
accumulator Jun 11, 2026
44e2ac3
qml: a FiatField containing a zero effective value during editing set…
accumulator Jun 29, 2026
8d39618
qml: expose amount in ReceiveDetailsDialog as an Amount type instead …
accumulator Jun 29, 2026
9e6ca00
qml: use a stable instance for amount in QERequestDetails
accumulator Jun 29, 2026
a552705
qml: ReceiveDetailsDialog fix can pay check on edit
accumulator Jun 29, 2026
87297fe
qml: QEAmount remove unneeded warnings and isEmpty checks
accumulator Jun 29, 2026
232d5d7
lnurl: assert LNURL3/LNURL6 response max amounts to theoretical range.
accumulator Aug 18, 2026
20ac067
qml: QEAmount treat a None operand as a zero amount in comparisons
accumulator Aug 18, 2026
a5c5b99
qml: QEAmount compare equality against None -> 0 implicit conversion …
accumulator Aug 18, 2026
7494494
qml: coerce QEAmount value to 0 if None
accumulator Aug 26, 2026
1b3b459
qml: qeconfig: unify the behaviour of formatMilliSats{,ForEditing} to…
accumulator Aug 27, 2026
9779acf
qml: fix ReceiveDetailsDialog for millisat precision for non-lightnin…
accumulator Aug 26, 2026
5e35419
qt: render amounts in millisat precision in channel_details, lightnin…
accumulator Aug 26, 2026
555a431
qml: tighten btc amount regexes to allow 21000000 BTC plus decimals, …
accumulator Aug 27, 2026
8ce0c4f
qml: BalanceSummary formatMilliSats
accumulator Aug 27, 2026
949765e
lnurl: check lnurlp min amount > 0, lnurlw min amount >= 0
accumulator Aug 27, 2026
4aa2671
qeinvoice: avoid stale override amount, reset overrideAmount on set_e…
accumulator Sep 1, 2026
5e2c88b
qml: make sure to update on lightningCanSend in LnurlPayRequestDialog
accumulator Sep 1, 2026
22e396b
qt: clamp AmountEdit, FiatAmountEdit and FeerateEdit to 'reasonable' …
accumulator Sep 1, 2026
2838ce2
qml: don't show millisat precision, except in
accumulator Oct 15, 2026
b193c73
qml: fix qint64 overflow due to too large millisat amounts when conve…
accumulator Oct 15, 2026
3bf9b96
qml: introduce a .bind property on QEAmount, to allow valueChanged si…
accumulator Oct 15, 2026
2724f8e
qewallet: don't update balance, liquidity amounts in the getters
accumulator Oct 15, 2026
68a0287
qml: update balances on frozen coins/addresses change, and on config …
accumulator Oct 16, 2026
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 @@ -107,7 +107,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 @@ -1420,7 +1420,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
3 changes: 3 additions & 0 deletions electrum/gui/qml/components/ChannelDetails.qml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ Pane {
FormattedAmount {
visible: channeldetails.isOpen
amount: channeldetails.localCapacity
msatPrecision: true
}

Label {
Expand All @@ -136,6 +137,7 @@ Pane {
visible: !channeldetails.frozenForSending
amount: channeldetails.canSend
singleLine: false
msatPrecision: true
}
Label {
visible: channeldetails.frozenForSending
Expand Down Expand Up @@ -168,6 +170,7 @@ Pane {
visible: !channeldetails.frozenForReceiving
amount: channeldetails.canReceive
singleLine: false
msatPrecision: true
}

Label {
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
28 changes: 4 additions & 24 deletions electrum/gui/qml/components/ConfirmTxDialog.qml
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,6 @@ ElDialog {
height: parent.height
padding: 0

function updateAmountText() {
if (finalizer.valid) {
btcValue.text = Config.formatSats(finalizer.effectiveAmount, false)
fiatValue.text = Daemon.fx.enabled
? Daemon.fx.fiatValue(finalizer.effectiveAmount, false)
: ''
} else {
btcValue.text = Config.formatSats(finalizer.amount, false)
fiatValue.text = Daemon.fx.enabled
? Daemon.fx.fiatValue(finalizer.amount, false)
: ''
}
}

ColumnLayout {
anchors.fill: parent
spacing: 0
Expand Down Expand Up @@ -79,6 +65,7 @@ ElDialog {
Label {
id: btcValue
Layout.alignment: Qt.AlignRight
text: Config.formatSats(finalizer.valid ? finalizer.effectiveAmount : finalizer.amount, false)
font.pixelSize: constants.fontSizeXLarge
font.family: FixedFont
font.bold: true
Expand All @@ -95,6 +82,9 @@ ElDialog {
id: fiatValue
Layout.alignment: Qt.AlignRight
visible: Daemon.fx.enabled
text: Daemon.fx.enabled
? Daemon.fx.fiatValue(finalizer.valid ? finalizer.effectiveAmount : finalizer.amount, false)
: ''
font.pixelSize: constants.fontSizeMedium
color: constants.mutedForeground
}
Expand All @@ -106,16 +96,6 @@ ElDialog {
font.pixelSize: constants.fontSizeMedium
color: constants.mutedForeground
}
Component.onCompleted: updateAmountText()
Connections {
target: finalizer
function onEffectiveAmountChanged() {
updateAmountText()
}
function onValidChanged() {
updateAmountText()
}
}
}
}

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 @@ -231,16 +231,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 @@ -473,7 +473,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 @@ -491,7 +491,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
8 changes: 5 additions & 3 deletions electrum/gui/qml/components/LightningPaymentDetails.qml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Pane {
}

Label {
text: lnpaymentdetails.amount.msatsInt > 0
text: lnpaymentdetails.amount.positive
? qsTr('Amount received')
: qsTr('Amount sent')
color: Material.accentColor
Expand All @@ -58,18 +58,20 @@ Pane {
FormattedAmount {
amount: lnpaymentdetails.amount
timestamp: lnpaymentdetails.timestamp
msatPrecision: true
}

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
msatPrecision: true
}

Label {
Expand Down
25 changes: 16 additions & 9 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: isValidAmount()
property bool valid: commentValid && amountValid

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

ColumnLayout {
width: parent.width

Expand All @@ -41,8 +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)
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)
backgroundColor: constants.darkerDialogBackground
}

Expand Down Expand Up @@ -74,13 +82,12 @@ 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: {
invoiceParser.amountOverride = textAsSats
}
msatPrecision: true
onValueChanged: invoiceParser.amountOverride = textAsSats
}
Label {
text: Config.baseUnit
Expand Down
Loading