Skip to content

Commit c281d38

Browse files
committed
add option to show warnings on wallet close, add warning for ongoing submarine swap
1 parent cca29ef commit c281d38

File tree

4 files changed

+73
-5
lines changed

4 files changed

+73
-5
lines changed

electrum/gui/messages.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,15 @@ def to_rtf(msg):
6161
_("Please remain online until the funding transaction is confirmed.") + "\n\n" +
6262
_('The swap will be finalized once your transaction is confirmed.') + " " +
6363
_("After the funding transaction is mined, the server will reveal the preimage needed to "
64-
"fulfill the pending received lightning HTLCs. The HTLCs expire in {} blocks. "
64+
"fulfill the pending received lightning HTLCs.")
65+
)
66+
67+
MSG_FORWARD_SWAP_HTLC_EXPIRY = _(
68+
"The HTLCs expire in {} blocks. "
6569
"You will need to be online after the funding transaction is confirmed but before the HTLCs expire, "
6670
"to claim your money. If you go offline for several days while the swap is pending, "
6771
"you risk losing the swap amount!").format(MIN_FINAL_CLTV_DELTA_FOR_CLIENT)
68-
)
72+
6973

7074
MSG_REVERSE_SWAP_FUNDING_MEMPOOL = (
7175
_('The funding transaction has been detected.') + " " +

electrum/gui/qt/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import signal
2828
import sys
2929
import threading
30-
from typing import Optional, TYPE_CHECKING, List, Sequence
30+
from typing import Optional, TYPE_CHECKING, List, Sequence, Callable
3131

3232
try:
3333
import PyQt6

electrum/gui/qt/main_window.py

+48-1
Original file line numberDiff line numberDiff line change
@@ -2619,8 +2619,46 @@ def settings_dialog(self):
26192619
if d.need_restart:
26202620
self.show_warning(_('Please restart Electrum to activate the new GUI settings'), title=_('Success'))
26212621

2622+
def _show_closing_warnings(self) -> bool:
2623+
"""Show any closing warnings and return True if the user chose to quit anyways."""
2624+
for callback in self.wallet.closing_warning_callbacks:
2625+
try:
2626+
warning: Optional[str] = callback()
2627+
except Exception:
2628+
self.logger.exception("Closing warning callback failed: ")
2629+
continue
2630+
if warning:
2631+
# build custom QMessageBox to change button strings and color
2632+
box = QMessageBox()
2633+
box.setWindowTitle(_("Don't close Electrum yet!"))
2634+
box.setText(_("An ongoing operation may get interrupted!"))
2635+
box.setInformativeText(str(warning))
2636+
box.setMaximumWidth(400)
2637+
box.setIcon(QMessageBox.Icon.Warning)
2638+
box.setStyleSheet("QMessageBox { border: 3px solid #d9534f; }")
2639+
2640+
# Add custom buttons
2641+
cancel_button = box.addButton(_("Cancel"), QMessageBox.ButtonRole.RejectRole)
2642+
box.setDefaultButton(cancel_button)
2643+
close_anyway_button = box.addButton(_("Close anyways"), QMessageBox.ButtonRole.AcceptRole)
2644+
close_anyway_button.setStyleSheet("background-color: #d9534f;")
2645+
2646+
if text_label := box.findChild(QLabel):
2647+
text_label.setWordWrap(True)
2648+
2649+
box.exec()
2650+
if box.clickedButton() == cancel_button:
2651+
break
2652+
else:
2653+
# user chose to cancel all warnings or there were no warnings
2654+
return True
2655+
return False
2656+
26222657
def closeEvent(self, event):
26232658
# note that closeEvent is NOT called if the user quits with Ctrl-C
2659+
if not self._show_closing_warnings():
2660+
event.ignore()
2661+
return
26242662
self.clean_up()
26252663
event.accept()
26262664

@@ -2809,7 +2847,16 @@ def on_swap_result(self, txid: Optional[str], *, is_reverse: bool):
28092847
if is_reverse:
28102848
msg += messages.MSG_REVERSE_SWAP_FUNDING_MEMPOOL
28112849
else:
2812-
msg += messages.MSG_FORWARD_SWAP_FUNDING_MEMPOOL
2850+
msg += messages.MSG_FORWARD_SWAP_FUNDING_MEMPOOL + messages.MSG_FORWARD_SWAP_HTLC_EXPIRY
2851+
2852+
def wallet_closing_warning_callback() -> Optional[str]:
2853+
# gets called when the wallet GUI is closed
2854+
warning = messages.MSG_REVERSE_SWAP_FUNDING_MEMPOOL if is_reverse \
2855+
else messages.MSG_FORWARD_SWAP_FUNDING_MEMPOOL
2856+
if self.wallet.adb.get_tx_height(txid).height < 1:
2857+
return _("Ongoing submarine swap") + ": " + warning
2858+
self.wallet.register_closing_warning_callback(wallet_closing_warning_callback)
2859+
28132860
self.show_message_signal.emit(msg)
28142861
else:
28152862
msg += _("Lightning funds were not received.") # FIXME should this not depend on is_reverse?

electrum/wallet.py

+18-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
from functools import partial
3535
from collections import defaultdict
3636
from decimal import Decimal
37-
from typing import TYPE_CHECKING, List, Optional, Tuple, Union, NamedTuple, Sequence, Dict, Any, Set, Iterable, Mapping
37+
from typing import (TYPE_CHECKING, List, Optional, Tuple, Union, NamedTuple, Sequence,
38+
Dict, Any, Set, Iterable, Mapping, Callable)
3839
from abc import ABC, abstractmethod
3940
import itertools
4041
import threading
@@ -401,6 +402,7 @@ def __init__(self, db: WalletDB, *, config: SimpleConfig):
401402
db.load_addresses(self.wallet_type)
402403
self.keystore = None # type: Optional[KeyStore] # will be set by load_keystore
403404
self._password_in_memory = None # see self.unlock
405+
self.closing_warning_callbacks = [] # type: List[Callable[[], Optional[str]]]
404406
Logger.__init__(self)
405407

406408
self.network = None
@@ -3456,6 +3458,21 @@ def add_future_tx(self, sweep_info: 'SweepInfo', wanted_height: int):
34563458
util.trigger_callback('wallet_updated', self)
34573459
self.adb.set_future_tx(tx.txid(), wanted_height=wanted_height)
34583460

3461+
def register_closing_warning_callback(
3462+
self,
3463+
callback: Callable[[], Optional[str]],
3464+
*,
3465+
only_gui: Optional[bool] = True
3466+
) -> None:
3467+
"""
3468+
Registers a callback that will be called when the wallet is closed. If the callback
3469+
returns a string it will be shown to the user as a warning to prevent them closing the wallet.
3470+
"""
3471+
if only_gui and not self.config.get("cmd") == "gui":
3472+
return
3473+
self.logger.debug(f"registering wallet closing warning callback")
3474+
self.closing_warning_callbacks.append(callback)
3475+
34593476

34603477
class Simple_Wallet(Abstract_Wallet):
34613478
# wallet with a single keystore

0 commit comments

Comments
 (0)