taddress_synchronizer.get_history now returns HistoryItem(NamedTuple)s - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 241873f0a4bcf907f5a4ae3bba087355a5f14c34 DIR parent 65b88dca8644b6a1be819029d81e3c8b83b11bc0 HTML Author: SomberNight <somber.night@protonmail.com> Date: Thu, 12 Sep 2019 04:05:57 +0200 address_synchronizer.get_history now returns HistoryItem(NamedTuple)s Diffstat: M electrum/address_synchronizer.py | 18 +++++++++++++++--- M electrum/gui/stdio.py | 11 ++++++----- M electrum/gui/text.py | 11 ++++++----- M electrum/wallet.py | 46 +++++++++++++++++-------------- 4 files changed, 53 insertions(+), 33 deletions(-) --- DIR diff --git a/electrum/address_synchronizer.py b/electrum/address_synchronizer.py t@@ -26,7 +26,7 @@ import threading import asyncio import itertools from collections import defaultdict -from typing import TYPE_CHECKING, Dict, Optional, Set, Tuple +from typing import TYPE_CHECKING, Dict, Optional, Set, Tuple, NamedTuple, Sequence from . import bitcoin from .bitcoin import COINBASE_MATURITY, TYPE_ADDRESS, TYPE_PUBKEY t@@ -57,6 +57,14 @@ class UnrelatedTransactionException(AddTransactionException): return _("Transaction is unrelated to this wallet.") +class HistoryItem(NamedTuple): + txid: str + tx_mined_status: TxMinedInfo + delta: Optional[int] + fee: Optional[int] + balance: Optional[int] + + class AddressSynchronizer(Logger): """ inherited by wallet t@@ -418,7 +426,7 @@ class AddressSynchronizer(Logger): return f @with_local_height_cached - def get_history(self, domain=None): + def get_history(self, domain=None) -> Sequence[HistoryItem]: # get domain if domain is None: domain = self.get_addresses() t@@ -448,7 +456,11 @@ class AddressSynchronizer(Logger): balance = c + u + x h2 = [] for tx_hash, tx_mined_status, delta, fee in history: - h2.append((tx_hash, tx_mined_status, delta, fee, balance)) + h2.append(HistoryItem(txid=tx_hash, + tx_mined_status=tx_mined_status, + delta=delta, + fee=fee, + balance=balance)) if balance is None or delta is None: balance = None else: DIR diff --git a/electrum/gui/stdio.py b/electrum/gui/stdio.py t@@ -94,9 +94,9 @@ class ElectrumGui: + "%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s" messages = [] - for tx_hash, tx_mined_status, delta, balance in reversed(self.wallet.get_history()): - if tx_mined_status.conf: - timestamp = tx_mined_status.timestamp + for hist_item in reversed(self.wallet.get_history()): + if hist_item.tx_mined_status.conf: + timestamp = hist_item.tx_mined_status.timestamp try: time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3] except Exception: t@@ -104,8 +104,9 @@ class ElectrumGui: else: time_str = 'unconfirmed' - label = self.wallet.get_label(tx_hash) - messages.append( format_str%( time_str, label, format_satoshis(delta, whitespaces=True), format_satoshis(balance, whitespaces=True) ) ) + label = self.wallet.get_label(hist_item.txid) + messages.append(format_str % (time_str, label, format_satoshis(delta, whitespaces=True), + format_satoshis(hist_item.balance, whitespaces=True))) self.print_list(messages[::-1], format_str%( _("Date"), _("Description"), _("Amount"), _("Balance"))) DIR diff --git a/electrum/gui/text.py b/electrum/gui/text.py t@@ -117,9 +117,9 @@ class ElectrumGui: b = 0 self.history = [] - for tx_hash, tx_mined_status, value, balance in self.wallet.get_history(): - if tx_mined_status.conf: - timestamp = tx_mined_status.timestamp + for hist_item in self.wallet.get_history(): + if hist_item.tx_mined_status.conf: + timestamp = hist_item.tx_mined_status.timestamp try: time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3] except Exception: t@@ -127,10 +127,11 @@ class ElectrumGui: else: time_str = 'unconfirmed' - label = self.wallet.get_label(tx_hash) + label = self.wallet.get_label(hist_item.txid) if len(label) > 40: label = label[0:37] + '...' - self.history.append( format_str%( time_str, label, format_satoshis(value, whitespaces=True), format_satoshis(balance, whitespaces=True) ) ) + self.history.append(format_str % (time_str, label, format_satoshis(hist_item.value, whitespaces=True), + format_satoshis(hist_item.balance, whitespaces=True))) def print_balance(self): DIR diff --git a/electrum/wallet.py b/electrum/wallet.py t@@ -482,26 +482,27 @@ class Abstract_Wallet(AddressSynchronizer): # we also assume that block timestamps are monotonic (which is false...!) h = self.get_history(domain) balance = 0 - for tx_hash, tx_mined_status, value, fee, balance in h: - if tx_mined_status.timestamp is None or tx_mined_status.timestamp > target_timestamp: - return balance - value + for hist_item in h: + balance = hist_item.balance + if hist_item.tx_mined_status.timestamp is None or hist_item.tx_mined_status.timestamp > target_timestamp: + return balance - hist_item.delta # return last balance return balance def get_onchain_history(self): - for tx_hash, tx_mined_status, value, fee, balance in self.get_history(): + for hist_item in self.get_history(): yield { - 'txid': tx_hash, - 'fee_sat': fee, - 'height': tx_mined_status.height, - 'confirmations': tx_mined_status.conf, - 'timestamp': tx_mined_status.timestamp, - 'incoming': True if value>0 else False, - 'bc_value': Satoshis(value), - 'bc_balance': Satoshis(balance), - 'date': timestamp_to_datetime(tx_mined_status.timestamp), - 'label': self.get_label(tx_hash), - 'txpos_in_block': tx_mined_status.txpos, + 'txid': hist_item.tx_mined_status, + 'fee_sat': hist_item.fee, + 'height': hist_item.tx_mined_status.height, + 'confirmations': hist_item.tx_mined_status.conf, + 'timestamp': hist_item.tx_mined_status.timestamp, + 'incoming': True if hist_item.delta>0 else False, + 'bc_value': Satoshis(hist_item.delta), + 'bc_balance': Satoshis(hist_item.balance), + 'date': timestamp_to_datetime(hist_item.tx_mined_status.timestamp), + 'label': self.get_label(hist_item.txid), + 'txpos_in_block': hist_item.tx_mined_status.txpos, } def save_invoice(self, invoice): t@@ -757,13 +758,18 @@ class Abstract_Wallet(AddressSynchronizer): def get_unconfirmed_base_tx_for_batching(self) -> Optional[Transaction]: candidate = None - for tx_hash, tx_mined_status, delta, fee, balance in self.get_history(): + for hist_item in self.get_history(): # tx should not be mined yet - if tx_mined_status.conf > 0: continue + if hist_item.tx_mined_status.conf > 0: continue + # conservative future proofing of code: only allow known unconfirmed types + if hist_item.tx_mined_status.height not in (TX_HEIGHT_UNCONFIRMED, + TX_HEIGHT_UNCONF_PARENT, + TX_HEIGHT_LOCAL): + continue # tx should be "outgoing" from wallet - if delta >= 0: + if hist_item.delta >= 0: continue - tx = self.db.get_transaction(tx_hash) + tx = self.db.get_transaction(hist_item.txid) if not tx: continue # is_mine outputs should not be spent yet t@@ -776,7 +782,7 @@ class Abstract_Wallet(AddressSynchronizer): if not all([self.is_mine(self.get_txin_address(txin)) for txin in tx.inputs()]): continue # prefer txns already in mempool (vs local) - if tx_mined_status.height == TX_HEIGHT_LOCAL: + if hist_item.tx_mined_status.height == TX_HEIGHT_LOCAL: candidate = tx continue # tx must have opted-in for RBF