electrum

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

commit e699ab6660ba91ccf194bed9d9aa4aa1ed913fb8
parent d9db7771f993002f7cae07cb4c7951e4843218f7
Author: ThomasV <thomasv@gitorious>
Date:   Thu,  5 Jun 2014 21:55:11 +0200

coin control: select UTXOs in menu

Diffstat:
Mgui/qt/main_window.py | 54+++++++++++++++++++++++++++++++++++++-----------------
Mlib/simple_config.py | 2+-
Mlib/wallet.py | 21+++++++++++----------
3 files changed, 49 insertions(+), 28 deletions(-)

diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py @@ -664,12 +664,14 @@ class ElectrumWindow(QMainWindow): self.from_label = QLabel(_('From')) grid.addWidget(self.from_label, 3, 0) - self.from_list = QTreeWidget(self) + self.from_list = MyTreeWidget(self) self.from_list.setColumnCount(2) self.from_list.setColumnWidth(0, 350) self.from_list.setColumnWidth(1, 50) - self.from_list.setHeaderHidden (True) + self.from_list.setHeaderHidden(True) self.from_list.setMaximumHeight(80) + self.from_list.setContextMenuPolicy(Qt.CustomContextMenu) + self.from_list.customContextMenuRequested.connect(self.from_list_menu) grid.addWidget(self.from_list, 3, 1, 1, 3) self.set_pay_from([]) @@ -699,8 +701,8 @@ class ElectrumWindow(QMainWindow): self.payto_sig = QLabel('') grid.addWidget(self.payto_sig, 7, 0, 1, 4) - QShortcut(QKeySequence("Up"), w, w.focusPreviousChild) - QShortcut(QKeySequence("Down"), w, w.focusNextChild) + #QShortcut(QKeySequence("Up"), w, w.focusPreviousChild) + #QShortcut(QKeySequence("Down"), w, w.focusNextChild) w.setLayout(grid) def entry_changed( is_fee ): @@ -710,7 +712,7 @@ class ElectrumWindow(QMainWindow): self.amount_e.is_shortcut = False sendable = self.get_sendable_balance() # there is only one output because we are completely spending inputs - inputs, total, fee = self.wallet.choose_tx_inputs( sendable, 0, 1, self.get_payment_sources()) + inputs, total, fee = self.wallet.choose_tx_inputs( sendable, 0, 1, coins = self.get_coins()) fee = self.wallet.estimated_fee(inputs, 1) amount = total - fee self.amount_e.setText( self.format_amount(amount) ) @@ -724,7 +726,7 @@ class ElectrumWindow(QMainWindow): if amount is None: return # assume that there will be 2 outputs (one for change) - inputs, total, fee = self.wallet.choose_tx_inputs(amount, fee, 2, self.get_payment_sources()) + inputs, total, fee = self.wallet.choose_tx_inputs(amount, fee, 2, coins = self.get_coins()) if not is_fee: self.fee_e.setText( self.format_amount( fee ) ) if inputs: @@ -749,17 +751,32 @@ class ElectrumWindow(QMainWindow): run_hook('create_send_tab', grid) return w + def from_list_delete(self, item): + i = self.from_list.indexOfTopLevelItem(item) + self.pay_from.pop(i) + self.redraw_from_list() - def set_pay_from(self, l): - self.pay_from = l + def from_list_menu(self, position): + item = self.from_list.itemAt(position) + menu = QMenu() + menu.addAction(_("Remove"), lambda: self.from_list_delete(item)) + 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.redraw_from_list() + + def redraw_from_list(self): self.from_list.clear() self.from_label.setHidden(len(self.pay_from) == 0) self.from_list.setHidden(len(self.pay_from) == 0) - for addr in self.pay_from: - c, u = self.wallet.get_addr_balance(addr) - balance = self.format_amount(c + u) - self.from_list.addTopLevelItem(QTreeWidgetItem( [addr, balance] )) + def format(x): + h = x.get('prevout_hash') + return h[0:8] + '...' + h[-8:] + ":%d"%x.get('prevout_n') + u'\t' + "%s"%x.get('address') + + for item in self.pay_from: + self.from_list.addTopLevelItem(QTreeWidgetItem( [format(item), self.format_amount(item['value']) ])) def update_completions(self): l = [] @@ -810,9 +827,9 @@ class ElectrumWindow(QMainWindow): self.send_button.setDisabled(True) # first, create an unsigned tx - domain = self.get_payment_sources() + coins = self.get_coins() try: - tx = self.wallet.make_unsigned_transaction(outputs, fee, None, domain) + tx = self.wallet.make_unsigned_transaction(outputs, fee, None, coins = coins) tx.error = None except Exception as e: traceback.print_exc(file=sys.stdout) @@ -1100,14 +1117,17 @@ class ElectrumWindow(QMainWindow): def get_sendable_balance(self): - return sum(sum(self.wallet.get_addr_balance(a)) for a in self.get_payment_sources()) + return sum(map(lambda x:x['value'], self.get_coins())) - def get_payment_sources(self): + def get_coins(self): if self.pay_from: return self.pay_from else: - return self.wallet.get_account_addresses(self.current_account) + 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) def send_from_addresses(self, addrs): diff --git a/lib/simple_config.py b/lib/simple_config.py @@ -3,7 +3,7 @@ import ast import threading import os -from util import user_dir, print_error +from util import user_dir, print_error, print_msg diff --git a/lib/wallet.py b/lib/wallet.py @@ -661,17 +661,18 @@ class Abstract_Wallet: return [x[1] for x in coins] - def choose_tx_inputs( self, amount, fixed_fee, num_outputs, domain = None ): + def choose_tx_inputs( self, amount, fixed_fee, num_outputs, domain = None, coins = None ): """ todo: minimize tx size """ total = 0 fee = self.fee if fixed_fee is None else fixed_fee - if domain is None: - domain = self.addresses(True) - for i in self.frozen_addresses: - if i in domain: domain.remove(i) + if not coins: + 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) - coins = self.get_unspent_coins(domain) inputs = [] for item in coins: @@ -852,11 +853,11 @@ class Abstract_Wallet: return default_label - def make_unsigned_transaction(self, outputs, fee=None, change_addr=None, domain=None ): + def make_unsigned_transaction(self, outputs, fee=None, change_addr=None, domain=None, coins=None ): for address, x in outputs: assert is_valid(address), "Address " + address + " is invalid!" amount = sum( map(lambda x:x[1], outputs) ) - inputs, total, fee = self.choose_tx_inputs( amount, fee, len(outputs), domain ) + inputs, total, fee = self.choose_tx_inputs( amount, fee, len(outputs), domain, coins ) if not inputs: raise ValueError("Not enough funds") for txin in inputs: @@ -865,8 +866,8 @@ class Abstract_Wallet: return Transaction.from_io(inputs, outputs) - def mktx(self, outputs, password, fee=None, change_addr=None, domain= None ): - tx = self.make_unsigned_transaction(outputs, fee, change_addr, domain) + def mktx(self, outputs, password, fee=None, change_addr=None, domain= None, coins = None ): + tx = self.make_unsigned_transaction(outputs, fee, change_addr, domain, coins) keypairs = {} self.add_keypairs_from_wallet(tx, keypairs, password) if keypairs: