diff options
-rw-r--r-- | rpcblockchainexplorer/api.py | 109 |
1 files changed, 62 insertions, 47 deletions
diff --git a/rpcblockchainexplorer/api.py b/rpcblockchainexplorer/api.py index d7a6d32..77a0c4a 100644 --- a/rpcblockchainexplorer/api.py +++ b/rpcblockchainexplorer/api.py @@ -19,6 +19,17 @@ import functools # pretty lame but it works. from bitcoin.rpc import Proxy +from bitcoin.core import ( + # bytes to little endian hex + b2lx, + + # little endian hex to bytes + lx, + + # bytes to hex + b2x, +) + # because of the interwebs... from flask import ( Blueprint, @@ -38,7 +49,6 @@ ALLOWED_COMMANDS = [ "getchaintips", "getdifficulty", "getmempoolinfo", - "gettxout", # network "getconnectioncount", @@ -55,6 +65,22 @@ ALLOWED_COMMANDS = [ # to construct valid urls. API_ENDPOINT_TEMPLATE = "/{command_name}" +# Some of the user-supplied values need to be converted. Use this table to +# determine how to convert values automatically. +CONVERSION_TABLE = { + # convert to bytes + "block_hash": lx, + "txid": lx, +} + +def converter(name, value): + """ + Convert from user-given values into an acceptable internal type. + """ + + if name in CONVERSION_TABLE.keys(): + return CONVERSION_TABLE[name](value) + def create_api_endpoints(commands=ALLOWED_COMMANDS): """ Automatically generate all API endpoints by (ab)using python-bitcoinlib. @@ -99,52 +125,41 @@ def create_api_endpoints(commands=ALLOWED_COMMANDS): # endpoint is always based on the command name api_uri = API_ENDPOINT_TEMPLATE.format(command_name=command) - def some_command_endpoint(): - """ - Autogenerated API endpoint. - """ - - # Allow the defaults or user-passed values to be used. - params = {} - - # Use request.args to get the user-passed value, otherwise use the - # default as defined in python-bitcoinlib. - for (argument_name, default_value) in keyword_arguments.items(): - params[argument_name] = request.args.get(argument_name, default_value) - - # Get a reference to the command, if any. - if command in Proxy.__dict__.keys(): - callable_function = g.bitcoin_rpc_client.__dict__[command] - rpc_function = functools.partial(callable_function) - else: - callable_function = g.bitcoin_rpc_client._call - _self = g.bitcoin_rpc_client - rpc_function = functools.partial(callable_function, command) - - # Call the RPC service command and pass in all of the given - # parameters. - results = rpc_function(**params) - - # That's all, folks. - return repr(results) - - #temporary_function = types.FunctionType( - # # TODO: use func_name in python2 - # copy(some_command_endpoint.__code__), - # - # # use func_globals in python2 - # copy(some_command_endpoint.__globals__), - # - # name=command, - # - # # use func_defaults in python2 - # argdefs=copy(some_command_endpoint.__defaults__), - # - # # use just "closure" in python2 - # closure=copy(some_command_endpoint.__closure__), - #) - - api.add_url_rule(api_uri, endpoint=command, view_func=some_command_endpoint, methods=["GET"]) + def make_command_endpoint(command, keyword_arguments): + def some_command_endpoint(): + """ + Autogenerated API endpoint. + """ + + # Allow the defaults or user-passed values to be used. + params = {} + + # Use request.args to get the user-passed value, otherwise use the + # default as defined in python-bitcoinlib. + for (argument_name, default_value) in keyword_arguments.items(): + value = request.args.get(argument_name, default_value) + possibly_converted_value = converter(argument_name, value) + params[argument_name] = possibly_converted_value + + # Get a reference to the command, if any. + if command in Proxy.__dict__.keys(): + callable_function = getattr(g.bitcoin_rpc_client, command) + rpc_function = functools.partial(callable_function) + else: + callable_function = g.bitcoin_rpc_client._call + _self = g.bitcoin_rpc_client + rpc_function = functools.partial(callable_function, command) + + # Call the RPC service command and pass in all of the given + # parameters. + results = rpc_function(**params) + + # That's all, folks. + return repr(results) + return some_command_endpoint + + view_func = make_command_endpoint(command, keyword_arguments) + api.add_url_rule(api_uri, endpoint=command, view_func=view_func, methods=["GET"]) # Always create all the endpoints when importing this module. This will attach # the endpoints to the blueprint, which can then be attached to flask |