def get_blockchain_record(fqu): # hack to ensure local, until we update client from blockstack_client import client as bs_client # start session using blockstack_client bs_client.session(server_host=BLOCKSTACKD_IP, server_port=BLOCKSTACKD_PORT, set_global=True) data = {} try: resp = bs_client.get_name_blockchain_record(fqu) except Exception as e: data['error'] = e return data return resp
def recipientNotReady(address): """ Check if address can own more names or not """ # hack to ensure local, until we update client from blockstack_client import client as bs_client # start session using blockstack_client bs_client.session(server_host=BLOCKSTACKD_IP, server_port=BLOCKSTACKD_PORT, set_global=True) resp = bs_client.get_names_owned_by_address(address) names_owned = resp if len(names_owned) > MAXIMUM_NAMES_PER_ADDRESS: return True # if tests pass, then can use the address return False
def run_cli(argv=None, config_path=CONFIG_PATH): """ Run a CLI command from arguments (defaults to sys.argv) Return the result of the command on success. The result will be a dict, and will have 'error' defined on error condition. """ if argv is None: argv = sys.argv # only version? if '-v' in argv or '--version' in argv: print config.VERSION sys.exit(0) # alternative config path? if '-c' in argv or '--config' in argv: i = 1 while i < len(argv): if argv[i] == '-c' or argv[i] == '--config': if i + 1 >= len(argv): print >> sys.stderr, "%s: missing path" % argv[i] sys.exit(1) config_path = argv[i+1] argv.pop(i) argv.pop(i) else: i+=1 conf = config.get_config(path=config_path) if conf is None: return {'error': 'Failed to load config'} conf_version = conf.get('client_version', '') if not semver_match( conf_version, VERSION ): exit_with_error("Invalid configuration file: %s != %s" % (conf_version, VERSION), \ "Your configuration file (%s) is out of date. Please move it and try again in order to automatically generate a new config file." % config_path) advanced_mode = conf.get('advanced_mode', False) parser = argparse.ArgumentParser( description='Blockstack cli version {}'.format(config.VERSION)) all_methods = [] subparsers = parser.add_subparsers(dest='action') # add basic methods basic_methods = get_cli_basic_methods() basic_method_info = parse_methods( basic_methods ) build_method_subparsers( subparsers, basic_method_info ) all_methods = basic_method_info if advanced_mode: # add advanced methods log.debug("Enabling advanced methods") advanced_methods = get_cli_advanced_methods() advanced_method_info = parse_methods( advanced_methods ) build_method_subparsers( subparsers, advanced_method_info ) all_methods += advanced_method_info # Print default help message, if no argument is given if len(argv) == 1 or '-h' in argv: parser.print_help() return {} interactive = False args = None directive = None try: args, unknown_args = parser.parse_known_args(args=argv[1:]) directive = args.action except SystemExit: # bad arguments # special case: if the method is specified, but no method arguments are given, # then switch to prompting the user for individual arguments. try: directive_parser = argparse.ArgumentParser(description='Blockstack cli version {}'.format(config.VERSION)) directive_subparsers = directive_parser.add_subparsers(dest='action') # only parse the directive build_method_subparsers( directive_subparsers, all_methods, include_args=False, include_opts=False ) directive_args, directive_unknown_args = directive_parser.parse_known_args( args=argv[1:] ) # want interactive prompting interactive = True directive = directive_args.action except SystemExit: # still invalid parser.print_help() return {'error': 'Invalid arguments. Try passing "-h".'} result = {} blockstack_server = conf['server'] blockstack_port = conf['port'] # initialize blockstack connection session(conf=conf, server_host=blockstack_server, server_port=blockstack_port, set_global=True) # dispatch to the apporpriate method for method_info in all_methods: if directive != method_info['command']: continue method = method_info['method'] # interactive? if interactive: print "" print "Interactive prompt engaged. Press Ctrl+C to quit" print "Help for '%s': %s" % (method_info['command'], method_info['help']) print "" required_args = prompt_args( method_info['args'], lambda arghelp, argname: raw_input("%s ('%s'): " % (arghelp, argname)) ) if required_args is None: return {'error': 'Failed to prompt for arguments'} optional_args = prompt_args( method_info['opts'], lambda arghelp, argname: raw_input("optional: %s ('%s'): " % (arghelp, argname) )) if optional_args is None: return {'error': 'Failed to prompt for arguments'} full_args = [method_info['command']] + required_args + optional_args try: args, unknown_args = parser.parse_known_args( args=full_args ) except SystemExit: # invalid arguments return {'error': 'Invalid arguments. Please try again.'} result = method( args, config_path=config_path ) return result # not found return {'error': "No such command '%s'" % args.action}
def run_cli(argv=None, config_path=CONFIG_PATH): """ Run a CLI command from arguments (defaults to sys.argv) Return the result of the command on success. The result will be a dict, and will have 'error' defined on error condition. """ if argv is None: argv = sys.argv # alternative config path? if '-c' in argv or '--config' in argv: i = 1 while i < len(argv): if argv[i] == '-c' or argv[i] == '--config': if i + 1 >= len(argv): print >> sys.stderr, "%s: missing path" % argv[i] sys.exit(1) config_path = argv[i+1] argv.pop(i) argv.pop(i) else: i+=1 conf = config.get_config(path=config_path) if conf is None: return {'error': 'Failed to load config'} conf_version = conf.get('client_version', '') if not semver_match( conf_version, VERSION ): exit_with_error("Invalid configuration file: %s != %s" % (conf_version, VERSION), \ "Your configuration file (%s) is out of date. Please move it and try again in order to automatically generate a new config file." % config_path) advanced_mode = conf.get('advanced_mode', False) parser = argparse.ArgumentParser( description='Blockstack cli version {}'.format(config.VERSION)) all_methods = [] subparsers = parser.add_subparsers(dest='action') # add basic methods basic_methods = get_cli_basic_methods() basic_method_info = parse_methods( basic_methods ) build_method_subparsers( subparsers, basic_method_info ) all_methods = basic_method_info if advanced_mode: # add advanced methods log.debug("Enabling advanced methods") advanced_methods = get_cli_advanced_methods() advanced_method_info = parse_methods( advanced_methods ) build_method_subparsers( subparsers, advanced_method_info ) all_methods += advanced_method_info # Print default help message, if no argument is given if len(argv) == 1: parser.print_help() return {} interactive = False args = None directive = None try: args, unknown_args = parser.parse_known_args(args=argv[1:]) directive = args.action except SystemExit: # bad arguments # special case: if the method is specified, but no method arguments are given, # then switch to prompting the user for individual arguments. try: directive_parser = argparse.ArgumentParser(description='Blockstack cli version {}'.format(config.VERSION)) directive_subparsers = directive_parser.add_subparsers(dest='action') # only parse the directive build_method_subparsers( directive_subparsers, all_methods, include_args=False, include_opts=False ) directive_args, directive_unknown_args = directive_parser.parse_known_args( args=argv[1:] ) # want interactive prompting interactive = True directive = directive_args.action except SystemExit: # still invalid parser.print_help() return {'error': 'Invalid arguments. Try passing "-h".'} result = {} blockstack_server = conf['server'] blockstack_port = conf['port'] # initialize blockstack connection session(conf=conf, server_host=blockstack_server, server_port=blockstack_port, set_global=True) # dispatch to the apporpriate method for method_info in all_methods: if directive != method_info['command']: continue method = method_info['method'] # interactive? if interactive: print "" print "Interactive prompt engaged. Press Ctrl+C to quit" print "Help for '%s': %s" % (method_info['command'], method_info['help']) print "" required_args = prompt_args( method_info['args'], lambda arghelp, argname: raw_input("%s ('%s'): " % (arghelp, argname)) ) if required_args is None: return {'error': 'Failed to prompt for arguments'} optional_args = prompt_args( method_info['opts'], lambda arghelp, argname: raw_input("optional: %s ('%s'): " % (arghelp, argname) )) if optional_args is None: return {'error': 'Failed to prompt for arguments'} full_args = [method_info['command']] + required_args + optional_args try: args, unknown_args = parser.parse_known_args( args=full_args ) except SystemExit: # invalid arguments return {'error': 'Invalid arguments. Please try again.'} result = method( args, config_path=config_path ) return result # not found return {'error': "No such command '%s'" % args.action}
def update(fqu, profile): """ Update a previously registered fqu (step #3) @fqu: fully qualified name e.g., muneeb.id @profile: new profile json, hash(profile) goes to blockchain Internal use: @owner_address: fetches the owner_address that can update Returns True/False and stores tx_hash in queue """ # hack to ensure local, until we update client from blockstack_client import client as bs_client # start session using blockstack_client bs_client.session(server_host=BLOCKSTACKD_IP, server_port=BLOCKSTACKD_PORT, set_global=True) if alreadyinQueue(update_queue, fqu): log.debug("Already in update queue: %s" % fqu) return False if not nameRegistered(fqu): log.debug("Not yet registered %s" % fqu) return False data = get_blockchain_record(fqu) owner_address = data['address'] profile_hash = get_hash(profile) owner_privkey = wallet.get_privkey_from_address(owner_address) if owner_privkey is None: log.debug("Registrar doens't own this name.") return False if dontuseAddress(owner_address): log.debug("Owner address not ready: %s" % owner_address) return False elif underfundedAddress(owner_address): log.debug("Owner address under funded: %s" % owner_address) return False log.debug("Updating (%s, %s)" % (fqu, profile_hash)) resp = {} try: resp = bs_client.update(fqu, profile_hash, owner_privkey) except Exception as e: log.debug(e) if 'tx_hash' in resp: add_to_queue(update_queue, fqu, profile=profile, profile_hash=profile_hash, owner_address=owner_address, tx_hash=resp['tx_hash']) else: log.debug("Error updating: %s" % fqu) log.debug(resp) return False return True
def run_cli(argv=None, config_path=CONFIG_PATH): """ Run a CLI command from arguments (defaults to sys.argv) Return the result of the command on success. The result will be a dict, and will have 'error' defined on error condition. """ if argv is None: argv = sys.argv global_cli_args = { 'debug': { 'short': '-d', 'long': '--debug', 'has_arg': False, 're-exec': True, 'env': 'BLOCKSTACK_DEBUG', 'help': 'Enable global debugging messages', 'similar': ['--dbg', '-dd', '-ddd', '-dddd', '--verbose'], 'secret': False, }, 'config': { 'short': '-c', 'long': '--config', 'has_arg': True, 're-exec': True, 'env': 'BLOCKSTACK_CLIENT_CONFIG', 'help': 'Path to alternative configuration file and associated state', 'similar': ['--conf'], 'secret': False, }, 'default_yes': { 'short': '-y', 'long': '--yes', 'has_arg': False, 're-exec': False, 'env': 'BLOCKSTACK_CLIENT_INTERACTIVE_YES', 'help': 'Assume default/yes response to all queries', 'similar': [], 'secret': False, }, 'api_pass': { 'short': '-a', 'long': '--api_password', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_API_PASSWORD', 'help': 'API password to use', 'similar': ['--api-password', '--api-pass', '--api_pass'], 'secret': True, }, 'api_session': { 'short': '-A', 'long': '--api_session', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_API_SESSION', 'help': 'API session token to use', 'similar': ['--api-session', '--session', '--ses'], 'secret': True, }, 'api_bind': { 'short': '-b', 'long': '--bind', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_API_BIND', 'help': 'Address or hostname to bind the API server', 'similar': [], 'secret': False, }, 'dry_run': { 'short': '-n', 'long': '--dry_run', 'has_arg': False, 're-exec': True, 'env': 'BLOCKSTACK_DRY_RUN', 'help': 'Do not send transactions. Return the signed transaction instead.', 'similar': ['--dry-run', '--dryrun'], 'secret': False, }, 'wallet_password': { 'short': '-p', 'long': '--password', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_CLIENT_WALLET_PASSWORD', 'help': 'Wallet decryption password', 'similar': ['--pass', '--passwd'], 'secret': True, }, 'indexer_host': { 'short': '-H', 'long': '--host', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_CLI_SERVER_HOST', 'help': 'Hostname or IP address of the Blockstack blockchain indexer', 'similar': ['--ip', '--ipv4'], 'secret': False, }, 'indexer_port': { 'short': '-P', 'long': '--port', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_CLI_SERVER_PORT', 'help': 'Port number of the Blockstack blockchain indexer', 'similar': [], 'secret': False, }, 'secret_fd': { 'short': '-f', 'long': '--secrets', 'has_arg': True, 're-exec': False, 'help': 'Used internally; file descriptor number to serialized secrets preserved across execv(2).', 'similar': [], 'secret': False, }, } if '-v' in argv or '--version' in argv: print(VERSION) sys.exit(0) arg_info = parse_args(global_cli_args, argv, config_path=config_path) if 'error' in arg_info: print("Failed to parse global CLI arguments: {}".format( arg_info['error']), file=sys.stderr) print("Global CLI arguments:\n{}\n".format("\n".join([ "\t{}/{}\n\t\t{}".format(cliarg['short'], cliarg['long'], cliarg['help']) for argname, cliarg in global_cli_args.items() ])), file=sys.stderr) if 'similar' in arg_info: siminfo = arg_info['similar'] assert len(siminfo.keys()) == 1 opt = siminfo.keys()[0] arg = siminfo[opt] print("Suggestion: Use '{}' instead of '{}'".format(opt, arg), file=sys.stderr) sys.exit(1) cli_debug = arg_info['args'].get('debug') cli_config_argv = (arg_info['args'].has_key('config')) # set (non-secret) environment variables for envar, enval in arg_info['envs'].items(): if os.environ.get(envar) is None: if cli_debug: print("Set {} to {}".format(envar, enval), file=sys.stderr) os.environ[envar] = enval # set secrets... for secvar, secval in arg_info['secrets'].items(): set_secret(secvar, secval) # re-exec? if arg_info['re-exec']: new_argv = arg_info['new_argv'] if len(arg_info['secrets']) > 0: secbuf = serialize_secrets() fd = write_secrets(secbuf) new_argv += ['--secrets', str(fd)] new_argv = [sys.executable] + new_argv if cli_debug: print("Re-exec as `{}`".format(", ".join( ['"{}"'.format(i) for i in new_argv])), file=sys.stderr) try: os.execv(new_argv[0], new_argv) except: import traceback as tb tb.print_exc() sys.exit(1) # load secrets if arg_info['args'].has_key('secret_fd'): fd_str = arg_info['args']['secret_fd'] if fd_str: try: fd = int(fd_str) except: print('Invalid secret fd {}'.format(fd_str), file=sys.stderr) sys.exit(1) log.debug("Load secrets from {}".format(fd)) try: os.lseek(fd, 0, os.SEEK_SET) secbuf = os.read(fd, 65536) os.close(fd) load_secrets(secbuf) except Exception as e: traceback.print_exc() sys.exit(1) # do one-time opt-in request uuid_path = client_uuid_path(config_dir=os.path.dirname(config_path)) first_time = False client_uuid = None if not os.path.exists(uuid_path): first_time = True client_uuid = get_or_set_uuid(config_dir=os.path.dirname(config_path)) res = config.setup_config( config_path=config_path, interactive=(os.environ.get("BLOCKSTACK_CLIENT_INTERACTIVE_YES") != '1')) if 'error' in res: exit_with_error("Failed to load and verify config file: {}".format( res['error'])) conf = res['config'] # if the wallet exists, make sure that it's the latest version wallet_path = os.path.join(os.path.dirname(config_path), WALLET_FILENAME) if os.path.exists(wallet_path): res = inspect_wallet(wallet_path=wallet_path) if 'error' in res: exit_with_error( "Failed to inspect wallet at {}".format(wallet_path)) if res['migrate'] or res['format'] != 'current': if len(sys.argv) <= 1 or sys.argv[1] != 'setup_wallet': exit_with_error( "Wallet is in legacy format. Please unlock and migrate it with `blockstack setup_wallet`." ) parser = BlockstackArgumentParser( description='Blockstack cli version {}'.format(config.VERSION)) all_methods = [] subparsers = parser.add_subparsers(dest='action') # add basic methods all_method_names = get_cli_methods() all_methods = parse_methods(all_method_names) build_method_subparsers(subparsers, all_methods) # Print default help message, if no argument is given if len(argv) == 1 or '-h' in argv or '--help' in argv: parser.print_help() sys.exit(0) interactive, args, directive = False, None, None try: # capture stderr so we don't repeat ourselves args, unknown_args = parser.parse_known_args(args=argv[1:]) directive = args.action except SystemExit: # bad arguments # special case: if the method is specified, but no method arguments are given, # then switch to prompting the user for individual arguments. try: directive_parser = BlockstackArgumentParser( description='Blockstack cli version {}'.format(config.VERSION)) directive_subparsers = directive_parser.add_subparsers( dest='action') # only parse the directive build_method_subparsers(directive_subparsers, all_methods, include_args=False, include_opts=False) directive_args, directive_unknown_args = directive_parser.parse_known_args( args=argv[1:]) # want interactive prompting interactive, directive = True, directive_args.action except SystemExit: # still invalid return {'error': 'Invalid arguments. Try passing "-h".'} result = {} blockstack_server, blockstack_port = conf['blockstack-client'][ 'server'], conf['blockstack-client']['port'] # initialize blockstack connection session(server_host=blockstack_server, server_port=blockstack_port, set_global=True) prompt_func_arg = lambda help, name: raw_input('required: {} ("{}"): '. format(help, name)) prompt_func_opt = lambda help, name: raw_input('optional: {} ("{}"): '. format(help, name)) # dispatch to the apporpriate method for method_info in all_methods: if directive != method_info['command']: continue method = method_info['method'] pragmas = method_info['pragmas'] # interactive? if interactive: arg_names = [mi['name'] for mi in method_info['args']] opt_names = [mi['name'] for mi in method_info['opts']] arg_usage = ' '.join(arg_names) opt_usage = ' '.join(['[{}]'.format(opt) for opt in opt_names]) print('') print('Interactive prompt engaged. Press Ctrl+C to quit') print('Help for "{}": {}'.format(method_info['command'], method_info['help'])) print('Arguments: {} {} {}'.format(method_info['command'], arg_usage, opt_usage)) print('') required_args = prompt_args(method_info['args'], prompt_func_arg) if required_args is None: return {'error': 'Failed to prompt for arguments'} optional_args = prompt_args(method_info['opts'], prompt_func_opt) if optional_args is None: return {'error': 'Failed to prompt for arguments'} full_args = [method_info['command'] ] + required_args + optional_args try: args, unknown_args = parser.parse_known_args(args=full_args) except SystemExit: # invalid arguments return {'error': 'Invalid arguments. Please try again.'} result = method(args, config_path=config_path) return {'status': True, 'result': result, 'pragmas': pragmas} # not found return {'error': 'No such command "{}"'.format(args.action)}
def subsidized_transfer(fqu, transfer_address, owner_privkey, payment_address, payment_privkey=None): """ Transfer a previously registered fqu, using a different payment address @fqu: fully qualified name e.g., muneeb.id @transfer_address: new owner address @owner_privkey: privkey of current owner address, to sign tx @payment_address: the address which is paying for the cost Returns True/False and stores tx_hash in queue """ # hack to ensure local, until we update client from blockstack_client import client as bs_client # start session using blockstack_client bs_client.session(server_host=BLOCKSTACKD_IP, server_port=BLOCKSTACKD_PORT, set_global=True) if alreadyinQueue(transfer_queue, fqu): log.debug("Already in transfer queue: %s" % fqu) return False if not nameRegistered(fqu): log.debug("Not yet registered %s" % fqu) return False if ownerName(fqu, transfer_address): log.debug("Already transferred %s" % fqu) return True if recipientNotReady(transfer_address): log.debug("Address %s owns too many names already." % transfer_address) return False blockchain_record = get_blockchain_record(fqu) owner_address = blockchain_record['address'] check_address = get_address_from_privkey(owner_privkey) if check_address != owner_address: log.debug("Given privkey/address doens't own this name.") return False if dontuseAddress(payment_address): log.debug("Payment address not ready: %s" % payment_address) return False elif underfundedAddress(payment_address): log.debug("Payment address under funded: %s" % payment_address) return False owner_public_key = get_pubkey_from_privkey(owner_privkey) if payment_privkey is None: payment_privkey = wallet.get_privkey_from_address(payment_address) log.debug("Transferring (%s, %s)" % (fqu, transfer_address)) log.debug("<owner, payment> (%s, %s)" % (owner_address, payment_address)) resp = {} try: # format for transfer RPC call is: # (name, address, keep_data, public_key, subsidy_key) resp = bs_client.transfer_subsidized(fqu, transfer_address, True, public_key=owner_public_key, subsidy_key=payment_privkey) except Exception as e: log.debug(e) if 'subsidized_tx' in resp: unsigned_tx = resp['subsidized_tx'] else: log.debug("Error transferring: %s" % fqu) log.debug(pprint(resp)) return False broadcast_resp = send_subsidized(owner_privkey, unsigned_tx) if 'tx_hash' in broadcast_resp: add_to_queue(transfer_queue, fqu, owner_address=owner_address, transfer_address=transfer_address, tx_hash=broadcast_resp['tx_hash']) else: log.debug("Error transferring: %s" % fqu) log.debug(broadcast_resp) return False return True
along with Blockstack-client. If not, see <http://www.gnu.org/licenses/>. """ import os import sys import json import unittest from blockstack_client import client from blockstack_client.utils import print_result as pprint from blockstack_client.config import BLOCKSTACKD_SERVER, BLOCKSTACKD_PORT, CONFIG_DIR # start session if not os.path.exists( CONFIG_DIR ): os.makedirs( CONFIG_DIR ) client.session(server_host=BLOCKSTACKD_SERVER, server_port=BLOCKSTACKD_PORT) test_names = ["muneeb.id", "fredwilson.id"] class BlockstackClientTest(unittest.TestCase): def tearDown(self): pass def test_ping(self): """ Check ping """ resp = client.ping()
def transfer(fqu, transfer_address): """ Transfer a previously registered fqu (step #4) @fqu: fully qualified name e.g., muneeb.id @transfer_address: new owner address of @fqu Internal use: @owner_address: fetches the owner_address that can transfer Returns True/False and stores tx_hash in queue """ # hack to ensure local, until we update client from blockstack_client import client as bs_client # start session using blockstack_client bs_client.session(server_host=BLOCKSTACKD_IP, server_port=BLOCKSTACKD_PORT, set_global=True) if alreadyinQueue(transfer_queue, fqu): log.debug("Already in transfer queue: %s" % fqu) return False if ownerName(fqu, transfer_address): log.debug("Already transferred %s" % fqu) return True if recipientNotReady(transfer_address): log.debug("Address %s owns too many names already." % transfer_address) return False data = get_blockchain_record(fqu) owner_address = data['address'] owner_privkey = wallet.get_privkey_from_address(owner_address) if dontuseAddress(owner_address): log.debug("Owner address not ready: %s" % owner_address) return False elif underfundedAddress(owner_address): log.debug("Owner address under funded: %s" % owner_address) return False log.debug("Transferring (%s, %s)" % (fqu, transfer_address)) resp = {} try: # format for transfer RPC call is (name, address, keepdata, privatekey) resp = bs_client.transfer(fqu, transfer_address, True, owner_privkey) except Exception as e: log.debug(e) if 'tx_hash' in resp: add_to_queue(transfer_queue, fqu, owner_address=owner_address, transfer_address=transfer_address, tx_hash=resp['tx_hash']) else: log.debug("Error transferring: %s" % fqu) log.debug(resp) return False return True
def register(fqu, payment_address=None, owner_address=None, payment_privkey=None, auto_preorder=True): """ Register a previously preordered fqu (step #2) @fqu: fully qualified name e.g., muneeb.id @auto_preorder: automatically preorder, if true Uses from preorder queue: @payment_address: used for making the payment @owner_address: will own the fqu (must be same as preorder owner_address) Returns True/False and stores tx_hash in queue """ # hack to ensure local, until we update client from blockstack_client import client as bs_client # start session using blockstack_client bs_client.session(server_host=BLOCKSTACKD_IP, server_port=BLOCKSTACKD_PORT, set_global=True) # check register_queue first # stale preorder will get removed from preorder_queue if alreadyinQueue(register_queue, fqu): log.debug("Already in register queue: %s" % fqu) return False if not alreadyinQueue(preorder_queue, fqu): if auto_preorder: return preorder(fqu, payment_address, owner_address) else: log.debug("No preorder sent yet: %s" % fqu) return False if nameRegistered(fqu): log.debug("Already registered %s" % fqu) return False preorder_entry = preorder_queue.find_one({"fqu": fqu}) preorder_tx = preorder_entry['tx_hash'] tx_confirmations = get_tx_confirmations(preorder_tx) if tx_confirmations < PREORDER_CONFIRMATIONS: log.debug("Waiting on preorder confirmations: (%s, %s)" % (preorder_tx, tx_confirmations)) return False if payment_privkey is None: # use the correct owner_address from preorder operation try: owner_address = preorder_entry['owner_address'] payment_address = preorder_entry['payment_address'] except: log.debug("Error getting preorder addresses") return False payment_privkey = wallet.get_privkey_from_address(payment_address) else: payment_address = get_address_from_privkey(payment_privkey) if dontuseAddress(payment_address): log.debug("Payment address not ready: %s" % payment_address) return False elif underfundedAddress(payment_address): log.debug("Payment address under funded: %s" % payment_address) return False log.debug("Registering (%s, %s, %s)" % (fqu, payment_address, owner_address)) resp = {} try: resp = bs_client.register(fqu, payment_privkey, owner_address) except Exception as e: log.debug(e) if 'tx_hash' in resp: add_to_queue(register_queue, fqu, payment_address=payment_address, tx_hash=resp['tx_hash'], owner_address=owner_address) else: log.debug("Error registering: %s" % fqu) log.debug(pprint(resp)) return False return True
Resolver ~~~~~ :copyright: (c) 2014-2016 by Halfmoon Labs, Inc. :copyright: (c) 2016 blockstack.org :license: MIT, see LICENSE for more details. """ import json from config import BLOCKSTACKD_IP from config import BLOCKSTACKD_PORT from config import NAMES_FILE, NEW_NAMES_FILE # hack to ensure local, until we update client from blockstack_client import client as bs_client # start session using blockstack_client bs_client.session(server_host=BLOCKSTACKD_IP, server_port=BLOCKSTACKD_PORT, set_global=True) if __name__ == "__main__": total_names = [] offset = 0 count = 50 try: fout = open(NAMES_FILE, 'r') data = fout.read() data = json.loads(data) old_counter = len(data) except:
def preorder(fqu, payment_address, owner_address, payment_privkey=None): """ Preorder a fqu (step #1) @fqu: fully qualified name e.g., muneeb.id @payment_address: used for making the payment @owner_address: will own the fqu Returns True/False and stores tx_hash in queue """ # hack to ensure local, until we update client from blockstack_client import client as bs_client # start session using blockstack_client bs_client.session(server_host=BLOCKSTACKD_IP, server_port=BLOCKSTACKD_PORT, set_global=True) # stale preorder will get removed from preorder_queue if alreadyinQueue(register_queue, fqu): log.debug("Already in register queue: %s" % fqu) return False if alreadyinQueue(preorder_queue, fqu): log.debug("Already in preorder queue: %s" % fqu) return False if recipientNotReady(owner_address): log.debug("Address %s owns too many names already." % owner_address) return False if payment_privkey is None: payment_privkey = wallet.get_privkey_from_address(payment_address) else: payment_address = get_address_from_privkey(payment_privkey) if dontuseAddress(payment_address): log.debug("Payment address not ready: %s" % payment_address) return False elif underfundedAddress(payment_address): log.debug("Payment address under funded: %s" % payment_address) return False log.debug("Preordering (%s, %s, %s)" % (fqu, payment_address, owner_address)) resp = {} try: resp = bs_client.preorder(fqu, payment_privkey, owner_address) except Exception as e: log.debug(e) if 'tx_hash' in resp: add_to_queue(preorder_queue, fqu, payment_address=payment_address, tx_hash=resp['tx_hash'], owner_address=owner_address) else: log.debug("Error preordering: %s" % fqu) log.debug(pprint(resp)) raise ValueError('Error preordering') return False return True
#!/usr/bin/env python # -*- coding: utf-8 -*- import math import os from flask import Flask, jsonify from flask_crossdomain import crossdomain from blockstack_client import client as bs_client import blockstack_client session = bs_client.session(server_host="localhost", server_port=6264, set_global=True) app = Flask(__name__) @app.route('/get_all_namespaces', methods=['GET']) @crossdomain(origin='*') def get_all_namespaces(): try: namespaces = session.get_all_namespaces() return jsonify(namespaces), 200, { 'Cache-Control': 'public, max-age=300' } except Exception as e: return jsonify(str(e)), 500 @app.route('/get_name_blockchain_history/<fqu>', methods=['GET'])
def run_cli(argv=None, config_path=CONFIG_PATH): """ Run a CLI command from arguments (defaults to sys.argv) Return the result of the command on success. The result will be a dict, and will have 'error' defined on error condition. """ if argv is None: argv = sys.argv cli_debug = False cli_config_argv = False cli_default_yes = False cli_api_pass = None cli_dry_run = False if '-v' in argv or '--version' in argv: print(VERSION) sys.exit(0) # debug? new_argv, cli_debug = find_arg(argv, False, '-d', '--debug') if new_argv is None: # invalid sys.exit(1) if cli_debug: os.environ['BLOCKSTACK_DEBUG'] = '1' log.setLevel(logging.DEBUG) log.debug("Activated debugging") # alternative config path? new_argv, cli_config_path = find_arg(argv, True, '-c', '--config') if new_argv is None: # invalid sys.exit(1) argv = new_argv if cli_config_path: cli_config_argv = True config_path = cli_config_path log.debug('Use config file {}'.format(config_path)) os.environ['BLOCKSTACK_CLIENT_CONFIG'] = config_path # CLI-given password? new_argv, cli_password = find_arg(argv, True, '-p', '--password') if new_argv is None: # invalid sys.exit(1) argv = new_argv if cli_password and os.environ.get( 'BLOCKSTACK_CLIENT_WALLET_PASSWORD') is None: log.debug("Use CLI password") os.environ["BLOCKSTACK_CLIENT_WALLET_PASSWORD"] = cli_password # assume YES to all prompts? new_argv, cli_default_yes = find_arg(argv, False, '-y', '--yes') if new_argv is None: # invalid sys.exit(1) if cli_default_yes or os.environ.get( "BLOCKSTACK_CLIENT_INTERACTIVE_YES") == "1": if cli_debug: print("Assume YES to all interactive prompts", file=sys.stderr) os.environ["BLOCKSTACK_CLIENT_INTERACTIVE_YES"] = '1' # API password? new_argv, cli_api_pass = find_arg(argv, True, '-a', '--api_password') if new_argv is None: # invalid sys.exit(1) argv = new_argv if cli_api_pass: os.environ['BLOCKSTACK_API_PASSWORD'] = cli_api_pass # dry-run? new_argv, cli_dry_run = find_arg(argv, False, '-n', '--dry-run') if new_argv is None: # invalid sys.exit(1) if cli_dry_run or os.environ.get("BLOCKSTACK_DRY_RUN") == "1": if cli_debug: print('Dry-run; no transactions will be sent', file=sys.stderr) os.environ['BLOCKSTACK_DRY_RUN'] = "1" if cli_config_argv or cli_debug or cli_dry_run: # re-exec to reset variables if cli_debug: print("Re-exec {} with {}".format(argv[0], argv), file=sys.stderr) os.execv(argv[0], argv) # do one-time opt-in request uuid_path = client_uuid_path(config_dir=os.path.dirname(config_path)) first_time = False client_uuid = None if not os.path.exists(uuid_path): first_time = True client_uuid = get_or_set_uuid(config_dir=os.path.dirname(config_path)) if os.environ.get('BLOCKSTACK_CLIENT_INTERACTIVE_YES') != '1': # interactive allowed # prompt for email print( "Would you like to receive an email when there is a new release of this software available?" ) email_addr = raw_input("Email address (leave blank to opt out): ") # will only process real email addresses when we email announcements out if len(email_addr) > 0: analytics_user_register(client_uuid, email_addr) conf = config.get_config( path=config_path, interactive=(os.environ.get('BLOCKSTACK_CLIENT_INTERACTIVE_YES') != '1')) if conf is None: return {'error': 'Failed to load config'} conf_version = conf.get('client_version', '') if not semver_match(conf_version, VERSION): # back up the config file if not cli_config_argv: # default config file backup_path = config.backup_config_file(config_path=config_path) if not backup_path: exit_with_error( "Failed to back up legacy configuration file {}".format( config_path)) else: exit_with_error( "Backed up legacy configuration file from {} to {} and re-generated a new, default configuration. Please restart." .format(config_path, backup_path)) advanced_mode = conf.get('advanced_mode', False) parser = argparse.ArgumentParser( description='Blockstack cli version {}'.format(config.VERSION)) all_methods = [] subparsers = parser.add_subparsers(dest='action') # add basic methods all_method_names = get_cli_methods() all_methods = parse_methods(all_method_names) build_method_subparsers(subparsers, all_methods) if not advanced_mode: # remove advanced methods all_methods = filter(lambda m: 'advanced' not in m['pragmas'], all_methods) # Print default help message, if no argument is given if len(argv) == 1 or '-h' in argv or '--help' in argv: parser.print_help() sys.exit(0) interactive, args, directive = False, None, None try: args, unknown_args = parser.parse_known_args(args=argv[1:]) directive = args.action except SystemExit: # bad arguments # special case: if the method is specified, but no method arguments are given, # then switch to prompting the user for individual arguments. try: directive_parser = argparse.ArgumentParser( description='Blockstack cli version {}'.format(config.VERSION)) directive_subparsers = directive_parser.add_subparsers( dest='action') # only parse the directive build_method_subparsers(directive_subparsers, all_methods, include_args=False, include_opts=False) directive_args, directive_unknown_args = directive_parser.parse_known_args( args=argv[1:]) # want interactive prompting interactive, directive = True, directive_args.action except SystemExit: # still invalid parser.print_help() return {'error': 'Invalid arguments. Try passing "-h".'} result = {} blockstack_server, blockstack_port = conf['server'], conf['port'] # initialize blockstack connection session(conf=conf, server_host=blockstack_server, server_port=blockstack_port, set_global=True) prompt_func = lambda help, name: raw_input('optional: {} ("{}"): '.format( help, name)) # dispatch to the apporpriate method for method_info in all_methods: if directive != method_info['command']: continue method = method_info['method'] pragmas = method_info['pragmas'] # interactive? if interactive: print('') print('Interactive prompt engaged. Press Ctrl+C to quit') print('Help for "{}": {}'.format(method_info['command'], method_info['help'])) print('') required_args = prompt_args(method_info['args'], prompt_func) if required_args is None: return {'error': 'Failed to prompt for arguments'} optional_args = prompt_args(method_info['opts'], prompt_func) if optional_args is None: return {'error': 'Failed to prompt for arguments'} full_args = [method_info['command'] ] + required_args + optional_args try: args, unknown_args = parser.parse_known_args(args=full_args) except SystemExit: # invalid arguments return {'error': 'Invalid arguments. Please try again.'} result = method(args, config_path=config_path) return {'status': True, 'result': result, 'pragmas': pragmas} # not found return {'error': 'No such command "{}"'.format(args.action)}
try: fout = open(NAMES_FILE, 'r') data = fout.read() data = json.loads(data) old_counter = len(data) except: old_counter = 0 print old_counter while 1: # start session using blockstack_client bs_client.session(server_host=BLOCKSTACKD_IP, server_port=BLOCKSTACKD_PORT, set_global=True) new_names = bs_client.get_all_names(offset, count) if len(new_names) == 0: break # check for blockstack errors if len(new_names) == 1 and "error" in new_names: print "Blockstack error: " + new_names["error"] break total_names += new_names offset += count print offset
def run_cli(argv=None, config_path=CONFIG_PATH): """ Run a CLI command from arguments (defaults to sys.argv) Return the result of the command on success. The result will be a dict, and will have 'error' defined on error condition. """ if argv is None: argv = sys.argv global_cli_args = { 'debug': { 'short': '-d', 'long': '--debug', 'has_arg': False, 're-exec': True, 'env': 'BLOCKSTACK_DEBUG', 'help': 'Enable global debugging messages', 'similar': ['--dbg', '-dd', '-ddd', '-dddd', '--verbose'], 'secret': False, }, 'config': { 'short': '-c', 'long': '--config', 'has_arg': True, 're-exec': True, 'env': 'BLOCKSTACK_CLIENT_CONFIG', 'help': 'Path to alternative configuration file and associated state', 'similar': ['--conf'], 'secret': False, }, 'default_yes': { 'short': '-y', 'long': '--yes', 'has_arg': False, 're-exec': False, 'env': 'BLOCKSTACK_CLIENT_INTERACTIVE_YES', 'help': 'Assume default/yes response to all queries', 'similar': [], 'secret': False, }, 'api_pass': { 'short': '-a', 'long': '--api_password', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_API_PASSWORD', 'help': 'API password to use', 'similar': ['--api-password', '--api-pass', '--api_pass'], 'secret': True, }, 'api_session': { 'short': '-A', 'long': '--api_session', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_API_SESSION', 'help': 'API session token to use', 'similar': ['--api-session', '--session', '--ses'], 'secret': True, }, 'api_bind': { 'short': '-b', 'long': '--bind', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_API_BIND', 'help': 'Address or hostname to bind the API server', 'similar': [], 'secret': False, }, 'dry_run': { 'short': '-n', 'long': '--dry_run', 'has_arg': False, 're-exec': True, 'env': 'BLOCKSTACK_DRY_RUN', 'help': 'Do not send transactions. Return the signed transaction instead.', 'similar': ['--dry-run', '--dryrun'], 'secret': False, }, 'wallet_password': { 'short': '-p', 'long': '--password', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_CLIENT_WALLET_PASSWORD', 'help': 'Wallet decryption password', 'similar': ['--pass', '--passwd'], 'secret': True, }, 'indexer_host': { 'short': '-H', 'long': '--host', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_CLI_SERVER_HOST', 'help': 'Hostname or IP address of the Blockstack blockchain indexer', 'similar': ['--ip', '--ipv4'], 'secret': False, }, 'indexer_port': { 'short': '-P', 'long': '--port', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_CLI_SERVER_PORT', 'help': 'Port number of the Blockstack blockchain indexer', 'similar': [], 'secret': False, }, 'secret_fd': { 'short': '-f', 'long': '--secrets', 'has_arg': True, 're-exec': False, 'help': 'Used internally; file descriptor number to serialized secrets preserved across execv(2).', 'similar': [], 'secret': False, }, } if '-v' in argv or '--version' in argv: print(VERSION) sys.exit(0) arg_info = parse_args( global_cli_args, argv, config_path=config_path ) if 'error' in arg_info: print("Failed to parse global CLI arguments: {}".format(arg_info['error']), file=sys.stderr) print("Global CLI arguments:\n{}\n".format( "\n".join( ["\t{}/{}\n\t\t{}".format(cliarg['short'], cliarg['long'], cliarg['help']) for argname, cliarg in global_cli_args.items()] )), file=sys.stderr) if 'similar' in arg_info: siminfo = arg_info['similar'] assert len(siminfo.keys()) == 1 opt = siminfo.keys()[0] arg = siminfo[opt] print("Suggestion: Use '{}' instead of '{}'".format(opt, arg), file=sys.stderr) sys.exit(1) cli_debug = arg_info['args'].get('debug') cli_config_argv = (arg_info['args'].has_key('config')) # set (non-secret) environment variables for envar, enval in arg_info['envs'].items(): if os.environ.get(envar) is None: if cli_debug: print("Set {} to {}".format(envar, enval), file=sys.stderr) os.environ[envar] = enval # set secrets... for secvar, secval in arg_info['secrets'].items(): set_secret(secvar, secval) # re-exec? if arg_info['re-exec']: new_argv = arg_info['new_argv'] if len(arg_info['secrets']) > 0: secbuf = serialize_secrets() fd = write_secrets(secbuf) new_argv += ['--secrets', str(fd)] new_argv = [sys.executable] + new_argv if cli_debug: print("Re-exec as `{}`".format(", ".join([ '"{}"'.format(i) for i in new_argv])), file=sys.stderr) try: os.execv(new_argv[0], new_argv) except: import traceback as tb tb.print_exc() sys.exit(1) # load secrets if arg_info['args'].has_key('secret_fd'): fd_str = arg_info['args']['secret_fd'] if fd_str: try: fd = int(fd_str) except: print('Invalid secret fd {}'.format(fd_str), file=sys.stderr) sys.exit(1) log.debug("Load secrets from {}".format(fd)) try: os.lseek(fd, 0, os.SEEK_SET) secbuf = os.read(fd, 65536) os.close(fd) load_secrets(secbuf) except Exception as e: traceback.print_exc() sys.exit(1) # do one-time opt-in request uuid_path = client_uuid_path(config_dir=os.path.dirname(config_path)) first_time = False client_uuid = None if not os.path.exists(uuid_path): first_time = True client_uuid = get_or_set_uuid(config_dir=os.path.dirname(config_path)) if os.environ.get('BLOCKSTACK_CLIENT_INTERACTIVE_YES') != '1': # interactive allowed # prompt for email print("Would you like to receive an email when there is a new release of this software available?") email_addr = raw_input("Email address (leave blank to opt out): ") # will only process real email addresses when we email announcements out if len(email_addr) > 0: analytics_user_register( client_uuid, email_addr ) res = config.setup_config(config_path=config_path, interactive=(os.environ.get("BLOCKSTACK_CLIENT_INTERACTIVE_YES") != '1')) if 'error' in res: exit_with_error("Failed to load and verify config file: {}".format(res['error'])) conf = res['config'] # if the wallet exists, make sure that it's the latest version wallet_path = os.path.join(os.path.dirname(config_path), WALLET_FILENAME) if os.path.exists(wallet_path): res = inspect_wallet(wallet_path=wallet_path) if 'error' in res: exit_with_error("Failed to inspect wallet at {}".format(wallet_path)) if res['migrate'] or res['format'] != 'current': if len(sys.argv) <= 1 or sys.argv[1] != 'setup_wallet': exit_with_error("Wallet is in legacy format. Please unlock and migrate it with `blockstack setup_wallet`.") parser = BlockstackArgumentParser( description='Blockstack cli version {}'.format(config.VERSION) ) all_methods = [] subparsers = parser.add_subparsers(dest='action') # add basic methods all_method_names = get_cli_methods() all_methods = parse_methods(all_method_names) build_method_subparsers(subparsers, all_methods) # Print default help message, if no argument is given if len(argv) == 1 or '-h' in argv or '--help' in argv: parser.print_help() sys.exit(0) interactive, args, directive = False, None, None try: # capture stderr so we don't repeat ourselves args, unknown_args = parser.parse_known_args(args=argv[1:]) directive = args.action except SystemExit: # bad arguments # special case: if the method is specified, but no method arguments are given, # then switch to prompting the user for individual arguments. try: directive_parser = BlockstackArgumentParser( description='Blockstack cli version {}'.format(config.VERSION) ) directive_subparsers = directive_parser.add_subparsers( dest='action' ) # only parse the directive build_method_subparsers( directive_subparsers, all_methods, include_args=False, include_opts=False ) directive_args, directive_unknown_args = directive_parser.parse_known_args( args=argv[1:] ) # want interactive prompting interactive, directive = True, directive_args.action except SystemExit: # still invalid return {'error': 'Invalid arguments. Try passing "-h".'} result = {} blockstack_server, blockstack_port = conf['blockstack-client']['server'], conf['blockstack-client']['port'] # initialize blockstack connection session( server_host=blockstack_server, server_port=blockstack_port, set_global=True ) prompt_func = lambda help, name: raw_input('optional: {} ("{}"): '.format(help, name)) # dispatch to the apporpriate method for method_info in all_methods: if directive != method_info['command']: continue method = method_info['method'] pragmas = method_info['pragmas'] # interactive? if interactive: arg_names = [mi['name'] for mi in method_info['args']] opt_names = [mi['name'] for mi in method_info['opts']] arg_usage = ' '.join(arg_names) opt_usage = ' '.join( ['[{}]'.format(opt) for opt in opt_names] ) print('') print('Interactive prompt engaged. Press Ctrl+C to quit') print('Help for "{}": {}'.format(method_info['command'], method_info['help'])) print('Arguments: {} {}'.format(method_info['command'], arg_usage, opt_usage)) print('') required_args = prompt_args(method_info['args'], prompt_func) if required_args is None: return {'error': 'Failed to prompt for arguments'} optional_args = prompt_args(method_info['opts'], prompt_func) if optional_args is None: return {'error': 'Failed to prompt for arguments'} full_args = [method_info['command']] + required_args + optional_args try: args, unknown_args = parser.parse_known_args(args=full_args) except SystemExit: # invalid arguments return {'error': 'Invalid arguments. Please try again.'} result = method(args, config_path=config_path) return {'status': True, 'result': result, 'pragmas': pragmas} # not found return {'error': 'No such command "{}"'.format(args.action)}
def subsidized_update(fqu, profile, owner_privkey, payment_address, payment_privkey=None): """ Update a previously registered fqu, using a different payment address @fqu: fully qualified name e.g., muneeb.id @profile: new profile json, hash(profile) goes to blockchain @owner_privkey: privkey of owner address, to sign update @payment_address: the address which is paying for the cost Returns True/False and stores tx_hash in queue """ # hack to ensure local, until we update client from blockstack_client import client as bs_client # start session using blockstack_client bs_client.session(server_host=BLOCKSTACKD_IP, server_port=BLOCKSTACKD_PORT, set_global=True) if alreadyinQueue(update_queue, fqu): log.debug("Already in update queue: %s" % fqu) return False if not nameRegistered(fqu): log.debug("Not yet registered %s" % fqu) return False profile_hash = get_hash(profile) blockchain_record = get_blockchain_record(fqu) owner_address = blockchain_record['address'] check_address = get_address_from_privkey(owner_privkey) if check_address != owner_address: log.debug("Given privkey/address doens't own this name.") return False if dontuseAddress(payment_address): log.debug("Payment address not ready: %s" % payment_address) return False elif underfundedAddress(payment_address): log.debug("Payment address under funded: %s" % payment_address) return False owner_public_key = get_pubkey_from_privkey(owner_privkey) if payment_privkey is None: payment_privkey = wallet.get_privkey_from_address(payment_address) log.debug("Updating (%s, %s)" % (fqu, profile_hash)) log.debug("<owner, payment> (%s, %s)" % (owner_address, payment_address)) resp = {} try: resp = bs_client.update_subsidized(fqu, profile_hash, public_key=owner_public_key, subsidy_key=payment_privkey) except Exception as e: log.debug(e) if 'subsidized_tx' in resp: unsigned_tx = resp['subsidized_tx'] else: log.debug("Error updating: %s" % fqu) log.debug(resp) return False broadcast_resp = send_subsidized(owner_privkey, unsigned_tx) if 'tx_hash' in broadcast_resp: add_to_queue(update_queue, fqu, profile=profile, profile_hash=profile_hash, owner_address=owner_address, tx_hash=broadcast_resp['tx_hash']) else: log.debug("Error updating: %s" % fqu) log.debug(broadcast_resp) return False return True
def run_cli(): """ run cli """ conf = config.get_config() if conf is None: log.error("Failed to load config") sys.exit(1) advanced_mode = conf['advanced_mode'] parser = argparse.ArgumentParser( description='Blockstack cli version {}'.format(config.VERSION)) parser.register('action', 'parsers', AliasedSubParsersAction) subparsers = parser.add_subparsers(dest='action') add_subparsers(subparsers) if advanced_mode == "on": add_advanced_subparsers(subparsers) # Print default help message, if no argument is given if len(sys.argv) == 1: parser.print_help() sys.exit(1) args, unknown_args = parser.parse_known_args() result = {} conf = config.get_config() blockstack_server = conf['server'] blockstack_port = conf['port'] proxy = client.session(conf=conf, server_host=blockstack_server, server_port=blockstack_port, set_global=True) # start the two background processes (rpc daemon and monitor queue) start_background_daemons() if args.action == 'balance': if not os.path.exists(WALLET_PATH): initialize_wallet() total_balance, addresses = get_total_balance() result['total_balance'] = total_balance if args.details: result['addresses'] = addresses elif args.action == 'price': fqu = str(args.name) check_valid_name(fqu) try: resp = client.get_name_cost(fqu) except socket_error: exit_with_error("Error connecting to server") if 'error' in resp: exit_with_error(resp['error']) data = get_total_fees(resp) result = data elif args.action == 'config': data = {} settings_updated = False data["message"] = "Updated settings for" if args.host is not None: config.update_config('blockstack-client', 'server', args.host) data["message"] += " host" settings_updated = True if args.port is not None: config.update_config('blockstack-client', 'port', args.port) data["message"] += " port" settings_updated = True if args.advanced is not None: if args.advanced != "on" and args.advanced != "off": exit_with_error("Use --advanced=on or --advanced=off") else: config.update_config('blockstack-client', 'advanced_mode', args.advanced) data["message"] += " advanced" settings_updated = True # reload conf conf = config.get_config() if settings_updated: result['message'] = data['message'] else: result['message'] = "No config settings were updated." elif args.action == 'deposit': if not os.path.exists(WALLET_PATH): initialize_wallet() result['message'] = 'Send bitcoins to the address specified.' result['address'], owner_address = get_addresses_from_file() elif args.action == 'import': if not os.path.exists(WALLET_PATH): initialize_wallet() result['message'] = 'Send the name you want to receive to the' result['message'] += ' address specified.' payment_address, result['address'] = get_addresses_from_file() elif args.action == 'names': if not os.path.exists(WALLET_PATH): initialize_wallet() result['names_owned'] = get_all_names_owned() if args.details: result['addresses'] = get_owner_addresses() elif args.action in ('info', 'status', 'ping', 'details'): resp = client.getinfo() result = {} result['server_host'] = conf['server'] result['server_port'] = str(conf['port']) result['cli_version'] = config.VERSION result['advanced_mode'] = conf['advanced_mode'] if 'error' in resp: result['server_alive'] = False result['server_error'] = resp['error'] else: result['server_alive'] = True result['server_version'] = resp['blockstore_version'] try: result['last_block_processed'] = resp['last_block'] except: result['last_block_processed'] = resp['blocks'] result['last_block_seen'] = resp['bitcoind_blocks'] result['consensus_hash'] = resp['consensus'] if advanced_mode == 'on': result['testset'] = resp['testset'] proxy = get_local_proxy() if proxy is not False: current_state = json.loads(proxy.state()) queue = {} pending_queue = [] preorder_queue = [] register_queue = [] update_queue = [] transfer_queue = [] def format_new_entry(entry): new_entry = {} new_entry['name'] = entry['fqu'] confirmations = get_tx_confirmations(entry['tx_hash']) if confirmations is None: confirmations = 0 new_entry['confirmations'] = confirmations return new_entry def format_queue_display(preorder_queue, register_queue): for entry in register_queue: name = entry['name'] for check_entry in preorder_queue: if check_entry['name'] == name: preorder_queue.remove(check_entry) for entry in current_state: if 'type' in entry: if entry['type'] == 'preorder': preorder_queue.append(format_new_entry(entry)) elif entry['type'] == 'register': register_queue.append(format_new_entry(entry)) elif entry['type'] == 'update': update_queue.append(format_new_entry(entry)) elif entry['type'] == 'transfer': transfer_queue.append(format_new_entry(entry)) format_queue_display(preorder_queue, register_queue) if len(preorder_queue) != 0: queue['preorder'] = preorder_queue if len(register_queue) != 0: queue['register'] = register_queue if len(update_queue) != 0: queue['update'] = update_queue if len(transfer_queue) != 0: queue['transfer'] = transfer_queue if queue != {}: result['queue'] = queue elif args.action == 'lookup': data = {} blockchain_record = None fqu = str(args.name) check_valid_name(fqu) try: blockchain_record = client.get_name_blockchain_record(fqu) except socket_error: exit_with_error("Error connecting to server.") if 'value_hash' not in blockchain_record: exit_with_error("%s is not registered" % fqu) data_id = blockchain_record['value_hash'] owner_address = blockchain_record['address'] profile = client.get_immutable(str(args.name), data_id)['data'] zone_file = profile profile = resolve_zone_file_to_profile(profile, owner_address) if not is_profile_in_legacy_format(profile): data['data_record'] = profile data['zone_file'] = zone_file else: data['data_record'] = json.loads(profile) #except Exception as e: # print e # data['data_record'] = None result = data elif args.action == 'whois': data = {} record = None fqu = str(args.name) check_valid_name(fqu) try: record = client.get_name_blockchain_record(fqu) except socket_error: exit_with_error("Error connecting to server.") if 'value_hash' not in record: result['registered'] = False else: result['registered'] = True result['block_preordered_at'] = record['preorder_block_number'] result['block_renewed_at'] = record['last_renewed'] result['owner_address'] = record['address'] result['owner_public_key'] = record['sender_pubkey'] result['owner_script'] = record['sender'] result['preorder_transaction_id'] = record['txid'] elif args.action == 'register': if not os.path.exists(WALLET_PATH): initialize_wallet() result = {} fqu = str(args.name) check_valid_name(fqu) cost = client.get_name_cost(fqu) if 'error' in cost: exit_with_error(cost['error']) if nameRegistered(fqu): exit_with_error("%s is already registered." % fqu) if not walletUnlocked(): unlock_wallet() fees = get_total_fees(cost) try: cost = fees['total_estimated_cost'] input_prompt = "Registering %s will cost %s BTC." % (fqu, cost) input_prompt += " Continue? (y/n): " user_input = raw_input(input_prompt) user_input = user_input.lower() if user_input != 'y': print "Not registering." exit(0) except KeyboardInterrupt: print "\nExiting." exit(0) payment_address, owner_address = get_addresses_from_file() if not hasEnoughBalance(payment_address, fees['total_estimated_cost']): msg = "Address %s doesn't have enough balance." % payment_address exit_with_error(msg) if recipientNotReady(owner_address): msg = "Address %s owns too many names already." % owner_address exit_with_error(msg) if dontuseAddress(payment_address): msg = "Address %s has pending transactions." % payment_address msg += " Wait and try later." exit_with_error(msg) proxy = get_local_proxy() try: resp = proxy.preorder(fqu) except: exit_with_error("Error talking to server, try again.") if 'success' in resp and resp['success']: result = resp else: if 'error' in resp: exit_with_error(resp['error']) if 'message' in resp: exit_with_error(resp['message']) elif args.action == 'update': if not os.path.exists(WALLET_PATH): initialize_wallet() fqu = str(args.name) check_valid_name(fqu) user_data = str(args.data) try: user_data = json.loads(user_data) except: exit_with_error("Data is not in JSON format.") tests_for_update_and_transfer(fqu) if profileonBlockchain(fqu, user_data): msg = "Data is same as current data record, update not needed." exit_with_error(msg) if not walletUnlocked(): unlock_wallet() proxy = get_local_proxy() try: resp = proxy.update(fqu, user_data) except: exit_with_error("Error talking to server, try again.") if 'success' in resp and resp['success']: result = resp else: if 'error' in resp: exit_with_error(resp['error']) if 'message' in resp: exit_with_error(resp['message']) elif args.action == 'transfer': if not os.path.exists(WALLET_PATH): initialize_wallet() fqu = str(args.name) check_valid_name(fqu) transfer_address = str(args.address) tests_for_update_and_transfer(fqu, transfer_address=transfer_address) if not walletUnlocked(): unlock_wallet() proxy = get_local_proxy() try: resp = proxy.transfer(fqu, transfer_address) except: exit_with_error("Error talking to server, try again.") if 'success' in resp and resp['success']: result = resp else: if 'error' in resp: exit_with_error(resp['error']) if 'message' in resp: exit_with_error(resp['message']) # ---------------------- Advanced options --------------------------------- elif args.action == 'wallet': if not os.path.exists(WALLET_PATH): result = initialize_wallet() else: unlock_wallet(display_enabled=True) elif args.action == 'consensus': if args.block_height is None: # by default get last indexed block resp = client.getinfo() if 'error' in resp: exit_with_error("Error connecting to server.") elif 'last_block' in resp or 'blocks' in resp: if 'last_block' in resp: args.block_height = client.getinfo()['last_block'] elif 'blocks' in resp: args.block_height = client.getinfo()['blocks'] else: result['error'] = "Server is indexing. Try again" exit(0) resp = client.get_consensus_at(int(args.block_height)) data = {} data['consensus'] = resp data['block_height'] = args.block_height result = data elif args.action == 'register_tx': result = client.register(str(args.name), str(args.privatekey), str(args.addr), tx_only=True) elif args.action == 'register_subsidized': result = client.register_subsidized(str(args.name), str(args.privatekey), str(args.addr), str(args.subsidy_key)) elif args.action == 'update_tx': txid = None if args.txid is not None: txid = str(args.txid) result = client.update(str(args.name), str(args.record_json), str(args.privatekey), txid=txid, tx_only=True) elif args.action == 'update_subsidized': txid = None if args.txid is not None: txid = str(args.txid) result = client.update_subsidized(str(args.name), str(args.record_json), str(args.public_key), str(args.subsidy_key), txid=txid) elif args.action == 'transfer_tx': keepdata = False if args.keepdata.lower() not in ["on", "false"]: print >> sys.stderr, "Pass 'true' or 'false' for keepdata" sys.exit(1) if args.keepdata.lower() == "on": keepdata = True result = client.transfer(str(args.name), str(args.address), keepdata, str(args.privatekey), tx_only=True) elif args.action == 'preorder': register_addr = None if args.address is not None: register_addr = str(args.address) result = client.preorder(str(args.name), str(args.privatekey), register_addr=register_addr) elif args.action == 'preorder_tx': register_addr = None if args.address is not None: register_addr = str(args.address) result = client.preorder(str(args.name), str(args.privatekey), register_addr=register_addr, tx_only=True) elif args.action == 'preorder_subsidized': result = client.preorder_subsidized(str(args.name), str(args.public_key), str(args.address), str(args.subsidy_key)) elif args.action == 'transfer_subsidized': keepdata = False if args.keepdata.lower() not in ["on", "false"]: print >> sys.stderr, "Pass 'true' or 'false' for keepdata" sys.exit(1) if args.keepdata.lower() == "on": keepdata = True result = client.transfer_subsidized(str(args.name), str(args.address), keepdata, str(args.public_key), str(args.subsidy_key)) elif args.action == 'renew': result = client.renew(str(args.name), str(args.privatekey)) elif args.action == 'renew_tx': result = client.renew(str(args.name), str(args.privatekey), tx_only=True) elif args.action == 'renew_subsidized': result = client.renew_subsidized(str(args.name), str(args.public_key), str(args.subsidy_key)) elif args.action == 'revoke': result = client.revoke(str(args.name), str(args.privatekey)) elif args.action == 'revoke_tx': result = client.revoke(str(args.name), str(args.privatekey), tx_only=True) elif args.action == 'revoke_subsidized': result = client.revoke_subsidized(str(args.name), str(args.public_key), str(args.subsidy_key)) elif args.action == 'name_import': result = client.name_import(str(args.name), str(args.address), str(args.hash), str(args.privatekey)) elif args.action == 'namespace_preorder': reveal_addr = None if args.address is not None: reveal_addr = str(args.address) result = client.namespace_preorder(str(args.namespace_id), str(args.privatekey), reveal_addr=reveal_addr) elif args.action == 'namespace_reveal': bucket_exponents = args.bucket_exponents.split(',') if len(bucket_exponents) != 16: raise Exception("bucket_exponents must be a 16-value CSV \ of integers") for i in xrange(0, len(bucket_exponents)): try: bucket_exponents[i] = int(bucket_exponents[i]) except: raise Exception("bucket_exponents must contain integers in \ range [0, 16)") lifetime = int(args.lifetime) if lifetime < 0: lifetime = 0xffffffff # means "infinite" to blockstack-server result = client.namespace_reveal(str(args.namespace_id), str(args.addr), lifetime, int(args.coeff), int(args.base), bucket_exponents, int(args.nonalpha_discount), int(args.no_vowel_discount), str(args.privatekey)) elif args.action == 'namespace_ready': result = client.namespace_ready(str(args.namespace_id), str(args.privatekey)) elif args.action == 'put_mutable': result = client.put_mutable(str(args.name), str(args.data_id), str(args.data), str(args.privatekey)) elif args.action == 'put_immutable': result = client.put_immutable(str(args.name), str(args.data), str(args.privatekey), conf=conf) elif args.action == 'get_mutable': result = client.get_mutable(str(args.name), str(args.data_id), conf=conf) elif args.action == 'get_immutable': result = client.get_immutable(str(args.name), str(args.hash)) elif args.action == 'delete_immutable': result = client.delete_immutable(str(args.name), str(args.hash), str(args.privatekey)) elif args.action == 'delete_mutable': result = client.delete_mutable(str(args.name), str(args.data_id), str(args.privatekey)) elif args.action == 'get_name_blockchain_record': result = client.get_name_blockchain_record(str(args.name)) elif args.action == 'get_namespace_blockchain_record': result = client.get_namespace_blockchain_record(str(args.namespace_id)) elif args.action == 'lookup_snv': result = client.lookup_snv(str(args.name), int(args.block_id), str(args.consensus_hash)) elif args.action == 'get_name_record': result = client.get_name_record(str(args.name)) elif args.action == 'get_names_owned_by_address': result = client.get_names_owned_by_address(str(args.address)) elif args.action == 'get_namespace_cost': result = client.get_namespace_cost(str(args.namespace_id)) elif args.action == 'get_all_names': offset = None count = None if args.offset is not None: offset = int(args.offset) if args.count is not None: count = int(args.count) result = client.get_all_names(offset, count) elif args.action == 'get_names_in_namespace': offset = None count = None if args.offset is not None: offset = int(args.offset) if args.count is not None: count = int(args.count) result = client.get_names_in_namespace(str(args.namespace_id), offset, count) elif args.action == 'get_nameops_at': result = client.get_nameops_at(int(args.block_id)) print_result(result)
""" import os import sys import json import unittest from blockstack_client import client from blockstack_client.utils import print_result as pprint from blockstack_client.config import BLOCKSTACKD_SERVER, BLOCKSTACKD_PORT, CONFIG_DIR # start session if not os.path.exists( CONFIG_DIR ): os.makedirs( CONFIG_DIR ) client.session(server_host=BLOCKSTACKD_SERVER, server_port=BLOCKSTACKD_PORT) test_names = ["muneeb.id", "fredwilson.id"] class BlockstackClientTest(unittest.TestCase): def tearDown(self): pass def test_ping(self): """ Check ping """ resp = client.ping()