qt: fix: addresses tab broken for imported watchonly wallets
What changed, and why it matters
This commit fixes a bug where the 'Addresses' tab in Electrum's Qt GUI would crash or fail to display for a specific type of wallet: imported watch-only wallets. These wallets contain addresses you are monitoring but do not own the private keys for. The crash happened because the code assumed every address had an associated public key/index, but watch-only imported addresses do not. The fix makes the sorting function safely handle a missing index by treating it as an empty string. There is no security vulnerability here—just a user-interface regression.
No security action required. Treat as a normal bug-fix release. Users of imported watch-only wallets should update to obtain the fix for the Addresses tab crash.
Security signals we found
No security-relevant signals present
Bug is a UI regression causing a crash in a non-privileged view
No input from untrusted sources is processed unsafely
No cryptographic, authentication, or authorization changes
Evidence from the diff
The patch resolves a regression introduced by PR #10376. In wallet.py, Imported_Wallet.get_address_index() can return None for imported watch-only addresses because no public key is stored. In address_list.py, address_index_as_sortable_key() previously assumed address_index was always a str or tuple, so passing None caused a TypeError when formatting. The fix changes the helper to a static method, accepts Optional[AddressIndexGeneric], and returns an empty string for None. This restores the Addresses tab for imported watchonly wallets.
Changed components
electrum/gui/qt/address_list.pyelectrum/wallet.pyQt GUI Addresses tabImported watch-only walletsInspect captured patch +13 / −4
diff --git a/electrum/gui/qt/address_list.py b/electrum/gui/qt/address_list.py
index 80e5f09..8836511 100644
--- a/electrum/gui/qt/address_list.py
+++ b/electrum/gui/qt/address_list.py
@@ -25,7 +25,7 @@
import enum
from enum import IntEnum
-from typing import TYPE_CHECKING
+from typing import TYPE_CHECKING, Optional
from PyQt6.QtCore import Qt, QPersistentModelIndex, QModelIndex
from PyQt6.QtGui import QStandardItemModel, QStandardItem, QFont
@@ -244,8 +244,14 @@ class AddressList(MyTreeView):
# update counter
self.num_addr_label.setText(_("{} addresses").format(num_shown))
- def address_index_as_sortable_key(self, address_index: 'AddressIndexGeneric'):
- return address_index if isinstance(address_index, str) else ''.join(f'{i:08x}' for i in address_index)
+ @staticmethod
+ def address_index_as_sortable_key(address_index: Optional['AddressIndexGeneric']) -> str:
+ if isinstance(address_index, str): # pubkey hex
+ return address_index
+ elif address_index is None:
+ return ""
+ else:
+ return "".join(f"{i:08x}" for i in address_index)
def refresh_row(self, key, row):
assert row is not None
diff --git a/electrum/wallet.py b/electrum/wallet.py
index 0ab2343..247dfa9 100644
--- a/electrum/wallet.py
+++ b/electrum/wallet.py
@@ -3784,7 +3784,10 @@ class Imported_Wallet(Simple_Wallet):
return self.db.has_imported_address(address)
def get_address_index(self, address) -> Optional[str]:
- # returns None if address is not mine
+ # Return pubkey for address if we know it.
+ # If we don't know it, return None, which might happen:
+ # - if address is not is_mine
+ # - if this is an "imported address", we don't have the pubkey for. (watch-only imported wallet)
return self.get_public_key(address)
def get_address_path_str(self, address):
Why this scored 18/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.