qt: refactor message for change-to-lightning swap to backend submarine_swaps.py
What changed, and why it matters
This commit is a straightforward code cleanup: it moves the logic that decides what message to show users about 'sending change to Lightning' from the Qt GUI dialog into a shared backend module. The visible behavior is essentially unchanged, and there is no indication of a security fix or vulnerability.
No security action required; treat as a normal maintainability refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff refactors message-generation for the ‘change-to-lightning’ submarine swap feature. In confirm_tx_dialog.py, a ~30-line block of inline message construction is replaced by a call to self.swap_manager.get_message_for_swap_change(...). The equivalent logic is added as a new method in submarine_swaps.py. The refactor also slightly restructures the conditional flow (e.g., adding an explicit ‘Lightning is not enabled’ branch and a ‘No change output’ branch), but the strings and calculations remain the same. No cryptographic, network, or transaction-handling code is modified.
Changed components
electrum/gui/qt/confirm_tx_dialog.pyelectrum/submarine_swaps.pyInspect captured patch +40 / −33
diff --git a/electrum/gui/qt/confirm_tx_dialog.py b/electrum/gui/qt/confirm_tx_dialog.py
index edfa715..a53f36c 100644
--- a/electrum/gui/qt/confirm_tx_dialog.py
+++ b/electrum/gui/qt/confirm_tx_dialog.py
@@ -683,39 +683,11 @@ class TxEditor(WindowModalDialog, QtEventListener, Logger):
messages.append(long_warning)
if self.no_dynfee_estimates:
self.error = _('Fee estimates not available. Please set a fixed fee or feerate.')
- if dummy_output := self.tx.get_dummy_output(DummyAddress.SWAP):
- swap_msg = _('Will send change to lightning')
- swap_fee_msg = "."
- if self.swap_manager and self.swap_manager.is_initialized.is_set() and isinstance(dummy_output.value, int):
- ln_amount_we_recv = self.swap_manager.get_recv_amount(send_amount=dummy_output.value, is_reverse=False)
- if ln_amount_we_recv:
- swap_fees = dummy_output.value - ln_amount_we_recv
- swap_fee_msg = " [" + _("Swap fees:") + " " + self.main_window.format_amount_and_units(swap_fees) + "]."
- messages.append(swap_msg + swap_fee_msg)
- elif self.config.WALLET_SEND_CHANGE_TO_LIGHTNING \
- and not (self.swap_transport and self.swap_transport.ongoing_connection_attempt) \
- and self.tx.has_change():
- swap_msg = _('Will not send change to Lightning')
- swap_msg_reason = None
- change_amount = sum(c.value for c in self.tx.get_change_outputs() if isinstance(c.value, int))
- if not self.wallet.has_lightning():
- swap_msg_reason = _('Lightning is not enabled.')
- elif change_amount > int(self.wallet.lnworker.num_sats_can_receive()):
- swap_msg_reason = _("Your channels cannot receive this amount.")
- elif self.wallet.lnworker.swap_manager.is_initialized.is_set():
- min_amount = self.wallet.lnworker.swap_manager.get_min_amount()
- max_amount = self.wallet.lnworker.swap_manager.get_provider_max_reverse_amount()
- if change_amount < min_amount:
- swap_msg_reason = _("Below the swap providers minimum value of {}.").format(
- self.main_window.format_amount_and_units(min_amount)
- )
- else:
- swap_msg_reason = _('Change amount exceeds the swap providers maximum value of {}.').format(
- self.main_window.format_amount_and_units(max_amount)
- )
- messages.append(swap_msg + (f": {swap_msg_reason}" if swap_msg_reason else '.'))
- elif self.swap_transport and self.swap_transport.ongoing_connection_attempt:
- messages.append(_("Fetching submarine swap providers..."))
+ if self.config.WALLET_SEND_CHANGE_TO_LIGHTNING:
+ if not self.swap_manager:
+ messages.append(_("Lightning is not enabled."))
+ elif swap_msg := self.swap_manager.get_message_for_swap_change(self.swap_transport, self.tx):
+ messages.append(swap_msg)
# warn if spending unconf
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.'))
diff --git a/electrum/submarine_swaps.py b/electrum/submarine_swaps.py
index 78aa2bb..9607f8a 100644
--- a/electrum/submarine_swaps.py
+++ b/electrum/submarine_swaps.py
@@ -372,6 +372,41 @@ class SwapManager(Logger):
# we couldn't even connect to the relays, this transport is useless. maybe network issues.
return False
+ def get_message_for_swap_change(self, swap_transport, tx):
+ """ UI support for send-change-to-lightning.
+ """
+ msg = ''
+ if swap_transport is not None and swap_transport.ongoing_connection_attempt:
+ msg = _("Fetching submarine swap providers...")
+ elif dummy_output := tx.get_dummy_output(DummyAddress.SWAP):
+ msg = _('Will send change to lightning')
+ if self.is_initialized.is_set() and isinstance(dummy_output.value, int):
+ ln_amount_we_recv = self.get_recv_amount(send_amount=dummy_output.value,
+ is_reverse=False)
+ if ln_amount_we_recv:
+ swap_fees = dummy_output.value - ln_amount_we_recv
+ msg += " [" + _("Swap fees:") + " " + self.config.format_amount_and_units(swap_fees) + "]."
+ elif not tx.has_change():
+ msg = _('No change output, so no need for swap')
+ else:
+ change_amount = sum(c.value for c in tx.get_change_outputs() if isinstance(c.value, int))
+ if change_amount > int(self.wallet.lnworker.num_sats_can_receive()):
+ msg = _("Your channels cannot receive this amount.")
+ elif self.is_initialized.is_set():
+ min_amount = self.get_min_amount()
+ max_amount = self.get_provider_max_reverse_amount()
+ if change_amount < min_amount:
+ msg = _("Below the swap providers minimum value of {}.").format(
+ self.config.format_amount_and_units(min_amount)
+ )
+ elif change_amount > max_amount:
+ msg = _('Change amount exceeds the swap providers maximum value of {}.').format(
+ self.config.format_amount_and_units(max_amount)
+ )
+ else:
+ msg = _('Will not send change to Lightning')
+ return msg
+
async def set_nostr_proof_of_work(self) -> None:
current_pow = get_nostr_ann_pow_amount(
self.lnworker.nostr_keypair.pubkey[1:],
Why this scored 13/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.