From 900bcdc2edfe9af63555ac9e2f87b1ce3c016d46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sa=C5=82aban?= Date: Sun, 14 Jan 2018 23:51:18 +0100 Subject: [PATCH] Add daemon API sketch --- monero/__init__.py | 1 + monero/backends/jsonrpc.py | 51 ++++++++++++++++++++++++++++++++++++-- monero/daemon.py | 6 +++++ utils/daemonping.py | 36 +++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 monero/daemon.py create mode 100644 utils/daemonping.py diff --git a/monero/__init__.py b/monero/__init__.py index 2f73d17..3e96fe8 100644 --- a/monero/__init__.py +++ b/monero/__init__.py @@ -1,5 +1,6 @@ from .address import Address from .account import Account +from .daemon import Daemon from .wallet import Wallet from .numbers import from_atomic, to_atomic, as_monero from . import prio diff --git a/monero/backends/jsonrpc.py b/monero/backends/jsonrpc.py index 007a866..3410c30 100644 --- a/monero/backends/jsonrpc.py +++ b/monero/backends/jsonrpc.py @@ -15,6 +15,53 @@ from ..transaction import Transaction, Payment, Transfer _log = logging.getLogger(__name__) +class JSONRPCDaemon(object): + def __init__(self, protocol='http', host='127.0.0.1', port=18081, path='/json_rpc'): + self.url = '{protocol}://{host}:{port}/json_rpc'.format( + protocol=protocol, + host=host, + port=port) + _log.debug("JSONRPC daemon backend URL: {url}".format(url=self.url)) + + def get_info(self): + info = self.raw_jsonrpc_request('get_info') + return info + + def raw_jsonrpc_request(self, method, params=None): + hdr = {'Content-Type': 'application/json'} + data = {'jsonrpc': '2.0', 'id': 0, 'method': method, 'params': params or {}} + _log.debug(u"Method: {method}\nParams:\n{params}".format( + method=method, + params=pprint.pformat(params))) + rsp = requests.post(self.url, headers=hdr, data=json.dumps(data)) + if rsp.status_code != 200: + raise RPCError("Invalid HTTP status {code} for method {method}.".format( + code=rsp.status_code, + method=method)) + result = rsp.json() + _ppresult = pprint.pformat(result) + _log.debug(u"Result:\n{result}".format(result=_ppresult)) + + if 'error' in result: + err = result['error'] + _log.error(u"JSON RPC error:\n{result}".format(result=_ppresult)) +# if err['code'] in _err2exc: +# raise _err2exc[err['code']](err['message']) +# else: +# raise RPCError( +# "Method '{method}' failed with RPC Error of unknown code {code}, " +# "message: {message}".format(method=method, data=data, result=result, **err)) + raise RPCError( + "Method '{method}' failed with RPC Error of unknown code {code}, " + "message: {message}".format(method=method, data=data, result=result, **err)) +# +# +# + return result['result'] + + + + class JSONRPCWallet(object): _master_address = None _addresses = None @@ -24,10 +71,10 @@ class JSONRPCWallet(object): protocol=protocol, host=host, port=port) - _log.debug("JSONRPC backend URL: {url}".format(url=self.url)) + _log.debug("JSONRPC wallet backend URL: {url}".format(url=self.url)) self.user = user self.password = password - _log.debug("JSONRPC backend auth: '{user}'/'{stars}'".format( + _log.debug("JSONRPC wallet backend auth: '{user}'/'{stars}'".format( user=user, stars=('*' * len(password)) if password else '')) def get_view_key(self): diff --git a/monero/daemon.py b/monero/daemon.py new file mode 100644 index 0000000..36ad4e7 --- /dev/null +++ b/monero/daemon.py @@ -0,0 +1,6 @@ +class Daemon(object): + def __init__(self, backend): + self._backend = backend + + def get_info(self): + return self._backend.get_info() diff --git a/utils/daemonping.py b/utils/daemonping.py new file mode 100644 index 0000000..959cbcd --- /dev/null +++ b/utils/daemonping.py @@ -0,0 +1,36 @@ +import argparse +import logging +import operator +import re + +from monero.backends.jsonrpc import JSONRPCDaemon +from monero import Daemon + +def url_data(url): + gs = re.compile( + r'^(?P[^:\s]+)(?::(?P[0-9]+))?$' + ).match(url).groupdict() + return dict(filter(operator.itemgetter(1), gs.items())) + +def get_daemon(): + argsparser = argparse.ArgumentParser(description="Display daemon info") + argsparser.add_argument('daemon_rpc_url', nargs='?', type=url_data, default='127.0.0.1:18081', + help="Daemon RPC URL [host[:port]]") + argsparser.add_argument('-v', dest='verbosity', action='count', default=0, + help="Verbosity (repeat to increase; -v for INFO, -vv for DEBUG") + args = argsparser.parse_args() + level = logging.WARNING + if args.verbosity == 1: + level = logging.INFO + elif args.verbosity > 1: + level = logging.DEBUG + logging.basicConfig(level=level, format="%(asctime)-15s %(message)s") + return Daemon(JSONRPCDaemon(**args.daemon_rpc_url)) + +d = get_daemon() +info = d.get_info() +print("Net: {net:>18s}\n" + "Height: {height:10d}\n" + "Difficulty: {difficulty:10d}".format( + net='test' if info['testnet'] else 'live', + **info))