URI: 
       tSize dependent tx fee. Allow user to override the tx fee - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 53b74689a1b44f1a793730d67d0d62d29a4487c3
   DIR parent 72aefa7c1600845c4703bc8c615703b664fb22c5
  HTML Author: thomasv <thomasv@gitorious>
       Date:   Wed,  7 Dec 2011 18:54:32 +0100
       
       Size dependent tx fee. Allow user to override the tx fee
       
       Diffstat:
         M client/electrum.py                  |      23 ++++++++++++++---------
         M client/gui.py                       |     104 ++++++++++++++++++++++++-------
       
       2 files changed, 94 insertions(+), 33 deletions(-)
       ---
   DIR diff --git a/client/electrum.py b/client/electrum.py
       t@@ -491,9 +491,8 @@ class Wallet:
                else:
                    return False
        
       -    def choose_inputs_outputs( self, to_addr, amount, fee, password):
       +    def choose_tx_inputs( self, amount, fixed_fee ):
                """ todo: minimize tx size """
       -
                total = 0 
                inputs = []
                for addr in self.addresses:
       t@@ -503,11 +502,18 @@ class Wallet:
                            v = item.get('value')
                            total += v
                            inputs.append((addr, v, item['tx_hash'], item['pos'], item['raw_scriptPubKey'], None, None) )
       +                    if fixed_fee is not None:
       +                        fee = fixed_fee
       +                    else:
       +                        fee = self.fee * len(inputs)
                            if total >= amount + fee: break
                    if total >= amount + fee: break
                else:
       -            print "not enough funds: %d %d"%(total, fee)
       -            return False, "not enough funds: %d %d"%(total, fee)
       +            #print "not enough funds: %d %d"%(total, fee)
       +            inputs = []
       +        return inputs, total, fee
       +
       +    def choose_tx_outputs( self, to_addr, amount, fee, total, password ):
                outputs = [ (to_addr, amount) ]
                change_amount = total - ( amount + fee )
                if change_amount != 0:
       t@@ -522,7 +528,7 @@ class Wallet:
                        change_address = self.create_new_address(True, password)
                        print "new change address", change_address
                    outputs.append( (change_address,  change_amount) )
       -        return inputs, outputs
       +        return outputs
        
            def sign_inputs( self, inputs, outputs, password ):
                s_inputs = []
       t@@ -611,11 +617,10 @@ class Wallet:
            def mktx(self, to_address, amount, label, password, fee=None):
                if not self.is_valid(to_address):
                    return False, "Invalid address"
       -        if fee is None: fee = self.fee
                try:
       -            inputs, outputs = wallet.choose_inputs_outputs( to_address, amount, fee, password )
       -            if not inputs:
       -                return False, "Not enough funds"
       +            inputs, total, fee = wallet.choose_tx_inputs( amount, fee )
       +            if not inputs: return False, "Not enough funds %d %d"%(total, fee)
       +            outputs = wallet.choose_tx_outputs( to_address, amount, fee, total, password )
                    s_inputs = wallet.sign_inputs( inputs, outputs, password )
                except InvalidPassword:
                    return False, "Wrong password"
   DIR diff --git a/client/gui.py b/client/gui.py
       t@@ -41,6 +41,17 @@ def numbify(entry, is_int = False):
            s = ''.join([i for i in text if i in '0123456789.'])
            entry.set_text(s)
        
       +    #entry.set_text( str( Decimal( amount ) / 100000000 ) )
       +
       +    if not is_int:
       +        try:
       +            amount = int( Decimal(entry.get_text()) * 100000000 )
       +        except:
       +            amount = 0
       +    return amount
       +
       +
       +
        
        def show_seed_dialog(wallet, password, parent):
            import mnemonic
       t@@ -208,7 +219,7 @@ def run_settings_dialog(wallet, is_create, is_recovery, parent):
                fee_entry.connect('changed', numbify, False)
                fee_entry.show()
                fee.pack_start(fee_entry,False,False, 10)
       -        add_help_button(fee, 'Transaction fee. Recommended value:0.005. Note that this fee is per transaction, not per kilobyte. Size-dependent fees still need to be implemented.')
       +        add_help_button(fee, 'Fee per transaction input. Transactions involving multiple inputs tend to have a higher fee. Recommended value:0.0005')
                fee.show()
                vbox.pack_start(fee, False,False, 5)
                    
       t@@ -266,9 +277,9 @@ def run_settings_dialog(wallet, is_create, is_recovery, parent):
        
        
        
       -def show_message(message):
       +def show_message(message, parent=None):
            dialog = gtk.MessageDialog(
       -        parent = None,
       +        parent = parent,
                flags = gtk.DIALOG_MODAL, 
                buttons = gtk.BUTTONS_CLOSE, 
                message_format = message )
       t@@ -373,6 +384,9 @@ gtk.binding_entry_add_signal(MyWindow, gtk.keysyms.Q, gtk.gdk.CONTROL_MASK, 'myk
        
        class BitcoinGUI:
        
       +    def show_message(self, msg):
       +        show_message(msg, self.window)
       +
            def __init__(self, wallet):
                self.error = ''
                self.is_connected = False
       t@@ -384,7 +398,7 @@ class BitcoinGUI:
                self.window.connect("destroy", gtk.main_quit)
                self.window.set_border_width(0)
                self.window.connect('mykeypress', gtk.main_quit)
       -        self.window.set_default_size(670, 350)
       +        self.window.set_default_size(720, 350)
        
                vbox = gtk.VBox()
        
       t@@ -453,6 +467,7 @@ class BitcoinGUI:
        
                self.window.add(vbox)
                self.window.show_all()
       +        self.fee_box.hide()
        
                self.context_id = self.status_bar.get_context_id("statusbar")
                self.update_status_bar()
       t@@ -539,22 +554,56 @@ class BitcoinGUI:
                label.pack_start(label_entry, False)
                vbox.pack_start(label, False, False, 5)
        
       -        amount = gtk.HBox()
       +        amount_box = gtk.HBox()
                amount_label = gtk.Label('Amount:')
       -        amount_label.set_size_request(100,10)
       +        amount_label.set_size_request(100,-1)
                amount_label.show()
       -        amount.pack_start(amount_label, False)
       +        amount_box.pack_start(amount_label, False)
                amount_entry = gtk.Entry()
       -        amount_entry.set_size_request(100, 26) 
       -        amount_entry.connect('changed', numbify)
       +        amount_entry.set_size_request(120, -1)
                amount_entry.show()
       -        amount.pack_start(amount_entry, False)
       -        vbox.pack_start(amount, False, False, 5)
       +        amount_box.pack_start(amount_entry, False)
       +        vbox.pack_start(amount_box, False, False, 5)
        
       -        button = gtk.Button("Send")
       -        button.connect("clicked", self.do_send, (payto_entry, label_entry, amount_entry))
       -        button.show()
       -        amount.pack_start(button, False, False, 5)
       +        send_button = gtk.Button("Send")
       +        send_button.show()
       +        amount_box.pack_start(send_button, False, False, 5)
       +
       +        self.fee_box = fee_box = gtk.HBox()
       +        fee_label = gtk.Label('Fee:')
       +        fee_label.set_size_request(100,10)
       +        fee_box.pack_start(fee_label, False)
       +        fee_entry = gtk.Entry()
       +        fee_entry.set_size_request(120, 26)
       +        fee_entry.set_has_frame(False)
       +        fee_entry.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("#eeeeee"))
       +        fee_box.pack_start(fee_entry, False)
       +
       +        send_button.connect("clicked", self.do_send, (payto_entry, label_entry, amount_entry, fee_entry))
       +        vbox.pack_start(fee_box, False, False, 5)
       +
       +        self.user_fee = False
       +
       +        def entry_changed( entry, is_fee ):
       +            amount = numbify(amount_entry)
       +            fee = numbify(fee_entry)
       +            if not is_fee: fee = None
       +            inputs, total, fee = self.wallet.choose_tx_inputs( amount, fee )
       +            if not is_fee:
       +                fee_entry.set_text( str( Decimal( fee ) / 100000000 ) )
       +                self.fee_box.show()
       +            if inputs:
       +                amount_entry.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000"))
       +                fee_entry.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000"))
       +                send_button.set_sensitive(True)
       +            else:
       +                send_button.set_sensitive(False)
       +                amount_entry.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("#cc0000"))
       +                fee_entry.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("#cc0000"))
       +                self.error = 'Not enough funds'
       +
       +        amount_entry.connect('changed', entry_changed, False)
       +        fee_entry.connect('changed', entry_changed, True)
        
                self.payto_entry = payto_entry
                self.payto_amount_entry = amount_entry
       t@@ -575,38 +624,45 @@ class BitcoinGUI:
                self.add_tab(page, 'Wall')
        
            def do_send(self, w, data):
       -        payto_entry, label_entry, amount_entry = data
       +        payto_entry, label_entry, amount_entry, fee_entry = data
                
                label = label_entry.get_text()
        
                to_address = payto_entry.get_text()
                if not self.wallet.is_valid(to_address):
       -            show_message( "invalid bitcoin address" )
       +            self.show_message( "invalid bitcoin address")
                    return
        
                try:
                    amount = int( Decimal(amount_entry.get_text()) * 100000000 )
                except:
       -            show_message( "invalid amount" )
       +            self.show_message( "invalid amount")
       +            return
       +        try:
       +            fee = int( Decimal(fee_entry.get_text()) * 100000000 )
       +        except:
       +            self.show_message( "invalid fee")
                    return
        
                password = password_dialog() if self.wallet.use_encryption else None
        
       -        status, tx = self.wallet.mktx( to_address, amount, label, password )
       +        status, tx = self.wallet.mktx( to_address, amount, label, password, fee )
                self.wallet.new_session() # we created a new change address
                if not status:
       -            show_message(tx)
       +            self.show_message(tx)
                    return
        
                status, msg = self.wallet.sendtx( tx )
                if status:
       -            show_message( "payment sent.\n" + msg )
       +            self.show_message( "payment sent.\n" + msg )
                    payto_entry.set_text("")
                    label_entry.set_text("")
                    amount_entry.set_text("")
       +            fee_entry.set_text("")
       +            self.fee_box.hide()
                    self.update_sending_tab()
                else:
       -            show_message( msg )
       +            self.show_message( msg )
        
        
            def treeview_key_press(self, treeview, event):
       t@@ -617,7 +673,7 @@ class BitcoinGUI:
                        treeview.set_cursor((0,))
                elif event.keyval == gtk.keysyms.Return and treeview == self.history_treeview:
                    tx_details = self.history_list.get_value( self.history_list.get_iter(c), 8)
       -            show_message(tx_details)
       +            self.show_message(tx_details)
                return False
        
            def create_history_tab(self):
       t@@ -1031,7 +1087,7 @@ class BitcoinGUI:
                        host = hh
                        port = 50000
                except:
       -            show_message("error")
       +            self.show_message("error")
                    return
        
                if host!= wallet.host or port!=wallet.port: