diff --git a/electrum/gui/qml/qetxfinalizer.py b/electrum/gui/qml/qetxfinalizer.py index bafe4a6c4..1b378d608 100644 --- a/electrum/gui/qml/qetxfinalizer.py +++ b/electrum/gui/qml/qetxfinalizer.py @@ -434,7 +434,10 @@ class QETxFinalizer(TxFeeSlider): self.update_fee_warning_from_tx(tx=tx, invoice_amt=amount) if self._amount.isMax and not self.warning: - if reserve_sats := sum(txo.value for txo in tx.outputs() if txo.is_utxo_reserve): + if reserve_sats := self._wallet.wallet.tx_keeps_ln_utxo_reserve( + tx, + gui_spend_max=self._amount.isMax + ): reserve_str = self._config.format_amount_and_units(reserve_sats) self.warning = ' '.join([ _('Warning') + ':', diff --git a/electrum/gui/qt/confirm_tx_dialog.py b/electrum/gui/qt/confirm_tx_dialog.py index b18f8332b..6ab873331 100644 --- a/electrum/gui/qt/confirm_tx_dialog.py +++ b/electrum/gui/qt/confirm_tx_dialog.py @@ -544,7 +544,7 @@ class TxEditor(WindowModalDialog): if any((txin.block_height is not None and txin.block_height<=0) for txin in self.tx.inputs()): messages.append(_('This transaction will spend unconfirmed coins.')) # warn if a reserve utxo was added - if reserve_sats := sum(txo.value for txo in self.tx.outputs() if txo.is_utxo_reserve): + if reserve_sats := self.wallet.tx_keeps_ln_utxo_reserve(self.tx, gui_spend_max=bool(self.output_value == '!')): reserve_str = self.main_window.config.format_amount_and_units(reserve_sats) messages.append(_('Could not spend max: a security reserve of {} was kept for your Lightning channels.').format(reserve_str)) # warn if we merge from mempool diff --git a/electrum/wallet.py b/electrum/wallet.py index 37c05e742..efdcf03e9 100644 --- a/electrum/wallet.py +++ b/electrum/wallet.py @@ -1911,6 +1911,19 @@ class Abstract_Wallet(ABC, Logger, EventListener): def is_low_reserve(self) -> bool: return self.should_keep_reserve_utxo([], [], False) + def tx_keeps_ln_utxo_reserve(self, tx, *, gui_spend_max: bool) -> Optional[int]: + if reserve_output_amount := sum(txo.value for txo in tx.outputs() if txo.is_utxo_reserve): + # tx has a reserve change output + return reserve_output_amount + if gui_spend_max: # user tried to spend max amount + coins_in_wallet = self.get_spendable_coins(nonlocal_only=False, confirmed_only=False) + amount_in_wallet = sum(c.value_sats() for c in coins_in_wallet) + tx_spend_amount = tx.output_value() + tx.get_fee() + if amount_in_wallet - tx_spend_amount == self.config.LN_UTXO_RESERVE: + # tx keeps exactly LN_UTXO_RESERVE amount sats in the wallet + return self.config.LN_UTXO_RESERVE + return None + @profiler(min_threshold=0.1) def make_unsigned_transaction( self, *,