tAdded 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). - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit def4de8184f7a725fa397a89d7174a11e05bdfd6 DIR parent c0fea37f13c323217ba3ed369e04d886deb911bb HTML Author: DiThi <kungfoobar@gmail.com> Date: Wed, 8 Feb 2012 04:22:18 +0100 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). Diffstat: M client/electrum | 58 ++++++++++++++++++++++++++----- M client/wallet.py | 13 ++++++++----- 2 files changed, 57 insertions(+), 14 deletions(-) --- DIR diff --git a/client/electrum b/client/electrum t@@ -31,7 +31,7 @@ urldecode = lambda x: _ud.sub(lambda m: chr(int(m.group(1), 16)), x) from wallet import format_satoshis 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)) t@@ -137,11 +137,19 @@ if __name__ == '__main__': wallet.synchronize() # check syntax - if cmd in ['payto', 'mktx']: + if cmd in ['payto', 'mktx', 'paytoch', 'payfromto']: + offset = 0 + if cmd == 'payfromto': + offset = 1 try: - to_address = args[1] - amount = int( 100000000 * Decimal(args[2]) ) - label = ' '.join(args[3:]) + to_address = args[offset+1] + amount = int( 100000000 * Decimal(args[offset+2]) ) + 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: options.tx_fee = int( 100000000 * Decimal(options.tx_fee) ) except: t@@ -155,7 +163,7 @@ if __name__ == '__main__': wallet.save() # 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 # check password try: t@@ -186,6 +194,16 @@ if __name__ == '__main__': print "payto <recipient> <amount> [label]" print "create and broadcast a transaction." 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': print "sendtx <tx>" print "broadcast a transaction to the network. <tx> must be in hexadecimal" t@@ -295,19 +313,41 @@ if __name__ == '__main__': wallet.labels[tx] = label 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(): if v == to_address: to_address = k print "alias", to_address break + if change_addr and v == change_addr: + change_addr = k 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: print e tx = None - if tx and cmd=='payto': + if tx and cmd in ['payto', 'paytoch', 'payfromto']: r, h = wallet.sendtx( tx ) print h else: DIR diff --git a/client/wallet.py b/client/wallet.py t@@ -618,12 +618,14 @@ class Wallet: inputs = [] 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) ] change_amount = total - ( amount + fee ) if change_amount != 0: # 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 def sign_inputs( self, inputs, outputs, password ): t@@ -702,13 +704,13 @@ class Wallet: default_label = 'at: ' + o_addr 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): raise BaseException("Invalid address") inputs, total, fee = self.choose_tx_inputs( amount, fee ) if not inputs: 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 ) tx = filter( raw_tx( s_inputs, outputs ) ) t@@ -717,7 +719,8 @@ class Wallet: if label: tx_hash = Hash(tx.decode('hex') )[::-1].encode('hex') self.labels[tx_hash] = label - self.save() + if save: + self.save() return tx def sendtx(self, tx):