tQt addresses list: show derivation path in tooltip (also addr dialog) - electrum - Electrum Bitcoin wallet (HTM) git clone https://git.parazyd.org/electrum (DIR) Log (DIR) Files (DIR) Refs (DIR) Submodules --- (DIR) commit d8180c678b9f476da9807556debf1974284e3825 (DIR) parent 09b3c8052982dc1fdcada054db0665c097743e57 (HTM) Author: SomberNight <somber.night@protonmail.com> Date: Sun, 1 Mar 2020 05:45:15 +0100 Qt addresses list: show derivation path in tooltip (also addr dialog) related: #5641 Diffstat: M electrum/address_synchronizer.py | 2 +- M electrum/gui/qt/address_dialog.py | 8 ++++++++ M electrum/gui/qt/address_list.py | 3 +++ M electrum/gui/qt/util.py | 4 ++-- M electrum/wallet.py | 18 +++++++++++++++++- 5 files changed, 31 insertions(+), 4 deletions(-) --- (DIR) diff --git a/electrum/address_synchronizer.py b/electrum/address_synchronizer.py t@@ -777,7 +777,7 @@ class AddressSynchronizer(Logger): return sum([v for height, v, is_cb in received.values()]) @with_local_height_cached - def get_addr_balance(self, address, *, excluded_coins: Set[str] = None): + def get_addr_balance(self, address, *, excluded_coins: Set[str] = None) -> Tuple[int, int, int]: """Return the balance of a bitcoin address: confirmed and matured, unconfirmed, unmatured """ (DIR) diff --git a/electrum/gui/qt/address_dialog.py b/electrum/gui/qt/address_dialog.py t@@ -98,6 +98,14 @@ class AddressDialog(WindowModalDialog): witness_e.addCopyButton(self.app) vbox.addWidget(witness_e) + address_path_str = self.wallet.get_address_path_str(address) + if address_path_str: + vbox.addWidget(QLabel(_("Derivation path") + ':')) + der_path_e = ButtonsLineEdit(address_path_str) + der_path_e.addCopyButton(self.app) + der_path_e.setReadOnly(True) + vbox.addWidget(der_path_e) + vbox.addWidget(QLabel(_("History"))) addr_hist_model = AddressHistoryModel(self.parent, self.address) self.hw = HistoryList(self.parent, addr_hist_model) (DIR) diff --git a/electrum/gui/qt/address_list.py b/electrum/gui/qt/address_list.py t@@ -187,6 +187,9 @@ class AddressList(MyTreeView): address_item[self.Columns.TYPE].setText(_('receiving')) address_item[self.Columns.TYPE].setBackground(ColorScheme.GREEN.as_color(True)) address_item[self.Columns.LABEL].setData(address, Qt.UserRole) + address_path_str = self.wallet.get_address_path_str(address) + if address_path_str is not None: + address_item[self.Columns.TYPE].setToolTip(address_path_str) # setup column 1 if self.wallet.is_frozen_address(address): address_item[self.Columns.ADDRESS].setBackground(ColorScheme.BLUE.as_color(True)) (DIR) diff --git a/electrum/gui/qt/util.py b/electrum/gui/qt/util.py t@@ -463,7 +463,7 @@ def filename_field(parent, config, defaultname, select_msg): return vbox, filename_e, b1 class ElectrumItemDelegate(QStyledItemDelegate): - def __init__(self, tv): + def __init__(self, tv: 'MyTreeView'): super().__init__(tv) self.tv = tv self.opened = None t@@ -529,7 +529,7 @@ class MyTreeView(QTreeView): items = self.selectionModel().selectedIndexes() return list(x for x in items if x.column() == column) - def current_item_user_role(self, col) -> Optional[QStandardItem]: + def current_item_user_role(self, col) -> Any: idx = self.selectionModel().currentIndex() idx = idx.sibling(idx.row(), col) item = self.model().itemFromIndex(idx) (DIR) diff --git a/electrum/wallet.py b/electrum/wallet.py t@@ -44,7 +44,7 @@ from abc import ABC, abstractmethod import itertools from .i18n import _ -from .bip32 import BIP32Node +from .bip32 import BIP32Node, convert_bip32_intpath_to_strpath from .crypto import sha256 from .util import (NotEnoughFunds, UserCancelled, profiler, format_satoshis, format_fee_satoshis, NoDynamicFeeEstimates, t@@ -442,6 +442,13 @@ class Abstract_Wallet(AddressSynchronizer, ABC): pass @abstractmethod + def get_address_path_str(self, address: str) -> Optional[str]: + """Returns derivation path str such as "m/0/5" to address, + or None if not applicable. + """ + pass + + @abstractmethod def get_redeem_script(self, address: str) -> Optional[str]: pass t@@ -2029,6 +2036,9 @@ class Imported_Wallet(Simple_Wallet): # returns None if address is not mine return self.get_public_key(address) + def get_address_path_str(self, address): + return None + def get_public_key(self, address) -> Optional[str]: x = self.db.get_imported_address(address) return x.get('pubkey') if x else None t@@ -2252,6 +2262,12 @@ class Deterministic_Wallet(Abstract_Wallet): def get_address_index(self, address) -> Optional[Sequence[int]]: return self.db.get_address_index(address) or self._ephemeral_addr_to_addr_index.get(address) + def get_address_path_str(self, address): + intpath = self.get_address_index(address) + if intpath is None: + return None + return convert_bip32_intpath_to_strpath(intpath) + def _learn_derivation_path_for_address_from_txinout(self, txinout, address): for ks in self.get_keystores(): pubkey, der_suffix = ks.find_my_pubkey_in_txinout(txinout, only_der_suffix=True)