tshow unmatured coins in status bar. fixes #1163 - electrum - Electrum Bitcoin wallet
 (HTM) git clone https://git.parazyd.org/electrum
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
       ---
 (DIR) commit 687cc7783f4f2f4165d67f8633146f71466651a3
 (DIR) parent 4bce96526b6876638dbf70a486f175097b1f6e72
 (HTM) Author: ThomasV <thomasv@gitorious>
       Date:   Tue,  5 May 2015 20:52:14 +0200
       
       show unmatured coins in status bar. fixes #1163
       
       Diffstat:
         M gui/android.py                      |       7 +++++--
         M gui/gtk.py                          |      13 ++++++++-----
         M gui/qt/lite_window.py               |       4 ++--
         M gui/qt/main_window.py               |      27 +++++++++++++++------------
         M gui/stdio.py                        |       9 ++++++---
         M gui/text.py                         |       9 ++++++---
         M lib/commands.py                     |      12 +++++++-----
         M lib/wallet.py                       |      45 +++++++++++++++++--------------
       
       8 files changed, 74 insertions(+), 52 deletions(-)
       ---
 (DIR) diff --git a/gui/android.py b/gui/android.py
       t@@ -410,9 +410,12 @@ def update_layout():
            elif not wallet.up_to_date:
                text = "Synchronizing..."
            else:
       -        c, u = wallet.get_balance()
       +        c, u, x = wallet.get_balance()
                text = "Balance:"+format_satoshis(c) 
       -        if u : text += '   [' + format_satoshis(u,True).strip() + ']'
       +        if u:
       +            text += '   [' + format_satoshis(u,True).strip() + ']'
       +        if x:
       +            text += '   [' + format_satoshis(x,True).strip() + ']'
        
        
            # vibrate if status changed
 (DIR) diff --git a/gui/gtk.py b/gui/gtk.py
       t@@ -1122,9 +1122,12 @@ class ElectrumWindow:
                        text = "Synchronizing..."
                    else:
                        self.status_image.set_from_stock(Gtk.STOCK_YES, Gtk.IconSize.MENU)
       -                c, u = self.wallet.get_balance()
       -                text =  "Balance: %s "%( format_satoshis(c,False,self.num_zeros) )
       -                if u: text +=  "[%s unconfirmed]"%( format_satoshis(u,True,self.num_zeros).strip() )
       +                c, u, x = self.wallet.get_balance()
       +                text = "Balance: %s "%(format_satoshis(c, False, self.num_zeros))
       +                if u:
       +                    text += "[%s unconfirmed]"%(format_satoshis(u, True, self.num_zeros).strip())
       +                if x:
       +                    text += "[%s unmatured]"%(format_satoshis(x, True, self.num_zeros).strip())
                else:
                    self.status_image.set_from_stock(Gtk.STOCK_NO, Gtk.IconSize.MENU)
                    self.network_button.set_tooltip_text("Not connected.")
       t@@ -1148,13 +1151,13 @@ class ElectrumWindow:
                    if self.wallet.is_change(address): Type = "C"
                    if address in self.wallet.imported_keys.keys():
                        Type = "I"
       -            c, u = self.wallet.get_addr_balance(address)
       +            c, u, x = self.wallet.get_addr_balance(address)
                    if address in self.wallet.frozen_addresses: Type = Type + "F"
                    label = self.wallet.labels.get(address)
                    h = self.wallet.history.get(address,[])
                    n = len(h)
                    tx = "0" if n==0 else "%d"%n
       -            self.recv_list.append((address, label, tx, format_satoshis(c,False,self.num_zeros), Type ))
       +            self.recv_list.append((address, label, tx, format_satoshis(c+u+x, False, self.num_zeros), Type ))
        
            def update_sending_tab(self):
                self.addressbook_list.clear()
 (DIR) diff --git a/gui/qt/lite_window.py b/gui/qt/lite_window.py
       t@@ -850,8 +850,8 @@ class MiniDriver(QObject):
                self.window.activate()
        
            def update_balance(self):
       -        conf_balance, unconf_balance = self.g.wallet.get_balance()
       -        balance = D(conf_balance + unconf_balance)
       +        conf_balance, unconf_balance, x = self.g.wallet.get_balance()
       +        balance = D(conf_balance + unconf_balance + x)
                self.window.set_balances(balance)
        
            def update_completions(self):
 (DIR) diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -525,10 +525,12 @@ class ElectrumWindow(QMainWindow):
                        text = _("Server is lagging (%d blocks)"%server_lag)
                        icon = QIcon(":icons/status_lagging.png")
                    else:
       -                c, u = self.wallet.get_account_balance(self.current_account)
       -                text =  _( "Balance" ) + ": %s "%( self.format_amount(c) ) + self.base_unit()
       -                if u: text +=  " [%s unconfirmed]"%( self.format_amount(u,True).strip() )
       -
       +                c, u, x = self.wallet.get_account_balance(self.current_account)
       +                text =  _("Balance" ) + ": %s "%(self.format_amount(c)) + self.base_unit()
       +                if u:
       +                    text +=  " [%s unconfirmed]"%(self.format_amount(u, True).strip())
       +                if x:
       +                    text +=  " [%s unmatured]"%(self.format_amount(x, True).strip())
                        # append fiat balance and price from exchange rate plugin
                        r = {}
                        run_hook('get_fiat_status_text', c+u, r)
       t@@ -958,8 +960,9 @@ class ElectrumWindow(QMainWindow):
                        palette = QPalette()
                        palette.setColor(self.amount_e.foregroundRole(), QColor('red'))
                        text = _( "Not enough funds" )
       -                c, u = self.wallet.get_frozen_balance()
       -                if c+u: text += ' (' + self.format_amount(c+u).strip() + ' ' + self.base_unit() + ' ' +_("are frozen") + ')'
       +                c, u, x = self.wallet.get_frozen_balance()
       +                if c+u+x:
       +                    text += ' (' + self.format_amount(c+u+x).strip() + ' ' + self.base_unit() + ' ' +_("are frozen") + ')'
                    self.statusBar().showMessage(text)
                    self.amount_e.setPalette(palette)
                    self.fee_e.setPalette(palette)
       t@@ -1030,7 +1033,7 @@ class ElectrumWindow(QMainWindow):
                menu.exec_(self.from_list.viewport().mapToGlobal(position))
        
            def set_pay_from(self, domain = None):
       -        self.pay_from = [] if domain == [] else self.wallet.get_unspent_coins(domain)
       +        self.pay_from = [] if domain == [] else self.wallet.get_spendable_coins(domain)
                self.redraw_from_list()
        
            def redraw_from_list(self):
       t@@ -1438,7 +1441,7 @@ class ElectrumWindow(QMainWindow):
                    domain = self.wallet.get_account_addresses(self.current_account)
                    for i in self.wallet.frozen_addresses:
                        if i in domain: domain.remove(i)
       -            return self.wallet.get_unspent_coins(domain)
       +            return self.wallet.get_spendable_coins(domain)
        
        
            def send_from_addresses(self, addrs):
       t@@ -1554,8 +1557,8 @@ class ElectrumWindow(QMainWindow):
                for k, account in account_items:
                    if len(accounts) > 1:
                        name = self.wallet.get_account_name(k)
       -                c, u = self.wallet.get_account_balance(k)
       -                account_item = QTreeWidgetItem( [ name, '', self.format_amount(c+u), ''] )
       +                c, u, x = self.wallet.get_account_balance(k)
       +                account_item = QTreeWidgetItem([ name, '', self.format_amount(c + u + x), ''])
                        l.addTopLevelItem(account_item)
                        account_item.setExpanded(self.accounts_expanded.get(k, True))
                        account_item.setData(0, Qt.UserRole, k)
       t@@ -1577,8 +1580,8 @@ class ElectrumWindow(QMainWindow):
                        for address in addr_list:
                            num, is_used = self.wallet.is_used(address)
                            label = self.wallet.labels.get(address,'')
       -                    c, u = self.wallet.get_addr_balance(address)
       -                    balance = self.format_amount(c + u)
       +                    c, u, x = self.wallet.get_addr_balance(address)
       +                    balance = self.format_amount(c + u + x)
                            item = QTreeWidgetItem( [ address, label, balance, "%d"%num] )
                            item.setFont(0, QFont(MONOSPACE_FONT))
                            item.setData(0, Qt.UserRole, address)
 (DIR) diff --git a/gui/stdio.py b/gui/stdio.py
       t@@ -124,9 +124,12 @@ class ElectrumGui:
                    if not self.wallet.up_to_date:
                        msg = _( "Synchronizing..." )
                    else: 
       -                c, u =  self.wallet.get_balance()
       -                msg = _("Balance")+": %f  "%(Decimal( c ) / 100000000)
       -                if u: msg += "  [%f unconfirmed]"%(Decimal( u ) / 100000000)
       +                c, u, x =  self.wallet.get_balance()
       +                msg = _("Balance")+": %f  "%(Decimal(c) / 100000000)
       +                if u:
       +                    msg += "  [%f unconfirmed]"%(Decimal(u) / 100000000)
       +                if x:
       +                    msg += "  [%f unmatured]"%(Decimal(x) / 100000000)
                else:
                        msg = _( "Not connected" )
                    
 (DIR) diff --git a/gui/text.py b/gui/text.py
       t@@ -132,9 +132,12 @@ class ElectrumGui:
                    if not self.wallet.up_to_date:
                        msg = _("Synchronizing...")
                    else: 
       -                c, u =  self.wallet.get_balance()
       -                msg = _("Balance")+": %f  "%(Decimal( c ) / 100000000)
       -                if u: msg += "  [%f unconfirmed]"%(Decimal( u ) / 100000000)
       +                c, u, x =  self.wallet.get_balance()
       +                msg = _("Balance")+": %f  "%(Decimal(c) / 100000000)
       +                if u:
       +                    msg += "  [%f unconfirmed]"%(Decimal(u) / 100000000)
       +                if x:
       +                    msg += "  [%f unmatured]"%(Decimal(x) / 100000000)
                else:
                    msg = _("Not connected")
                    
 (DIR) diff --git a/lib/commands.py b/lib/commands.py
       t@@ -231,12 +231,14 @@ class Commands:
        
            def getbalance(self, account= None):
                if account is None:
       -            c, u = self.wallet.get_balance()
       +            c, u, x = self.wallet.get_balance()
                else:
       -            c, u = self.wallet.get_account_balance(account)
       -
       -        out = { "confirmed": str(Decimal(c)/100000000) }
       -        if u: out["unconfirmed"] = str(Decimal(u)/100000000)
       +            c, u, x = self.wallet.get_account_balance(account)
       +        out = {"confirmed": str(Decimal(c)/100000000)}
       +        if u:
       +            out["unconfirmed"] = str(Decimal(u)/100000000)
       +        if x:
       +            out["unmatured"] = str(Decimal(x)/100000000)
                return out
        
            def getaddressbalance(self, addr):
 (DIR) diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -480,19 +480,21 @@ class Abstract_Wallet(object):
                coins, spent = self.get_addr_io(address)
                for txi in spent:
                    coins.pop(txi)
       -        return coins.items()
       +        return coins
        
            # return the total amount ever received by an address
            def get_addr_received(self, address):
                received, sent = self.get_addr_io(address)
                return sum([v for height, v, is_cb in received.values()])
        
       -    # return the confirmed balance and pending (unconfirmed) balance change of a bitcoin address
       +    # return the balance of a bitcoin address: confirmed and matured, unconfirmed, unmatured
            def get_addr_balance(self, address):
                received, sent = self.get_addr_io(address)
       -        c = u = 0
       +        c = u = x = 0
                for txo, (tx_height, v, is_cb) in received.items():
       -            if tx_height > 0:
       +            if is_cb and tx_height + COINBASE_MATURITY > self.network.get_local_height():
       +                x += v
       +            elif tx_height > 0:
                        c += v
                    else:
                        u += v
       t@@ -501,17 +503,19 @@ class Abstract_Wallet(object):
                            c -= v
                        else:
                            u -= v
       -        return c, u
       +        return c, u, x
        
        
       -    def get_unspent_coins(self, domain=None):
       +    def get_spendable_coins(self, domain=None):
                coins = []
                if domain is None:
                    domain = self.addresses(True)
                for addr in domain:
                    c = self.get_addr_utxo(addr)
       -            for txo, v in c:
       +            for txo, v in c.items():
                        tx_height, value, is_cb = v
       +                if is_cb and tx_height + COINBASE_MATURITY > self.network.get_local_height():
       +                    continue
                        prevout_hash, prevout_n = txo.split(':')
                        output = {
                            'address':addr,
       t@@ -564,13 +568,15 @@ class Abstract_Wallet(object):
                return self.get_balance(self.frozen_addresses)
        
            def get_balance(self, domain=None):
       -        if domain is None: domain = self.addresses(True)
       -        cc = uu = 0
       +        if domain is None:
       +            domain = self.addresses(True)
       +        cc = uu = xx = 0
                for addr in domain:
       -            c, u = self.get_addr_balance(addr)
       +            c, u, x = self.get_addr_balance(addr)
                    cc += c
                    uu += u
       -        return cc, uu
       +            xx += x
       +        return cc, uu, xx
        
            def set_fee(self, fee):
                if self.fee_per_kb != fee:
       t@@ -597,7 +603,7 @@ class Abstract_Wallet(object):
                            return addr
        
            def add_transaction(self, tx_hash, tx, tx_height):
       -        is_coinbase = tx.inputs[0].get('prevout_hash') == '0'*64
       +        is_coinbase = tx.inputs[0].get('is_coinbase') == True
                with self.transaction_lock:
                    # add inputs
                    self.txi[tx_hash] = d = {}
       t@@ -734,8 +740,8 @@ class Abstract_Wallet(object):
                history.reverse()
        
                # 3. add balance
       -        c, u = self.get_balance(domain)
       -        balance = c + u
       +        c, u, x = self.get_balance(domain)
       +        balance = c + u + x
                h2 = []
                for item in history:
                    tx_hash, conf, delta, timestamp = item
       t@@ -793,16 +799,15 @@ class Abstract_Wallet(object):
                    if domain is None:
                        domain = self.addresses(True)
                    for i in self.frozen_addresses:
       -                if i in domain: domain.remove(i)
       -            coins = self.get_unspent_coins(domain)
       +                if i in domain:
       +                    domain.remove(i)
       +            coins = self.get_spendable_coins(domain)
        
       -        amount = sum( map(lambda x:x[2], outputs) )
       +        amount = sum(map(lambda x:x[2], outputs))
                total = fee = 0
                inputs = []
                tx = Transaction.from_io(inputs, outputs)
                for item in coins:
       -            if item.get('coinbase') and item.get('height') + COINBASE_MATURITY > self.network.get_local_height():
       -                continue
                    v = item.get('value')
                    total += v
                    self.add_input_info(item)
       t@@ -1066,7 +1071,7 @@ class Abstract_Wallet(object):
        
            def is_used(self, address):
                h = self.history.get(address,[])
       -        c, u = self.get_addr_balance(address)
       +        c, u, x = self.get_addr_balance(address)
                return len(h), len(h) > 0 and c == -u
        
            def address_is_old(self, address, age_limit=2):