tFactorize history export code used in GUI and command line. Add options to export history limits and exchange rate. Closes: #1752, #2604, Replaces: #2715, 3724 - electrum - Electrum Bitcoin wallet
 (HTM) git clone https://git.parazyd.org/electrum
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
       ---
 (DIR) commit 3f954a8b3d39d2cb45927371a856802104f9182c
 (DIR) parent 670194b92037dba020ef8b6bfe5922560c7f5b26
 (HTM) Author: ThomasV <thomasv@electrum.org>
       Date:   Fri,  9 Feb 2018 15:28:28 +0100
       
       Factorize history export code used in GUI and command line.
       Add options to export history limits and exchange rate.
       Closes: #1752, #2604,
       Replaces: #2715, 3724
       
       Diffstat:
         M gui/qt/main_window.py               |      27 ++++-----------------------
         M lib/commands.py                     |      52 ++++++++-----------------------
         M lib/wallet.py                       |      51 +++++++++++++++++++++++++++++++
       
       3 files changed, 68 insertions(+), 62 deletions(-)
       ---
 (DIR) diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -2494,32 +2494,13 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                    plt.show()
        
            def do_export_history(self, wallet, fileName, is_csv):
       -        history = wallet.get_history()
       +        history = wallet.export_history(fx=self.fx)
                lines = []
                for item in history:
       -            tx_hash, height, confirmations, timestamp, value, balance = item
       -            if height>0:
       -                if timestamp is not None:
       -                    time_string = format_time(timestamp)
       -                else:
       -                    time_string = _("unverified")
       -            else:
       -                time_string = _("unconfirmed")
       -
       -            if value is not None:
       -                value_string = format_satoshis(value, True)
       -            else:
       -                value_string = '--'
       -
       -            if tx_hash:
       -                label = wallet.get_label(tx_hash)
       -            else:
       -                label = ""
       -
                    if is_csv:
       -                lines.append([tx_hash, label, confirmations, value_string, time_string])
       +                lines.append([item['txid'], item.get('label', ''), item['confirmations'], item['value'], item['date']])
                    else:
       -                lines.append({'txid':tx_hash, 'date':"%16s"%time_string, 'label':label, 'value':value_string})
       +                lines.append(item)
        
                with open(fileName, "w+") as f:
                    if is_csv:
       t@@ -2529,7 +2510,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                            transaction.writerow(line)
                    else:
                        import json
       -                f.write(json.dumps(lines, indent = 4))
       +                f.write(json.dumps(lines, indent=4))
        
            def sweep_key_dialog(self):
                d = WindowModalDialog(self, title=_('Sweep private keys'))
 (DIR) diff --git a/lib/commands.py b/lib/commands.py
       t@@ -440,46 +440,16 @@ class Commands:
                return tx.as_dict()
        
            @command('w')
       -    def history(self):
       +    def history(self, year=None, show_addresses=False, show_fiat=False):
                """Wallet history. Returns the transaction history of your wallet."""
       -        balance = 0
       -        out = []
       -        for item in self.wallet.get_history():
       -            tx_hash, height, conf, timestamp, value, balance = item
       -            if timestamp:
       -                date = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3]
       -            else:
       -                date = "----"
       -            label = self.wallet.get_label(tx_hash)
       -            tx = self.wallet.transactions.get(tx_hash)
       -            tx.deserialize()
       -            input_addresses = []
       -            output_addresses = []
       -            for x in tx.inputs():
       -                if x['type'] == 'coinbase': continue
       -                addr = x.get('address')
       -                if addr == None: continue
       -                if addr == "(pubkey)":
       -                    prevout_hash = x.get('prevout_hash')
       -                    prevout_n = x.get('prevout_n')
       -                    _addr = self.wallet.find_pay_to_pubkey_address(prevout_hash, prevout_n)
       -                    if _addr:
       -                        addr = _addr
       -                input_addresses.append(addr)
       -            for addr, v in tx.get_outputs():
       -                output_addresses.append(addr)
       -            out.append({
       -                'txid': tx_hash,
       -                'timestamp': timestamp,
       -                'date': date,
       -                'input_addresses': input_addresses,
       -                'output_addresses': output_addresses,
       -                'label': label,
       -                'value': str(Decimal(value)/COIN) if value is not None else None,
       -                'height': height,
       -                'confirmations': conf
       -            })
       -        return out
       +        kwargs = {'show_addresses': show_addresses}
       +        if year:
       +            import time
       +            start_date = datetime.datetime(year, 1, 1)
       +            end_date = datetime.datetime(year+1, 1, 1)
       +            kwargs['from_timestamp'] = time.mktime(start_date.timetuple())
       +            kwargs['to_timestamp'] = time.mktime(end_date.timetuple())
       +        return self.wallet.export_history(**kwargs)
        
            @command('w')
            def setlabel(self, key, label):
       t@@ -736,6 +706,9 @@ command_options = {
            'pending':     (None, "Show only pending requests."),
            'expired':     (None, "Show only expired requests."),
            'paid':        (None, "Show only paid requests."),
       +    'show_addresses': (None, "Show input and output addresses"),
       +    'show_fiat':   (None, "Show fiat value of transactions"),
       +    'year':        (None, "Show history for a given year"),
        }
        
        
       t@@ -746,6 +719,7 @@ arg_types = {
            'num': int,
            'nbits': int,
            'imax': int,
       +    'year': int,
            'entropy': int,
            'tx': tx_from_str,
            'pubkeys': json_loads,
 (DIR) diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -914,6 +914,57 @@ class Abstract_Wallet(PrintError):
        
                return h2
        
       +    def export_history(self, domain=None, from_timestamp=None, to_timestamp=None, fx=None, show_addresses=False):
       +        from decimal import Decimal
       +        from .util import format_time, format_satoshis, timestamp_to_datetime
       +        h = self.get_history(domain)
       +        out = []
       +        for tx_hash, height, conf, timestamp, value, balance in h:
       +            if from_timestamp and timestamp < from_timestamp:
       +                continue
       +            if to_timestamp and timestamp >= to_timestamp:
       +                continue
       +            item = {
       +                'txid':tx_hash,
       +                'height':height,
       +                'confirmations':conf,
       +                'timestamp':timestamp,
       +                'value': format_satoshis(value, True) if value is not None else '--',
       +                'balance': format_satoshis(balance)
       +            }
       +            if item['height']>0:
       +                date_str = format_time(timestamp) if timestamp is not None else _("unverified")
       +            else:
       +                date_str = _("unconfirmed")
       +            item['date'] = date_str
       +            item['label'] = self.get_label(tx_hash)
       +            if show_addresses:
       +                tx = self.transactions.get(tx_hash)
       +                tx.deserialize()
       +                input_addresses = []
       +                output_addresses = []
       +                for x in tx.inputs():
       +                    if x['type'] == 'coinbase': continue
       +                    addr = x.get('address')
       +                    if addr == None: continue
       +                    if addr == "(pubkey)":
       +                        prevout_hash = x.get('prevout_hash')
       +                        prevout_n = x.get('prevout_n')
       +                        _addr = self.wallet.find_pay_to_pubkey_address(prevout_hash, prevout_n)
       +                        if _addr:
       +                            addr = _addr
       +                    input_addresses.append(addr)
       +                for addr, v in tx.get_outputs():
       +                    output_addresses.append(addr)
       +                item['input_addresses'] = input_addresses
       +                item['output_addresses'] = output_addresses
       +            if fx is not None:
       +                date = timestamp_to_datetime(time.time() if conf <= 0 else timestamp)
       +                item['fiat_value'] = fx.historical_value_str(value, date)
       +                item['fiat_balance'] = fx.historical_value_str(balance, date)
       +            out.append(item)
       +        return out
       +
            def get_label(self, tx_hash):
                label = self.labels.get(tx_hash, '')
                if label is '':