URI: 
       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):