URI: 
       tcommands: extract params and options from arguments - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit ddd6a58cc7427c8f3474d08c348cbd68626152c9
   DIR parent 1d5c6bdc2d75919117292d92b5a20913a75ba7ec
  HTML Author: ThomasV <thomasv@gitorious>
       Date:   Sun, 31 May 2015 22:42:34 +0200
       
       commands: extract params and options from arguments
       
       Diffstat:
         M electrum                            |      15 ---------------
         M lib/commands.py                     |     600 ++++++++++++++++---------------
       
       2 files changed, 310 insertions(+), 305 deletions(-)
       ---
   DIR diff --git a/electrum b/electrum
       t@@ -21,7 +21,6 @@ from decimal import Decimal
        import json
        import os
        import re
       -import ast
        import sys
        import time
        import traceback
       t@@ -322,20 +321,6 @@ def run_cmdline(config):
                    else:
                        print_msg("Action canceled.")
        
       -    elif cmd.name == 'getconfig':
       -        key = args[0]
       -        out = config.get(key)
       -        print_msg(out)
       -
       -    elif cmd.name == 'setconfig':
       -        key, value = args[0:2]
       -        try:
       -            value = ast.literal_eval(value)
       -        except:
       -            pass
       -        config.set_key(key, value, True)
       -        print_msg(True)
       -
            elif cmd.name == 'password':
                new_password = prompt_password('New password:')
                wallet.update_password(password, new_password)
   DIR diff --git a/lib/commands.py b/lib/commands.py
       t@@ -22,6 +22,7 @@ import time
        import copy
        import argparse
        import json
       +import ast
        
        import util
        from util import print_msg, format_satoshis, print_stderr
       t@@ -31,226 +32,6 @@ import bitcoin
        from transaction import Transaction
        
        
       -class Command:
       -    def __init__(self, name, requires_network, requires_wallet, requires_password, params, options, help, description):
       -        self.name = name
       -        self.requires_network = bool(requires_network)
       -        self.requires_wallet = bool(requires_wallet)
       -        self.requires_password = bool(requires_password)
       -        self.params = params
       -        self.options = options
       -        self.help = help
       -        self.description = description
       -
       -known_commands = {}
       -
       -def register_command(*args):
       -    global known_commands
       -    name = args[0]
       -    known_commands[name] = Command(*args)
       -
       -
       -#                command
       -#                                      requires_network
       -#                                        requires_wallet
       -#                                          requires_password
       -#                                               arguments
       -#                                                    options
       -register_command('listcontacts',       0, 0, 0, [], [], 'Show your list of contacts', '')
       -register_command('create',             0, 1, 0, [], [], 'Create a new wallet', '')
       -register_command('createmultisig',     0, 1, 0, ['num', 'pubkeys'], ['unsigned'], 'Create multisig address', '')
       -register_command('createrawtx',        0, 1, 1, ['inputs', 'outputs'], ['unsigned'], 'Create a transaction from json inputs', 'The syntax is similar to bitcoind.')
       -register_command('deseed',             0, 1, 0, [], [], 'Remove seed from wallet.', 'This creates a seedless, watching-only wallet.')
       -register_command('decodetx',           0, 0, 0, ['tx'], [], 'Decode serialized transaction', '')
       -register_command('getprivatekeys',     0, 1, 1, ['address'], [], 'Get the private keys of an address', 'Address must be in wallet.')
       -register_command('dumpprivkeys',       0, 1, 1, [], [], 'Dump private keys from your wallet', '')
       -register_command('freeze',             0, 1, 0, ['address'], [], 'Freeze address', 'Freeze the funds at one of your wallet\'s addresses')
       -register_command('getalias',           0, 0, 0, ['key'], ['nocheck'], 'Retrieve alias', 'Lookup in your list of contacts, and for an OpenAlias DNS record')
       -register_command('getbalance',         1, 1, 0, [], [], 'Return the balance of your wallet', '')
       -register_command('getservers',         1, 0, 0, [], [], 'Return the list of available servers', '')
       -register_command('getaddressbalance',  1, 0, 0, ['address'], [], 'Return the balance of an address', '')
       -register_command('getaddresshistory',  1, 0, 0, ['address'], [], 'Return the transaction history of a wallet address', '')
       -register_command('getconfig',          0, 0, 0, ['key'], [], 'Return a configuration variable', '')
       -register_command('getpubkeys',         0, 1, 0, ['address'], [], 'Return the public keys for a wallet address', '')
       -register_command('gettransaction',     1, 0, 0, ['txid'], ['deserialized'], 'Retrieve a transaction', '')
       -register_command('getseed',            0, 1, 1, [], [], 'Get seed phrase', 'Print the generation seed of your wallet.')
       -register_command('getmpk',             0, 1, 0, [], [], 'Get Master Public Key', 'Return your wallet\'s master public key')
       -register_command('help',               0, 0, 0, [], [], 'Print help on a command', '')
       -register_command('history',            1, 1, 0, [], [], 'Wallet history', 'Returns the transaction history of your wallet')
       -register_command('importprivkey',      0, 1, 1, ['privkey'], [], 'Import a private key', '')
       -register_command('ismine',             0, 1, 0, ['address'], [], 'Check if address is in wallet', 'Return true if and only address is in wallet')
       -register_command('listaddresses',      0, 1, 0, [], ['show_all', 'show_labels', 'frozen', 'unused', 'funded', 'show_balance'],
       -                 'List wallet addresses', 'Returns your list of addresses.')
       -register_command('listunspent',        1, 1, 0, [], [], 'List unspent outputs', 'Returns the list of unspent transaction outputs in your wallet.')
       -register_command('getaddressunspent',  1, 0, 0, ['address'], [], 'Returns the list of unspent inputs for an address', '')
       -register_command('mktx',               0, 1, 1, ['destination', 'amount'], ['tx_fee', 'from_addr', 'change_addr', 'nocheck', 'unsigned', 'deserialized'],
       -                 'Create a transaction', '')
       -register_command('payto',              1, 1, 1, ['destination', 'amount'], ['tx_fee', 'from_addr', 'change_addr', 'nocheck'], 'Create and broadcast a transaction.', '')
       -register_command('mktx_csv',           0, 1, 1, ['csv_file'], ['tx_fee', 'from_addr', 'change_addr', 'nocheck', 'unsigned', 'deserialized'],
       -                 'Create a multi-output transaction', '')
       -register_command('payto_csv',          1, 1, 1, ['csv_file'], ['tx_fee', 'from_addr', 'change_addr', 'nocheck'], 'Create and broadcast multi-output transaction.', '')
       -register_command('password',           0, 1, 1, [], [], 'Change your password', '')
       -register_command('restore',            1, 1, 0, [], ['gap_limit', 'mpk', 'concealed'], 'Restore a wallet from seed', '')
       -register_command('searchcontacts',     0, 1, 0, ['query'], [], 'Search through contacts, return matching entries', '')
       -register_command('setconfig',          0, 0, 0, ['key', 'value'], [], 'Set a configuration variable', '')
       -register_command('setlabel',           0, 1, 0, ['item', 'label'], [], 'Assign a label to an item', 'Item may be a bitcoin address or a transaction ID')
       -register_command('sendtx',             1, 0, 0, ['tx'], [], 'Broadcast a transaction to the network', '')
       -register_command('signtransaction',    0, 1, 1, ['tx'], ['privkey'],
       -                 'Sign a transaction', 'The wallet keys will be used unless a private key is provided.')
       -register_command('signmessage',        0, 1, 1, ['address', 'message'], [],
       -                 'Sign a message with a key', 'Use quotes if your message contains whitespaces')
       -register_command('unfreeze',           0, 1, 0, ['address'], [], 'Unfreeze address', 'Unfreeze the funds at one of your wallet\'s address')
       -register_command('validateaddress',    0, 0, 0, ['address'], [], 'Check that the address is valid', '')
       -register_command('verifymessage',      0, 0, 0, ['address', 'signature', 'message'], [], 'Verify a signature', '')
       -register_command('version',            0, 0, 0, [], [], 'Return the version of your client', '')
       -register_command('encrypt',            0, 0, 0, ['pubkey', 'message'], [],
       -                 'Encrypt a message with a public key', 'Use quotes if the message contains whitespaces.')
       -register_command('decrypt',            0, 1, 1, ['pubkey', 'encrypted'], [], 'Decrypt a message encrypted with a public key', '')
       -register_command('getmerkle',          1, 0, 0, ['txid', 'height'], [], 'Get Merkle branch of a transaction included in a block', '')
       -register_command('getproof',           1, 0, 0, ['address'], [], 'Get Merkle branch of an address in the UTXO set', '')
       -register_command('getutxoaddress',     1, 0, 0, ['txid', 'pos'], [], 'Get the address of an unspent transaction output', '')
       -register_command('sweep',              1, 0, 0, ['privkey', 'destination'], ['tx_fee'],
       -                 'Sweep private key', 'Returns a transaction that spends UTXOs from privkey to a destination address. The transaction is not broadcasted.')
       -register_command('make_seed',          0, 0, 0, [], ['nbits', 'entropy', 'language'], 'Create a seed', '')
       -register_command('check_seed',         0, 0, 0, ['seed'], ['entropy', 'language'], 'Check that a seed was generated with given entropy', '')
       -
       -param_descriptions = {
       -    'privkey': 'Private key. Type \'?\' to get a prompt.',
       -    'destination': 'Bitcoin address, contact or alias',
       -    'address': 'Bitcoin address',
       -    'seed': 'Seed phrase',
       -    'txid': 'Transaction ID',
       -    'pos': 'Position',
       -    'heigh': 'Block height',
       -    'tx': 'Serialized transaction (hexadecimal)',
       -    'key': 'Variable name',
       -    'pubkey': 'Public key',
       -    'message': 'Clear text message. Use quotes if it contains spaces.',
       -    'encrypted': 'Encrypted message',
       -    'amount': 'Amount to be sent (in BTC). Type \'!\' to send the maximum available.',
       -    'csv_file': 'CSV file of recipient, amount',
       -}
       -
       -command_options = {
       -    'password':    ("-W", "--password",    None,  "Password"),
       -    'concealed':   ("-C", "--concealed",   False, "Don't echo seed to console when restoring"),
       -    'show_all':    ("-a", "--all",         False, "Include change addresses"),
       -    'frozen':      (None, "--frozen",      False, "Show only frozen addresses"),
       -    'unused':      (None, "--unused",      False, "Show only unused addresses"),
       -    'funded':      (None, "--funded",      False, "Show only funded addresses"),
       -    'show_balance':("-b", "--balance",     False, "Show the balances of listed addresses"),
       -    'show_labels': ("-l", "--labels",      False, "Show the labels of listed addresses"),
       -    'nocheck':     (None, "--nocheck",     False, "Do not verify aliases"),
       -    'tx_fee':      ("-f", "--fee",         None,  "Transaction fee (in BTC)"),
       -    'from_addr':   ("-F", "--from",        None,  "Source address. If it isn't in the wallet, it will ask for the private key unless supplied in the format public_key:private_key. It's not saved in the wallet."),
       -    'change_addr': ("-c", "--change",      None,  "Change address. Default is a spare address, or the source address if it's not in the wallet"),
       -    'nbits':       (None, "--nbits",       128,   "Number of bits of entropy"),
       -    'entropy':     (None, "--entropy",     1,     "Custom entropy"),
       -    'language':    ("-L", "--lang",        None,  "Default language for wordlist"),
       -    'gap_limit':   ("-G", "--gap",         None,  "Gap limit"),
       -    'mpk':         (None, "--mpk",         None,  "Restore from master public key"),
       -    'deserialized':("-d", "--deserialized",False, "Return deserialized transaction"),
       -    'privkey':     (None, "--privkey",     None,  "Private key. Set to '?' to get a prompt."),
       -    'unsigned':    ("-u", "--unsigned",    False, "Do not sign transaction"),
       -}
       -
       -
       -arg_types = {
       -    'num':int,
       -    'nbits':int,
       -    'entropy':long,
       -    'pubkeys': json.loads,
       -    'inputs': json.loads,
       -    'outputs': json.loads,
       -    'tx_fee': lambda x: Decimal(x) if x is not None else None,
       -    'amount': lambda x: Decimal(x) if x!='!' else '!',
       -}
       -
       -
       -def set_default_subparser(self, name, args=None):
       -    """see http://stackoverflow.com/questions/5176691/argparse-how-to-specify-a-default-subcommand"""
       -    subparser_found = False
       -    for arg in sys.argv[1:]:
       -        if arg in ['-h', '--help']:  # global help if no subparser
       -            break
       -    else:
       -        for x in self._subparsers._actions:
       -            if not isinstance(x, argparse._SubParsersAction):
       -                continue
       -            for sp_name in x._name_parser_map.keys():
       -                if sp_name in sys.argv[1:]:
       -                    subparser_found = True
       -        if not subparser_found:
       -            # insert default in first position, this implies no
       -            # global options without a sub_parsers specified
       -            if args is None:
       -                sys.argv.insert(1, name)
       -            else:
       -                args.insert(0, name)
       -
       -argparse.ArgumentParser.set_default_subparser = set_default_subparser
       -
       -def add_network_options(parser):
       -    parser.add_argument("-1", "--oneserver", action="store_true", dest="oneserver", default=False, help="connect to one server only")
       -    parser.add_argument("-s", "--server", dest="server", default=None, help="set server host:port:protocol, where protocol is either t (tcp) or s (ssl)")
       -    parser.add_argument("-p", "--proxy", dest="proxy", default=None, help="set proxy [type:]host[:port], where type is socks4,socks5 or http")
       -
       -def get_parser(run_gui, run_daemon, run_cmdline):
       -    # parent parser, because set_default_subparser removes global options
       -    parent_parser = argparse.ArgumentParser('parent', add_help=False)
       -    parent_parser.add_argument("-v", "--verbose", action="store_true", dest="verbose", default=False, help="Show debugging information")
       -    parent_parser.add_argument("-P", "--portable", action="store_true", dest="portable", default=False, help="Use local 'electrum_data' directory")
       -    # create main parser
       -    parser = argparse.ArgumentParser(
       -        parents=[parent_parser],
       -        epilog="Run 'electrum help <command>' to see the help for a command")
       -    subparsers = parser.add_subparsers(dest='cmd', metavar='<command>')
       -    # gui
       -    parser_gui = subparsers.add_parser('gui', parents=[parent_parser], description="Run Electrum's Graphical User Interface.", help="Run GUI (default)")
       -    parser_gui.add_argument("url", nargs='?', default=None, help="bitcoin URI (or bip70 file)")
       -    parser_gui.set_defaults(func=run_gui)
       -    parser_gui.add_argument("-g", "--gui", dest="gui", help="select graphical user interface", choices=['qt', 'lite', 'gtk', 'text', 'stdio'])
       -    parser_gui.add_argument("-m", action="store_true", dest="hide_gui", default=False, help="hide GUI on startup")
       -    parser_gui.add_argument("-L", "--lang", dest="language", default=None, help="default language used in GUI")
       -    parser_gui.add_argument("-o", "--offline", action="store_true", dest="offline", default=False, help="Run the GUI offline")
       -    parser_gui.add_argument("-w", "--wallet", dest="wallet_path", help="wallet path")
       -    add_network_options(parser_gui)
       -    # daemon
       -    parser_daemon = subparsers.add_parser('daemon', parents=[parent_parser], help="Run Daemon")
       -    parser_daemon.add_argument("subcommand", choices=['start', 'status', 'stop'])
       -    parser_daemon.set_defaults(func=run_daemon)
       -    add_network_options(parser_daemon)
       -    # commands
       -    for cmdname in sorted(known_commands.keys()):
       -        cmd = known_commands[cmdname]
       -        p = subparsers.add_parser(cmdname, parents=[parent_parser], help=cmd.help, description=cmd.help + '. ' + cmd.description)
       -        p.set_defaults(func=run_cmdline)
       -        if cmd.requires_password:
       -            p.add_argument("-W", "--password", dest="password", default=None, help="password")
       -        if cmd.requires_network:
       -            p.add_argument("-o", "--offline", action="store_true", dest="offline", default=False, help="Run command offline")
       -        if cmd.requires_wallet:
       -            p.add_argument("-w", "--wallet", dest="wallet_path", help="wallet path")
       -        for optname in cmd.options:
       -            a, b, default, help = command_options[optname]
       -            action = "store_true" if type(default) is bool else 'store'
       -            args = (a, b) if a else (b,)
       -            if action == 'store':
       -                _type = arg_types.get(optname, str)
       -                p.add_argument(*args, dest=optname, action=action, default=default, help=help, type=_type)
       -            else:
       -                p.add_argument(*args, dest=optname, action=action, default=default, help=help)
       -
       -        for param in cmd.params:
       -            h = param_descriptions.get(param, '')
       -            _type = arg_types.get(param, str)
       -            p.add_argument(param, help=h, type=_type)
       -    # 'gui' is the default command
       -    parser.set_default_subparser('gui')
       -    return parser
       -
       -
       -
        class Commands:
        
            def __init__(self, config, wallet, network, callback = None):
       t@@ -275,28 +56,45 @@ class Commands:
            def help(self):
                return 'Commands: ' + ', '.join(sorted(known_commands.keys()))
        
       -    def make_seed(self, nbits, custom_entropy, language):
       +    # dummy functions for register
       +    def create(self): pass
       +    def restore(self): pass
       +    def deseed(self): pass
       +    def password(self): pass
       +
       +    def getconfig(self, key):
       +        return self.config.get(key)
       +
       +    def setconfig(self, key, value):
       +        try:
       +            value = ast.literal_eval(value)
       +        except:
       +            pass
       +        self.config.set_key(key, value, True)
       +        return True
       +
       +    def make_seed(self, nbits=128, entropy=1, language=None):
                from mnemonic import Mnemonic
                s = Mnemonic(language).make_seed(nbits, custom_entropy=custom_entropy)
                return s.encode('utf8')
        
       -    def check_seed(self, seed, custom_entropy, language):
       +    def check_seed(self, seed, entropy=1, language=None):
                from mnemonic import Mnemonic
       -        return Mnemonic(language).check_seed(seed, custom_entropy)
       +        return Mnemonic(language).check_seed(seed, entropy)
        
       -    def getaddresshistory(self, addr):
       -        return self.network.synchronous_get([ ('blockchain.address.get_history',[addr]) ])[0]
       +    def getaddresshistory(self, address):
       +        return self.network.synchronous_get([('blockchain.address.get_history', [address])])[0]
        
            def listunspent(self):
                l = copy.deepcopy(self.wallet.get_spendable_coins(exclude_frozen = False))
                for i in l: i["value"] = str(Decimal(i["value"])/100000000)
                return l
        
       -    def getaddressunspent(self, addr):
       -        return self.network.synchronous_get([('blockchain.address.listunspent',[addr])])[0]
       +    def getaddressunspent(self, address):
       +        return self.network.synchronous_get([('blockchain.address.listunspent', [address])])[0]
        
       -    def getutxoaddress(self, txid, num):
       -        r = self.network.synchronous_get([ ('blockchain.utxo.get_address',[txid, num]) ])
       +    def getutxoaddress(self, txid, pos):
       +        r = self.network.synchronous_get([('blockchain.utxo.get_address', [txid, pos])])
                if r:
                    return {'address':r[0]}
        
       t@@ -319,8 +117,8 @@ class Commands:
                    self.wallet.sign_transaction(tx, self.password)
                return tx
        
       -    def signtransaction(self, raw_tx, privkey=None):
       -        tx = Transaction(raw_tx)
       +    def signtransaction(self, tx, privkey=None):
       +        tx = Transaction(tx)
                tx.deserialize()
                if privkey:
                    pubkey = bitcoin.public_key_from_private_key(sec)
       t@@ -329,13 +127,13 @@ class Commands:
                    self.wallet.sign_transaction(tx, self.password)
                return tx
        
       -    def decodetx(self, raw):
       -        tx = Transaction(raw)
       -        return tx.deserialize()
       +    def decodetx(self, tx):
       +        t = Transaction(rawtx)
       +        return t.deserialize()
        
       -    def sendtx(self, raw):
       -        tx = Transaction(raw)
       -        return self.network.synchronous_get([('blockchain.transaction.broadcast', [str(tx)])])[0]
       +    def sendtx(self, tx):
       +        t = Transaction(raw)
       +        return self.network.synchronous_get([('blockchain.transaction.broadcast', [str(t)])])[0]
        
            def createmultisig(self, num, pubkeys):
                assert isinstance(pubkeys, list), (type(num), type(pubkeys))
       t@@ -343,36 +141,30 @@ class Commands:
                address = hash_160_to_bc_address(hash_160(redeem_script.decode('hex')), 5)
                return {'address':address, 'redeemScript':redeem_script}
        
       -    def freeze(self, addr):
       -        return self.wallet.set_frozen_state([addr], True)
       +    def freeze(self, address):
       +        return self.wallet.set_frozen_state([address], True)
        
       -    def unfreeze(self, addr):
       -        return self.wallet.set_frozen_state([addr], False)
       +    def unfreeze(self, address):
       +        return self.wallet.set_frozen_state([address], False)
        
       -    def getprivatekeys(self, addr):
       -        return self.wallet.get_private_key(addr, self.password)
       +    def getprivatekeys(self, address):
       +        return self.wallet.get_private_key(address, self.password)
        
       -    def ismine(self, addr):
       -        return self.wallet.is_mine(addr)
       +    def ismine(self, address):
       +        return self.wallet.is_mine(address)
        
       -    def dumpprivkeys(self, addresses = None):
       -        if addresses is None:
       -            addresses = self.wallet.addresses(True)
       -        return [self.wallet.get_private_key(address, self.password) for address in addresses]
       +    def dumpprivkeys(self, domain=None):
       +        if domain is None:
       +            domain = self.wallet.addresses(True)
       +        return [self.wallet.get_private_key(address, self.password) for address in domain]
        
       -    def validateaddress(self, addr):
       -        isvalid = is_address(addr)
       -        out = { 'isvalid':isvalid }
       -        if isvalid:
       -            out['address'] = addr
       -        return out
       +    def validateaddress(self, address):
       +        return is_address(address)
        
       -    def getpubkeys(self, addr):
       -        out = { 'address':addr }
       -        out['pubkeys'] = self.wallet.get_public_keys(addr)
       -        return out
       +    def getpubkeys(self, address):
       +        return self.wallet.get_public_keys(address)
        
       -    def getbalance(self, account= None):
       +    def getbalance(self, account=None):
                if account is None:
                    c, u, x = self.wallet.get_balance()
                else:
       t@@ -384,21 +176,21 @@ class Commands:
                    out["unmatured"] = str(Decimal(x)/100000000)
                return out
        
       -    def getaddressbalance(self, addr):
       -        out = self.network.synchronous_get([ ('blockchain.address.get_balance',[addr]) ])[0]
       +    def getaddressbalance(self, address):
       +        out = self.network.synchronous_get([('blockchain.address.get_balance', [address])])[0]
                out["confirmed"] =  str(Decimal(out["confirmed"])/100000000)
                out["unconfirmed"] =  str(Decimal(out["unconfirmed"])/100000000)
                return out
        
       -    def getproof(self, addr):
       -        p = self.network.synchronous_get([ ('blockchain.address.get_proof',[addr]) ])[0]
       +    def getproof(self, address):
       +        p = self.network.synchronous_get([('blockchain.address.get_proof', [address])])[0]
                out = []
                for i,s in p:
                    out.append(i)
                return out
        
            def getmerkle(self, txid, height):
       -        return self.network.synchronous_get([ ('blockchain.transaction.get_merkle', [txid, int(height)]) ])[0]
       +        return self.network.synchronous_get([('blockchain.transaction.get_merkle', [txid, int(height)])])[0]
        
            def getservers(self):
                while not self.network.is_up_to_date():
       t@@ -416,20 +208,20 @@ class Commands:
                s = self.wallet.get_mnemonic(self.password)
                return s.encode('utf8')
        
       -    def importprivkey(self, sec):
       +    def importprivkey(self, privkey):
                try:
       -            addr = self.wallet.import_key(sec,self.password)
       +            addr = self.wallet.import_key(privkey, self.password)
                    out = "Keypair imported: ", addr
                except Exception as e:
                    out = "Error: Keypair import failed: " + str(e)
                return out
        
       -    def sweep(self, privkey, recipient, fee=None, nocheck=False):
       +    def sweep(self, privkey, destination, tx_fee=None, nocheck=False):
                resolver = lambda x: self.contacts.resolve(x, nocheck)['address']
       -        dest = resolver(recipient)
       -        if fee is None:
       -            fee = 0.0001
       -        fee = int(Decimal(fee)*100000000)
       +        dest = resolver(destination)
       +        if tx_fee is None:
       +            tx_fee = 0.0001
       +        fee = int(Decimal(tx_fee)*100000000)
                return Transaction.sweep([privkey], self.network, dest, fee)
        
            def signmessage(self, address, message):
       t@@ -481,27 +273,27 @@ class Commands:
                        outputs.append((address, amount))
                return outputs
        
       -    def mktx(self, to_address, amount, fee=None, from_addr=None, change_addr=None, nocheck=False, unsigned=False, deserialized=False):
       +    def mktx(self, destination, amount, tx_fee=None, from_addr=None, change_addr=None, nocheck=False, unsigned=False, deserialized=False):
                domain = [from_addr] if from_addr else None
       -        tx = self._mktx([(to_address, amount)], fee, change_addr, domain, nocheck, unsigned, deserialized)
       +        tx = self._mktx([(destination, amount)], tx_fee, change_addr, domain, nocheck, unsigned, deserialized)
                return tx
        
       -    def mktx_csv(self, path, fee=None, from_addr=None, change_addr=None, nocheck=False, unsigned=False, deserialized=False):
       +    def mktx_csv(self, csv_file, tx_fee=None, from_addr=None, change_addr=None, nocheck=False, unsigned=False, deserialized=False):
                domain = [from_addr] if from_addr else None
       -        outputs = self._read_csv(path)
       -        tx = self._mktx(outputs, fee, change_addr, domain, nocheck, unsigned, deserialized)
       +        outputs = self._read_csv(csv_file)
       +        tx = self._mktx(outputs, tx_fee, change_addr, domain, nocheck, unsigned, deserialized)
                return tx
        
       -    def payto(self, to_address, amount, fee=None, from_addr=None, change_addr=None, nocheck=False):
       +    def payto(self, destination, amount, tx_fee=None, from_addr=None, change_addr=None, nocheck=False):
                domain = [from_addr] if from_addr else None
       -        tx = self._mktx([(to_address, amount)], fee, change_addr, domain, nocheck)
       +        tx = self._mktx([(destination, amount)], tx_fee, change_addr, domain, nocheck)
                r, h = self.wallet.sendtx(tx)
                return h
        
       -    def payto_csv(self, path, fee = None, from_addr=None, change_addr=None, nocheck=False):
       +    def payto_csv(self, csv_file, tx_fee=None, from_addr=None, change_addr=None, nocheck=False):
                domain = [from_addr] if from_addr else None
       -        outputs = self._read_csv(path)
       -        tx = self._mktx(outputs, fee, change_addr, domain, nocheck)
       +        outputs = self._read_csv(csv_file)
       +        tx = self._mktx(outputs, tx_fee, change_addr, domain, nocheck)
                r, h = self.wallet.sendtx(tx)
                return h
        
       t@@ -536,12 +328,12 @@ class Commands:
                        results[key] = value
                return results
        
       -    def listaddresses(self, show_change=False, show_label=False, frozen=False, unused=False, funded=False, show_balance=False):
       +    def listaddresses(self, show_all=False, show_labels=False, frozen=False, unused=False, funded=False, show_balance=False):
                out = []
                for addr in self.wallet.addresses(True):
                    if frozen and not self.wallet.is_frozen(addr):
                        continue
       -            if not show_change and self.wallet.is_change(addr):
       +            if not show_all and self.wallet.is_change(addr):
                        continue
                    if unused and self.wallet.is_used(addr):
                        continue
       t@@ -550,15 +342,15 @@ class Commands:
                    item = addr
                    if show_balance:
                        item += ", "+ format_satoshis(sum(self.wallet.get_addr_balance(addr)))
       -            if show_label:
       +            if show_labels:
                        item += ', ' + self.wallet.labels.get(addr,'')
                    out.append(item)
                return out
        
       -    def gettransaction(self, tx_hash, deserialized=False):
       -        tx = self.wallet.transactions.get(tx_hash) if self.wallet else None
       +    def gettransaction(self, txid, deserialized=False):
       +        tx = self.wallet.transactions.get(txid) if self.wallet else None
                if tx is None and self.network:
       -            raw = self.network.synchronous_get([('blockchain.transaction.get', [tx_hash])])[0]
       +            raw = self.network.synchronous_get([('blockchain.transaction.get', [txid])])[0]
                    if raw:
                        tx = Transaction(raw)
                    else:
       t@@ -568,5 +360,233 @@ class Commands:
            def encrypt(self, pubkey, message):
                return bitcoin.encrypt_message(message, pubkey)
        
       -    def decrypt(self, pubkey, message):
       -        return self.wallet.decrypt_message(pubkey, message, self.password)
       +    def decrypt(self, pubkey, encrypted):
       +        return self.wallet.decrypt_message(pubkey, encrypted, self.password)
       +
       +
       +
       +class Command:
       +    def __init__(self, name, requires_network, requires_wallet, requires_password, help, description):
       +        self.name = name
       +        self.requires_network = bool(requires_network)
       +        self.requires_wallet = bool(requires_wallet)
       +        self.requires_password = bool(requires_password)
       +        self.help = help
       +        self.description = description
       +        # compute params and options
       +        func = getattr(Commands, name)
       +        varnames = func.func_code.co_varnames[1:func.func_code.co_argcount]
       +        defaults = func.func_defaults
       +        if defaults:
       +            n = len(defaults)
       +            self.params, self.options = list(varnames[:-n]), list(varnames[-n:])
       +        else:
       +            self.params, self.options = list(varnames), []
       +
       +
       +
       +known_commands = {}
       +
       +def register_command(*args):
       +    global known_commands
       +    name = args[0]
       +    known_commands[name] = Command(*args)
       +
       +
       +#                command
       +#                                      requires_network
       +#                                        requires_wallet
       +#                                          requires_password
       +#                                               arguments
       +#                                                    options
       +register_command('listcontacts',       0, 0, 0, 'Show your list of contacts', '')
       +register_command('create',             0, 1, 0, 'Create a new wallet', '')
       +register_command('createmultisig',     0, 1, 0, 'Create multisig address', '')
       +register_command('createrawtx',        0, 1, 1, 'Create a transaction from json inputs', 'The syntax is similar to bitcoind.')
       +register_command('deseed',             0, 1, 0, 'Remove seed from wallet.', 'This creates a seedless, watching-only wallet.')
       +register_command('decodetx',           0, 0, 0, 'Decode serialized transaction', '')
       +register_command('getprivatekeys',     0, 1, 1, 'Get the private keys of an address', 'Address must be in wallet.')
       +register_command('dumpprivkeys',       0, 1, 1, 'Dump private keys from your wallet', '')
       +register_command('freeze',             0, 1, 0, 'Freeze address', 'Freeze the funds at one of your wallet\'s addresses')
       +register_command('getalias',           0, 0, 0, 'Retrieve alias', 'Lookup in your list of contacts, and for an OpenAlias DNS record')
       +register_command('getbalance',         1, 1, 0, 'Return the balance of your wallet', '')
       +register_command('getservers',         1, 0, 0, 'Return the list of available servers', '')
       +register_command('getaddressbalance',  1, 0, 0, 'Return the balance of an address', '')
       +register_command('getaddresshistory',  1, 0, 0, 'Return the transaction history of a wallet address', '')
       +register_command('getconfig',          0, 0, 0, 'Return a configuration variable', '')
       +register_command('getpubkeys',         0, 1, 0, 'Return the public keys for a wallet address', '')
       +register_command('gettransaction',     1, 0, 0, 'Retrieve a transaction', '')
       +register_command('getseed',            0, 1, 1, 'Get seed phrase', 'Print the generation seed of your wallet.')
       +register_command('getmpk',             0, 1, 0, 'Get Master Public Key', 'Return your wallet\'s master public key')
       +register_command('help',               0, 0, 0, 'Print help on a command', '')
       +register_command('history',            1, 1, 0, 'Wallet history', 'Returns the transaction history of your wallet')
       +register_command('importprivkey',      0, 1, 1, 'Import a private key', '')
       +register_command('ismine',             0, 1, 0, 'Check if address is in wallet', 'Return true if and only address is in wallet')
       +register_command('listaddresses',      0, 1, 0, 'List wallet addresses', 'Returns your list of addresses.')
       +register_command('listunspent',        1, 1, 0, 'List unspent outputs', 'Returns the list of unspent transaction outputs in your wallet.')
       +register_command('getaddressunspent',  1, 0, 0, 'Returns the list of unspent inputs for an address', '')
       +register_command('mktx',               0, 1, 1, 'Create a transaction', '')
       +register_command('payto',              1, 1, 1, 'Create and broadcast a transaction.', '')
       +register_command('mktx_csv',           0, 1, 1, 'Create a multi-output transaction', '')
       +register_command('payto_csv',          1, 1, 1, 'Create and broadcast multi-output transaction.', '')
       +register_command('password',           0, 1, 1, 'Change your password', '')
       +register_command('restore',            1, 1, 0, 'Restore a wallet from seed', '')
       +register_command('searchcontacts',     0, 1, 0, 'Search through contacts, return matching entries', '')
       +register_command('setconfig',          0, 0, 0, 'Set a configuration variable', '')
       +register_command('setlabel',           0, 1, 0, 'Assign a label to an item', 'Item may be a bitcoin address or a transaction ID')
       +register_command('sendtx',             1, 0, 0, 'Broadcast a transaction to the network', '')
       +register_command('signtransaction',    0, 1, 1, 'Sign a transaction', 'The wallet keys will be used unless a private key is provided.')
       +register_command('signmessage',        0, 1, 1, 'Sign a message with a key', 'Use quotes if your message contains whitespaces')
       +register_command('unfreeze',           0, 1, 0, 'Unfreeze address', 'Unfreeze the funds at one of your wallet\'s address')
       +register_command('validateaddress',    0, 0, 0, 'Check that the address is valid', '')
       +register_command('verifymessage',      0, 0, 0, 'Verify a signature', '')
       +register_command('version',            0, 0, 0, 'Return the version of your client', '')
       +register_command('encrypt',            0, 0, 0, 'Encrypt a message with a public key', 'Use quotes if the message contains whitespaces.')
       +register_command('decrypt',            0, 1, 1, 'Decrypt a message encrypted with a public key', '')
       +register_command('getmerkle',          1, 0, 0, 'Get Merkle branch of a transaction included in a block', '')
       +register_command('getproof',           1, 0, 0, 'Get Merkle branch of an address in the UTXO set', '')
       +register_command('getutxoaddress',     1, 0, 0, 'Get the address of an unspent transaction output', '')
       +register_command('sweep',              1, 0, 0, 'Sweep private key',
       +                 'Returns a transaction that spends UTXOs from privkey to a destination address. The transaction is not broadcasted.')
       +register_command('make_seed',          0, 0, 0, 'Create a seed', '')
       +register_command('check_seed',         0, 0, 0, 'Check that a seed was generated with given entropy', '')
       +
       +param_descriptions = {
       +    'privkey': 'Private key. Type \'?\' to get a prompt.',
       +    'destination': 'Bitcoin address, contact or alias',
       +    'address': 'Bitcoin address',
       +    'seed': 'Seed phrase',
       +    'txid': 'Transaction ID',
       +    'pos': 'Position',
       +    'heigh': 'Block height',
       +    'tx': 'Serialized transaction (hexadecimal)',
       +    'key': 'Variable name',
       +    'pubkey': 'Public key',
       +    'message': 'Clear text message. Use quotes if it contains spaces.',
       +    'encrypted': 'Encrypted message',
       +    'amount': 'Amount to be sent (in BTC). Type \'!\' to send the maximum available.',
       +    'csv_file': 'CSV file of recipient, amount',
       +}
       +
       +command_options = {
       +    'password':    ("-W", "--password",    None,  "Password"),
       +    'concealed':   ("-C", "--concealed",   False, "Don't echo seed to console when restoring"),
       +    'show_all':    ("-a", "--all",         False, "Include change addresses"),
       +    'frozen':      (None, "--frozen",      False, "Show only frozen addresses"),
       +    'unused':      (None, "--unused",      False, "Show only unused addresses"),
       +    'funded':      (None, "--funded",      False, "Show only funded addresses"),
       +    'show_balance':("-b", "--balance",     False, "Show the balances of listed addresses"),
       +    'show_labels': ("-l", "--labels",      False, "Show the labels of listed addresses"),
       +    'nocheck':     (None, "--nocheck",     False, "Do not verify aliases"),
       +    'tx_fee':      ("-f", "--fee",         None,  "Transaction fee (in BTC)"),
       +    'from_addr':   ("-F", "--from",        None,  "Source address. If it isn't in the wallet, it will ask for the private key unless supplied in the format public_key:private_key. It's not saved in the wallet."),
       +    'change_addr': ("-c", "--change",      None,  "Change address. Default is a spare address, or the source address if it's not in the wallet"),
       +    'nbits':       (None, "--nbits",       128,   "Number of bits of entropy"),
       +    'entropy':     (None, "--entropy",     1,     "Custom entropy"),
       +    'language':    ("-L", "--lang",        None,  "Default language for wordlist"),
       +    'gap_limit':   ("-G", "--gap",         None,  "Gap limit"),
       +    'mpk':         (None, "--mpk",         None,  "Restore from master public key"),
       +    'deserialized':("-d", "--deserialized",False, "Return deserialized transaction"),
       +    'privkey':     (None, "--privkey",     None,  "Private key. Set to '?' to get a prompt."),
       +    'unsigned':    ("-u", "--unsigned",    False, "Do not sign transaction"),
       +    'domain':      ("-D", "--domain",      None,  "List of addresses"),
       +    'account':     (None, "--account",     None,  "Account"),
       +}
       +
       +
       +arg_types = {
       +    'num':int,
       +    'nbits':int,
       +    'entropy':long,
       +    'pubkeys': json.loads,
       +    'inputs': json.loads,
       +    'outputs': json.loads,
       +    'tx_fee': lambda x: Decimal(x) if x is not None else None,
       +    'amount': lambda x: Decimal(x) if x!='!' else '!',
       +}
       +
       +
       +def set_default_subparser(self, name, args=None):
       +    """see http://stackoverflow.com/questions/5176691/argparse-how-to-specify-a-default-subcommand"""
       +    subparser_found = False
       +    for arg in sys.argv[1:]:
       +        if arg in ['-h', '--help']:  # global help if no subparser
       +            break
       +    else:
       +        for x in self._subparsers._actions:
       +            if not isinstance(x, argparse._SubParsersAction):
       +                continue
       +            for sp_name in x._name_parser_map.keys():
       +                if sp_name in sys.argv[1:]:
       +                    subparser_found = True
       +        if not subparser_found:
       +            # insert default in first position, this implies no
       +            # global options without a sub_parsers specified
       +            if args is None:
       +                sys.argv.insert(1, name)
       +            else:
       +                args.insert(0, name)
       +
       +argparse.ArgumentParser.set_default_subparser = set_default_subparser
       +
       +def add_network_options(parser):
       +    parser.add_argument("-1", "--oneserver", action="store_true", dest="oneserver", default=False, help="connect to one server only")
       +    parser.add_argument("-s", "--server", dest="server", default=None, help="set server host:port:protocol, where protocol is either t (tcp) or s (ssl)")
       +    parser.add_argument("-p", "--proxy", dest="proxy", default=None, help="set proxy [type:]host[:port], where type is socks4,socks5 or http")
       +
       +from util import profiler
       +
       +@profiler
       +def get_parser(run_gui, run_daemon, run_cmdline):
       +    # parent parser, because set_default_subparser removes global options
       +    parent_parser = argparse.ArgumentParser('parent', add_help=False)
       +    parent_parser.add_argument("-v", "--verbose", action="store_true", dest="verbose", default=False, help="Show debugging information")
       +    parent_parser.add_argument("-P", "--portable", action="store_true", dest="portable", default=False, help="Use local 'electrum_data' directory")
       +    # create main parser
       +    parser = argparse.ArgumentParser(
       +        parents=[parent_parser],
       +        epilog="Run 'electrum help <command>' to see the help for a command")
       +    subparsers = parser.add_subparsers(dest='cmd', metavar='<command>')
       +    # gui
       +    parser_gui = subparsers.add_parser('gui', parents=[parent_parser], description="Run Electrum's Graphical User Interface.", help="Run GUI (default)")
       +    parser_gui.add_argument("url", nargs='?', default=None, help="bitcoin URI (or bip70 file)")
       +    parser_gui.set_defaults(func=run_gui)
       +    parser_gui.add_argument("-g", "--gui", dest="gui", help="select graphical user interface", choices=['qt', 'lite', 'gtk', 'text', 'stdio'])
       +    parser_gui.add_argument("-m", action="store_true", dest="hide_gui", default=False, help="hide GUI on startup")
       +    parser_gui.add_argument("-L", "--lang", dest="language", default=None, help="default language used in GUI")
       +    parser_gui.add_argument("-o", "--offline", action="store_true", dest="offline", default=False, help="Run the GUI offline")
       +    parser_gui.add_argument("-w", "--wallet", dest="wallet_path", help="wallet path")
       +    add_network_options(parser_gui)
       +    # daemon
       +    parser_daemon = subparsers.add_parser('daemon', parents=[parent_parser], help="Run Daemon")
       +    parser_daemon.add_argument("subcommand", choices=['start', 'status', 'stop'])
       +    parser_daemon.set_defaults(func=run_daemon)
       +    add_network_options(parser_daemon)
       +    # commands
       +    for cmdname in sorted(known_commands.keys()):
       +        cmd = known_commands[cmdname]
       +        p = subparsers.add_parser(cmdname, parents=[parent_parser], help=cmd.help, description=cmd.help + '. ' + cmd.description)
       +        p.set_defaults(func=run_cmdline)
       +        if cmd.requires_password:
       +            p.add_argument("-W", "--password", dest="password", default=None, help="password")
       +        if cmd.requires_network:
       +            p.add_argument("-o", "--offline", action="store_true", dest="offline", default=False, help="Run command offline")
       +        if cmd.requires_wallet:
       +            p.add_argument("-w", "--wallet", dest="wallet_path", help="wallet path")
       +        for optname in cmd.options:
       +            a, b, default, help = command_options[optname]
       +            action = "store_true" if type(default) is bool else 'store'
       +            args = (a, b) if a else (b,)
       +            if action == 'store':
       +                _type = arg_types.get(optname, str)
       +                p.add_argument(*args, dest=optname, action=action, default=default, help=help, type=_type)
       +            else:
       +                p.add_argument(*args, dest=optname, action=action, default=default, help=help)
       +
       +        for param in cmd.params:
       +            h = param_descriptions.get(param, '')
       +            _type = arg_types.get(param, str)
       +            p.add_argument(param, help=h, type=_type)
       +    # 'gui' is the default command
       +    parser.set_default_subparser('gui')
       +    return parser