electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 687cc7783f4f2f4165d67f8633146f71466651a3
parent 4bce96526b6876638dbf70a486f175097b1f6e72
Author: ThomasV <thomasv@gitorious>
Date:   Tue,  5 May 2015 20:52:14 +0200

show unmatured coins in status bar. fixes #1163

Diffstat:
Mgui/android.py | 7+++++--
Mgui/gtk.py | 13++++++++-----
Mgui/qt/lite_window.py | 4++--
Mgui/qt/main_window.py | 27+++++++++++++++------------
Mgui/stdio.py | 9++++++---
Mgui/text.py | 9++++++---
Mlib/commands.py | 12+++++++-----
Mlib/wallet.py | 45+++++++++++++++++++++++++--------------------
8 files changed, 74 insertions(+), 52 deletions(-)

diff --git a/gui/android.py b/gui/android.py @@ -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 diff --git a/gui/gtk.py b/gui/gtk.py @@ -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.") @@ -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() diff --git a/gui/qt/lite_window.py b/gui/qt/lite_window.py @@ -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): diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py @@ -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) @@ -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) @@ -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): @@ -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): @@ -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) @@ -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) diff --git a/gui/stdio.py b/gui/stdio.py @@ -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" ) diff --git a/gui/text.py b/gui/text.py @@ -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") diff --git a/lib/commands.py b/lib/commands.py @@ -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): diff --git a/lib/wallet.py b/lib/wallet.py @@ -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 @@ -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, @@ -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: @@ -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 = {} @@ -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 @@ -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) @@ -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):