Size dependent tx fee. Allow user to override the tx fee
This commit is contained in:
parent
72aefa7c16
commit
53b74689a1
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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 = []
|
||||
|
@ -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"
|
||||
|
|
104
client/gui.py
104
client/gui.py
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 )
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue