From 419746d017404c97d950f1355eb60c66c0c9f2fd Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Sun, 11 Oct 2020 18:31:17 -0300 Subject: [PATCH] Add API calls These are similar to (but not identical to) the old explorer; care was taken to ensure that emission and circulating_supply endpoints return the same values as before as these are likely being used externally. --- observer.py | 101 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 87 insertions(+), 14 deletions(-) diff --git a/observer.py b/observer.py index 35a712e..e06fe83 100644 --- a/observer.py +++ b/observer.py @@ -433,6 +433,22 @@ def parse_txs(txs_rpc): return txs_rpc['txs'] +def get_block_txs_future(lmq, lokid, block): + hashes = [] + if 'tx_hashes' in block: + hashes += block['tx_hashes'] + hashes.append(block['block_header']['miner_tx_hash']) + if 'info' not in block: + try: + block['info'] = json.loads(block["json"]) + del block['info']['miner_tx'] # Doesn't include enough for us, we fetch it separately with extra interpretation instead + del block["json"] + except Exception as e: + print("Something getting wrong: cannot parse block json for block {}: {}".format(block_height, e), file=sys.stderr) + + return tx_req(lmq, lokid, hashes, cache_key='block') + + @app.route('/block/') @app.route('/block//') @app.route('/block/') @@ -458,20 +474,7 @@ def show_block(height=None, hash=None, more_details=False): next_block = None block_height = block['block_header']['height'] - txs = None - hashes = [] - if 'tx_hashes' in block: - hashes += block['tx_hashes'] - hashes.append(block['block_header']['miner_tx_hash']) - if 'info' not in block: - try: - block['info'] = json.loads(block["json"]) - del block['info']['miner_tx'] # Doesn't include enough for us, we fetch it separately with extra interpretation instead - del block["json"] - except Exception as e: - print("Something getting wrong: cannot parse block json for block {}: {}".format(block_height, e), file=sys.stderr) - - txs = tx_req(lmq, lokid, hashes, cache_key='block') + txs = get_block_txs_future(lmq, lokid, block) if info.get()['height'] > 1 + block_height: next_block = block_header_req(lmq, lokid, '{}'.format(block_height + 1)) @@ -637,3 +640,73 @@ def search(): id=val, ) +@app.route('/api/networkinfo') +def api_networkinfo(): + lmq, lokid = lmq_connection() + info = FutureJSON(lmq, lokid, 'rpc.get_info', 1) + hfinfo = FutureJSON(lmq, lokid, 'rpc.hard_fork_info', 10) + + info = info.get() + data = {**info} + hfinfo = hfinfo.get() + data['current_hf_version'] = hfinfo['version'] + data['next_hf_height'] = hfinfo['earliest_height'] if 'earliest_height' in hfinfo else None + return flask.jsonify({"data": data, "status": "OK"}) + + +@app.route('/api/emission') +def api_emission(): + lmq, lokid = lmq_connection() + info = FutureJSON(lmq, lokid, 'rpc.get_info', 1) + coinbase = FutureJSON(lmq, lokid, 'admin.get_coinbase_tx_sum', 10, timeout=1, fail_okay=True, + args={"height":0, "count":2**31-1}).get() + if not coinbase: + return flask.jsonify(None) + info = info.get() + return flask.jsonify({ + "data": { + "blk_no": info['height'] - 1, + "burn": coinbase["burn_amount"], + "circulating_supply": coinbase["emission_amount"] - coinbase["burn_amount"], + "coinbase": coinbase["emission_amount"] - coinbase["burn_amount"], + "emission": coinbase["emission_amount"], + "fee": coinbase["fee_amount"] + }, + "status": "success" + }) + + +@app.route('/api/circulating_supply') +def api_circulating_supply(): + lmq, lokid = lmq_connection() + coinbase = FutureJSON(lmq, lokid, 'admin.get_coinbase_tx_sum', 10, timeout=1, fail_okay=True, + args={"height":0, "count":2**31-1}).get() + return flask.jsonify((coinbase["emission_amount"] - coinbase["burn_amount"]) // 1000000000 if coinbase else None) + + +# FIXME: need better error handling here +@app.route('/api/transaction/') +def api_tx(txid): + lmq, lokid = lmq_connection() + tx = tx_req(lmq, lokid, [txid]).get() + txs = parse_txs(tx) + return flask.jsonify({ + "status": tx['status'], + "data": (txs[0] if txs else None), + }) + +@app.route('/api/block/') +@app.route('/api/block/') +def api_block(blkid=None, height=None): + lmq, lokid = lmq_connection() + block = block_with_txs_req(lmq, lokid, blkid if blkid is not None else height).get() + txs = get_block_txs_future(lmq, lokid, block) + + if 'block_header' in block: + data = block['block_header'].copy() + data["txs"] = parse_txs(txs.get()).copy() + + return flask.jsonify({ + "status": block['status'], + "data": data, + })