commit 241873f0a4bcf907f5a4ae3bba087355a5f14c34
parent 65b88dca8644b6a1be819029d81e3c8b83b11bc0
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:
4 files changed, 53 insertions(+), 33 deletions(-)
diff --git a/electrum/address_synchronizer.py b/electrum/address_synchronizer.py
@@ -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
@@ -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
@@ -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()
@@ -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:
diff --git a/electrum/gui/stdio.py b/electrum/gui/stdio.py
@@ -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:
@@ -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")))
diff --git a/electrum/gui/text.py b/electrum/gui/text.py
@@ -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:
@@ -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):
diff --git a/electrum/wallet.py b/electrum/wallet.py
@@ -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):
@@ -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
@@ -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