Added two cli commands: payfromto and paytoch.
payfromto makes a payment from a keypair given as argument without saving the keypair in the wallet or using any other address in it. paytoch is the same as payto but specifying a custom change address (useful for imported keys).
This commit is contained in:
@@ -31,7 +31,7 @@ urldecode = lambda x: _ud.sub(lambda m: chr(int(m.group(1), 16)), x)
|
|||||||
from wallet import format_satoshis
|
from wallet import format_satoshis
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
known_commands = ['help', 'validateaddress', 'balance', 'contacts', 'create', 'payto', 'sendtx', 'password', 'newaddress', 'addresses', 'history', 'label', 'gui', 'mktx','seed','import','signmessage','verifymessage','eval']
|
known_commands = ['help', 'validateaddress', 'balance', 'contacts', 'create', 'payto', 'paytoch', 'payfromto', 'sendtx', 'password', 'newaddress', 'addresses', 'history', 'label', 'gui', 'mktx','seed','import','signmessage','verifymessage','eval']
|
||||||
|
|
||||||
usage = "usage: %prog [options] command args\nCommands: "+ (', '.join(known_commands))
|
usage = "usage: %prog [options] command args\nCommands: "+ (', '.join(known_commands))
|
||||||
|
|
||||||
@@ -137,11 +137,19 @@ if __name__ == '__main__':
|
|||||||
wallet.synchronize()
|
wallet.synchronize()
|
||||||
|
|
||||||
# check syntax
|
# check syntax
|
||||||
if cmd in ['payto', 'mktx']:
|
if cmd in ['payto', 'mktx', 'paytoch', 'payfromto']:
|
||||||
|
offset = 0
|
||||||
|
if cmd == 'payfromto':
|
||||||
|
offset = 1
|
||||||
try:
|
try:
|
||||||
to_address = args[1]
|
to_address = args[offset+1]
|
||||||
amount = int( 100000000 * Decimal(args[2]) )
|
amount = int( 100000000 * Decimal(args[offset+2]) )
|
||||||
label = ' '.join(args[3:])
|
change_addr = None
|
||||||
|
if cmd == 'paytoch':
|
||||||
|
change_addr = args[offset+3]
|
||||||
|
label = ' '.join(args[offset+4:])
|
||||||
|
else:
|
||||||
|
label = ' '.join(args[offset+3:])
|
||||||
if options.tx_fee:
|
if options.tx_fee:
|
||||||
options.tx_fee = int( 100000000 * Decimal(options.tx_fee) )
|
options.tx_fee = int( 100000000 * Decimal(options.tx_fee) )
|
||||||
except:
|
except:
|
||||||
@@ -155,7 +163,7 @@ if __name__ == '__main__':
|
|||||||
wallet.save()
|
wallet.save()
|
||||||
|
|
||||||
# commands needing password
|
# commands needing password
|
||||||
if cmd in ['payto', 'password', 'mktx', 'seed', 'import','signmessage' ] or ( cmd=='addresses' and options.show_keys):
|
if cmd in ['payto', 'paytoch', 'payfromto', 'password', 'mktx', 'seed', 'import','signmessage' ] or ( cmd=='addresses' and options.show_keys):
|
||||||
password = getpass.getpass('Password:') if wallet.use_encryption else None
|
password = getpass.getpass('Password:') if wallet.use_encryption else None
|
||||||
# check password
|
# check password
|
||||||
try:
|
try:
|
||||||
@@ -186,6 +194,16 @@ if __name__ == '__main__':
|
|||||||
print "payto <recipient> <amount> [label]"
|
print "payto <recipient> <amount> [label]"
|
||||||
print "create and broadcast a transaction."
|
print "create and broadcast a transaction."
|
||||||
print "<recipient> can be a bitcoin address or a label"
|
print "<recipient> can be a bitcoin address or a label"
|
||||||
|
elif cmd2 == 'paytoch':
|
||||||
|
print "paytoch <recipient> <amount> <change address> [label]"
|
||||||
|
print "create and broadcast a transaction, returning change to a custom address."
|
||||||
|
print "<recipient> and <change address> can be a bitcoin address or a label"
|
||||||
|
elif cmd2 == 'payfromto':
|
||||||
|
print "payfromto <public key>[:<private key>] <recipient> <amount>"
|
||||||
|
print "create and broadcast a transaction, from the address <public key> to <recipient>, without saving the address to the wallet."
|
||||||
|
print "it sends back the change to the same source address."
|
||||||
|
print "<recipient> can be a bitcoin address or a label."
|
||||||
|
print "if you omit <private key>, it will ask you for the key."
|
||||||
elif cmd2== 'sendtx':
|
elif cmd2== 'sendtx':
|
||||||
print "sendtx <tx>"
|
print "sendtx <tx>"
|
||||||
print "broadcast a transaction to the network. <tx> must be in hexadecimal"
|
print "broadcast a transaction to the network. <tx> must be in hexadecimal"
|
||||||
@@ -295,19 +313,41 @@ if __name__ == '__main__':
|
|||||||
wallet.labels[tx] = label
|
wallet.labels[tx] = label
|
||||||
wallet.save()
|
wallet.save()
|
||||||
|
|
||||||
elif cmd in ['payto', 'mktx']:
|
elif cmd in ['payto', 'mktx', 'paytoch', 'payfromto']:
|
||||||
|
if cmd == 'payfromto':
|
||||||
|
#temporally import key and remove the other addresses
|
||||||
|
keypair = args[1]
|
||||||
|
wallet.imported_keys = {}
|
||||||
|
if keypair.find(":") == -1:
|
||||||
|
keypair = keypair + ":" + getpass.getpass('Private key:')
|
||||||
|
if not wallet.import_key(keypair,password):
|
||||||
|
print "invalid key pair"
|
||||||
|
exit(1)
|
||||||
|
addr = wallet.imported_keys.keys()[0]
|
||||||
|
wallet.history[addr] = wallet.interface.retrieve_history(addr)
|
||||||
|
wallet.synchronize()
|
||||||
|
wallet.update_tx_history()
|
||||||
|
wallet.addresses = []
|
||||||
|
wallet.change_addresses = []
|
||||||
|
change_addr = addr
|
||||||
|
save = False
|
||||||
|
else:
|
||||||
|
save = True
|
||||||
for k, v in wallet.labels.items():
|
for k, v in wallet.labels.items():
|
||||||
if v == to_address:
|
if v == to_address:
|
||||||
to_address = k
|
to_address = k
|
||||||
print "alias", to_address
|
print "alias", to_address
|
||||||
break
|
break
|
||||||
|
if change_addr and v == change_addr:
|
||||||
|
change_addr = k
|
||||||
try:
|
try:
|
||||||
tx = wallet.mktx( to_address, amount, label, password, fee = options.tx_fee )
|
tx = wallet.mktx( to_address, amount, label, password,
|
||||||
|
fee = options.tx_fee, change_addr = change_addr, save = save )
|
||||||
except BaseException, e:
|
except BaseException, e:
|
||||||
print e
|
print e
|
||||||
tx = None
|
tx = None
|
||||||
|
|
||||||
if tx and cmd=='payto':
|
if tx and cmd in ['payto', 'paytoch', 'payfromto']:
|
||||||
r, h = wallet.sendtx( tx )
|
r, h = wallet.sendtx( tx )
|
||||||
print h
|
print h
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -618,12 +618,14 @@ class Wallet:
|
|||||||
inputs = []
|
inputs = []
|
||||||
return inputs, total, fee
|
return inputs, total, fee
|
||||||
|
|
||||||
def choose_tx_outputs( self, to_addr, amount, fee, total ):
|
def choose_tx_outputs( self, to_addr, amount, fee, total, change_addr=None ):
|
||||||
outputs = [ (to_addr, amount) ]
|
outputs = [ (to_addr, amount) ]
|
||||||
change_amount = total - ( amount + fee )
|
change_amount = total - ( amount + fee )
|
||||||
if change_amount != 0:
|
if change_amount != 0:
|
||||||
# normally, the update thread should ensure that the last change address is unused
|
# normally, the update thread should ensure that the last change address is unused
|
||||||
outputs.append( ( self.change_addresses[-1], change_amount) )
|
if not change_addr:
|
||||||
|
change_addr = self.change_addresses[-1]
|
||||||
|
outputs.append( ( change_addr, change_amount) )
|
||||||
return outputs
|
return outputs
|
||||||
|
|
||||||
def sign_inputs( self, inputs, outputs, password ):
|
def sign_inputs( self, inputs, outputs, password ):
|
||||||
@@ -702,13 +704,13 @@ class Wallet:
|
|||||||
default_label = 'at: ' + o_addr
|
default_label = 'at: ' + o_addr
|
||||||
tx['default_label'] = default_label
|
tx['default_label'] = default_label
|
||||||
|
|
||||||
def mktx(self, to_address, amount, label, password, fee=None):
|
def mktx(self, to_address, amount, label, password, fee=None, change_addr=None, save=True):
|
||||||
if not self.is_valid(to_address):
|
if not self.is_valid(to_address):
|
||||||
raise BaseException("Invalid address")
|
raise BaseException("Invalid address")
|
||||||
inputs, total, fee = self.choose_tx_inputs( amount, fee )
|
inputs, total, fee = self.choose_tx_inputs( amount, fee )
|
||||||
if not inputs:
|
if not inputs:
|
||||||
raise BaseException("Not enough funds")
|
raise BaseException("Not enough funds")
|
||||||
outputs = self.choose_tx_outputs( to_address, amount, fee, total )
|
outputs = self.choose_tx_outputs( to_address, amount, fee, total, change_addr )
|
||||||
s_inputs = self.sign_inputs( inputs, outputs, password )
|
s_inputs = self.sign_inputs( inputs, outputs, password )
|
||||||
|
|
||||||
tx = filter( raw_tx( s_inputs, outputs ) )
|
tx = filter( raw_tx( s_inputs, outputs ) )
|
||||||
@@ -717,7 +719,8 @@ class Wallet:
|
|||||||
if label:
|
if label:
|
||||||
tx_hash = Hash(tx.decode('hex') )[::-1].encode('hex')
|
tx_hash = Hash(tx.decode('hex') )[::-1].encode('hex')
|
||||||
self.labels[tx_hash] = label
|
self.labels[tx_hash] = label
|
||||||
self.save()
|
if save:
|
||||||
|
self.save()
|
||||||
return tx
|
return tx
|
||||||
|
|
||||||
def sendtx(self, tx):
|
def sendtx(self, tx):
|
||||||
|
|||||||
Reference in New Issue
Block a user