What changed, and why it matters
This commit only adds Python type hints and fixes a minor return-value consistency bug in the QML GUI code. It does not change runtime behavior in a security-relevant way, and there is no indication it fixes a vulnerability.
No security action needed. Treat as a normal code-quality/type-annotation patch.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff adds type annotations (PartialTransaction, FeePolicy, Callable, Transaction) to several methods and variables in electrum/gui/qml/qechannelopener.py, electrum/gui/qml/qetxfinalizer.py, and electrum/gui/qml/qewallet.py. It also changes save_tx to explicitly return False on conflict instead of returning None implicitly. These are static-typing and code-clarity improvements; no security-sensitive logic is altered.
Changed components
electrum/gui/qml/qechannelopener.pyelectrum/gui/qml/qetxfinalizer.pyelectrum/gui/qml/qewallet.pyInspect captured patch +17 / −10
diff --git a/electrum/gui/qml/qechannelopener.py b/electrum/gui/qml/qechannelopener.py
index 350c20e..927f7a8 100644
--- a/electrum/gui/qml/qechannelopener.py
+++ b/electrum/gui/qml/qechannelopener.py
@@ -15,6 +15,7 @@ from electrum.bitcoin import DummyAddress
from electrum.lnworker import hardcoded_trampoline_nodes
from electrum.logging import get_logger
from electrum.fee_policy import FeePolicy
+from electrum.transaction import PartialTransaction
from .auth import AuthMixin, auth_protect
from .qetxfinalizer import QETxFinalizer
@@ -219,7 +220,7 @@ class QEChannelOpener(QObject, AuthMixin):
self.finalizerChanged.emit()
@auth_protect(message=_('Open Lightning channel?'))
- def do_open_channel(self, funding_tx, conn_str, password):
+ def do_open_channel(self, funding_tx: PartialTransaction, conn_str, password):
"""
conn_str: a connection string that extract_nodeid can parse, i.e. cannot be a trampoline name
"""
diff --git a/electrum/gui/qml/qetxfinalizer.py b/electrum/gui/qml/qetxfinalizer.py
index 368d0c6..2f74c7e 100644
--- a/electrum/gui/qml/qetxfinalizer.py
+++ b/electrum/gui/qml/qetxfinalizer.py
@@ -2,7 +2,7 @@ import copy
from enum import IntEnum
import threading
from decimal import Decimal
-from typing import Optional, TYPE_CHECKING
+from typing import Optional, TYPE_CHECKING, Callable
from functools import partial
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, pyqtEnum
@@ -55,7 +55,7 @@ class FeeSlider(QObject):
self._wallet = None # type: Optional[QEWallet]
self._sliderSteps = 0
self._sliderPos = 0
- self._fee_policy = None
+ self._fee_policy = None # type: Optional[FeePolicy]
self._target = ''
self._config = None # type: Optional[SimpleConfig]
@@ -150,7 +150,7 @@ class TxFeeSlider(FeeSlider):
self._fee = QEAmount()
self._feeRate = ''
self._rbf = False
- self._tx = None
+ self._tx = None # type: Optional[PartialTransaction]
self._inputs = []
self._outputs = []
self._finalized_txid = ''
@@ -244,7 +244,7 @@ class TxFeeSlider(FeeSlider):
def doUpdate(self):
self.update()
- def update_from_tx(self, tx):
+ def update_from_tx(self, tx: PartialTransaction):
tx_size = tx.estimated_size()
fee = tx.get_fee()
feerate = Decimal(fee) / tx_size # sat/byte
@@ -256,7 +256,7 @@ class TxFeeSlider(FeeSlider):
self.update_inputs_from_tx(tx)
self.update_outputs_from_tx(tx)
- def update_inputs_from_tx(self, tx):
+ def update_inputs_from_tx(self, tx: Transaction):
inputs = []
for inp in tx.inputs():
# addr = self.wallet.adb.get_txin_address(txin)
@@ -277,7 +277,7 @@ class TxFeeSlider(FeeSlider):
})
self.inputs = inputs
- def update_outputs_from_tx(self, tx):
+ def update_outputs_from_tx(self, tx: PartialTransaction):
sm = self._wallet.wallet.lnworker.swap_manager if self._wallet.wallet.lnworker else None
outputs = []
@@ -315,7 +315,13 @@ class QETxFinalizer(TxFeeSlider):
finished = pyqtSignal([bool, bool, bool], arguments=['signed', 'saved', 'complete'])
signError = pyqtSignal([str], arguments=['message'])
- def __init__(self, parent=None, *, make_tx=None, accept=None):
+ def __init__(
+ self,
+ parent=None,
+ *,
+ make_tx: Callable[[int, FeePolicy], PartialTransaction] = None,
+ accept: Callable[[PartialTransaction], None] = None,
+ ):
super().__init__(parent)
self.f_make_tx = make_tx
self.f_accept = accept
diff --git a/electrum/gui/qml/qewallet.py b/electrum/gui/qml/qewallet.py
index 8a4d6a6..b9c593d 100644
--- a/electrum/gui/qml/qewallet.py
+++ b/electrum/gui/qml/qewallet.py
@@ -637,14 +637,14 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
# TODO: properly catch server side errors, e.g. bad-txns-inputs-missingorspent
- def save_tx(self, tx: 'PartialTransaction'):
+ def save_tx(self, tx: 'PartialTransaction') -> bool:
assert tx
try:
if not self.wallet.adb.add_transaction(tx):
self.saveTxError.emit(tx.txid(), 'conflict',
_("Transaction could not be saved.") + "\n" + _("It conflicts with current history."))
- return
+ return False
self.wallet.save_db()
self.saveTxSuccess.emit(tx.txid())
self.historyModel.initModel(True)
Why this scored 15/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.