Add eth utils and readme

This commit is contained in:
Brian Ford 2020-07-08 21:19:42 -04:00
parent 19263bba9e
commit c011a12b48
16 changed files with 275 additions and 5 deletions

17
README.md Normal file
View File

@ -0,0 +1,17 @@
# Chainwalker Utilities
This repo is home to Flipsides chainwalkers python utilities package. A central repo that packeges up various python modules that can be used across chainwalkers projects.
## Modules
### Tendermint Utils
Collection of common methods used to interact with tendermint based chains (Cosmos, Kava, Binance)
### Eth utils
Collection of common methods used across eth based chains
## Install
`pip install git+ssh://git@github.com/FlipsideCrypto/chainwalkers-utils.git`

View File

@ -0,0 +1 @@
from eth_utils.jsonrpc import JsonRpcCaller

View File

@ -0,0 +1,7 @@
def hex_to_decimal(hex_value):
if hex_value == '0x':
return 0
return int(hex_value, 16)
def decimal_to_hex(decimal):
return hex(decimal)

View File

@ -0,0 +1,62 @@
import requests
import json
import base64
import time
class RpcCallFailedException(Exception):
pass
class JsonRpcCaller(object):
def __init__(self, node_url, user=None, password=None, tls=False, tlsVerify=False):
self.url = node_url
self.user = user
self.password = password
self.tls = tls
self.tlsVerify = tlsVerify
def _make_rpc_call(self, headers, payload, json):
try:
response = requests.post(
self.url,
headers=headers,
data=payload,
json=json,
verify=(self.tls and self.tlsVerify)
)
except Exception as e:
raise RpcCallFailedException(e)
if response.status_code != 200:
raise RpcCallFailedException("Invalid status code: %s" % response.status_code)
responseJson = response.json(parse_float=lambda f: f)
if type(responseJson) != list:
if "error" in responseJson and responseJson["error"] is not None:
raise RpcCallFailedException("RPC call error: %s" % responseJson["error"])
else:
return responseJson.get('result')
else:
result = []
for subResult in responseJson:
if "error" in subResult and subResult["error"] is not None:
raise RpcCallFailedException("RPC call error: %s" % subResult["error"])
else:
result.append(subResult["result"])
return result
def call(self, method, params=None, query=None):
if params is None:
params = []
headers = {'content-type': 'application/json'}
payload = json.dumps({"jsonrpc": "2.0", "id": "0", "method": method, "params": params})
if query: # GQL Hack
return self._make_rpc_call(headers, payload=None, json={'query': query})
return self._make_rpc_call(headers, payload, json=None)
def bulk_call(self, methodParamsTuples):
headers = {'content-type': 'application/json'}
payload = json.dumps([{"jsonrpc": "2.0", "id": "0", "method": method, "params": params}
for method, params in methodParamsTuples])
return self._make_rpc_call(headers, payload)

View File

@ -1,4 +1,4 @@
Metadata-Version: 1.0 Metadata-Version: 2.1
Name: chainwalkers-utils Name: chainwalkers-utils
Version: 0.0.4 Version: 0.0.4
Summary: Collection of utilities to be used across chainwalkers repos Summary: Collection of utilities to be used across chainwalkers repos
@ -6,5 +6,22 @@ Home-page: git@github.com:FlipsideCrypto/chainwalkers-utils.git
Author: Brian Ford Author: Brian Ford
Author-email: brian@flipsidecrypto.com Author-email: brian@flipsidecrypto.com
License: unlicense License: unlicense
Description: UNKNOWN Description: # Chainwalker Utilities
This repo is home to Flipsides chainwalkers python utilities package. A central repo that packeges up various python modules that can be used across chainwalkers projects.
## Modules
### Tendermint Utils
Collection of common methods used to interact with tendermint based chains (Cosmos, Kava, Binance)
### Eth utils
Collection of common methods used across eth based chains
## Install
`pip install git+ssh://git@github.com/FlipsideCrypto/chainwalkers-utils.git`
Platform: UNKNOWN Platform: UNKNOWN
Description-Content-Type: text/markdown

View File

@ -1,8 +1,12 @@
README.md
setup.py setup.py
chainwalkers_utils.egg-info/PKG-INFO chainwalkers_utils.egg-info/PKG-INFO
chainwalkers_utils.egg-info/SOURCES.txt chainwalkers_utils.egg-info/SOURCES.txt
chainwalkers_utils.egg-info/dependency_links.txt chainwalkers_utils.egg-info/dependency_links.txt
chainwalkers_utils.egg-info/not-zip-safe chainwalkers_utils.egg-info/not-zip-safe
chainwalkers_utils.egg-info/top_level.txt chainwalkers_utils.egg-info/top_level.txt
tendermint/__init__.py eth_utils/__init__.py
tendermint/rpc.py eth_utils/decimals.py
eth_utils/jsonrpc.py
tendermint_utils/__init__.py
tendermint_utils/rpc.py

View File

@ -1 +1,2 @@
tendermint eth_utils
tendermint_utils

Binary file not shown.

1
eth_utils/__init__.py Normal file
View File

@ -0,0 +1 @@
from eth_utils.jsonrpc import JsonRpcCaller

7
eth_utils/decimals.py Normal file
View File

@ -0,0 +1,7 @@
def hex_to_decimal(hex_value):
if hex_value == '0x':
return 0
return int(hex_value, 16)
def decimal_to_hex(decimal):
return hex(decimal)

62
eth_utils/jsonrpc.py Normal file
View File

@ -0,0 +1,62 @@
import requests
import json
import base64
import time
class RpcCallFailedException(Exception):
pass
class JsonRpcCaller(object):
def __init__(self, node_url, user=None, password=None, tls=False, tlsVerify=False):
self.url = node_url
self.user = user
self.password = password
self.tls = tls
self.tlsVerify = tlsVerify
def _make_rpc_call(self, headers, payload, json):
try:
response = requests.post(
self.url,
headers=headers,
data=payload,
json=json,
verify=(self.tls and self.tlsVerify)
)
except Exception as e:
raise RpcCallFailedException(e)
if response.status_code != 200:
raise RpcCallFailedException("Invalid status code: %s" % response.status_code)
responseJson = response.json(parse_float=lambda f: f)
if type(responseJson) != list:
if "error" in responseJson and responseJson["error"] is not None:
raise RpcCallFailedException("RPC call error: %s" % responseJson["error"])
else:
return responseJson.get('result')
else:
result = []
for subResult in responseJson:
if "error" in subResult and subResult["error"] is not None:
raise RpcCallFailedException("RPC call error: %s" % subResult["error"])
else:
result.append(subResult["result"])
return result
def call(self, method, params=None, query=None):
if params is None:
params = []
headers = {'content-type': 'application/json'}
payload = json.dumps({"jsonrpc": "2.0", "id": "0", "method": method, "params": params})
if query: # GQL Hack
return self._make_rpc_call(headers, payload=None, json={'query': query})
return self._make_rpc_call(headers, payload, json=None)
def bulk_call(self, methodParamsTuples):
headers = {'content-type': 'application/json'}
payload = json.dumps([{"jsonrpc": "2.0", "id": "0", "method": method, "params": params}
for method, params in methodParamsTuples])
return self._make_rpc_call(headers, payload)

View File

@ -1,9 +1,14 @@
import setuptools import setuptools
with open("README.md", "r") as fh:
long_description = fh.read()
setuptools.setup( setuptools.setup(
name='chainwalkers_utils', name='chainwalkers_utils',
version='0.0.4', version='0.0.4',
description='Collection of utilities to be used across chainwalkers repos', description='Collection of utilities to be used across chainwalkers repos',
long_description=long_description,
long_description_content_type="text/markdown",
url='git@github.com:FlipsideCrypto/chainwalkers-utils.git', url='git@github.com:FlipsideCrypto/chainwalkers-utils.git',
author='Brian Ford', author='Brian Ford',
author_email='brian@flipsidecrypto.com', author_email='brian@flipsidecrypto.com',

View File

@ -0,0 +1 @@
from tendermint.rpc import TendermintRPC

85
tendermint_utils/rpc.py Normal file
View File

@ -0,0 +1,85 @@
import json
import requests
class TendermintRPC:
def __init__(self, node_url):
self.node_url = node_url
def get_block_height(self):
try:
response = requests.get(self.node_url+ '/abci_info?')
response.raise_for_status()
data = response.json()
return data['result']['response']['last_block_height']
except Exception as err:
print(f'An error occured retrieving the latest block height: {err}')
def get_block(self, height):
try:
response = requests.get(self.node_url + '/block?height=' + str(height))
response.raise_for_status()
data = response.json()
block = self.init_block(data['result'])
block_results = self.get_block_results(height)
# Capture transactions and underlying events
block_transactions = self.get_transactions_by_block(height)
if block_transactions['txs']:
for tx in block_transactions['txs']:
block_tx = self.get_transactions_by_hash(tx['hash'])
block.add_transaction(block_tx)
# Capture begin block events ()
if block_results['results']['begin_block']:
for event in block_results['results']['begin_block']['events']:
block.begin_block.append(event)
block.end_block = block_results['results']['end_block']
block_validators = self.get_block_validators(height)
for validator in block_validators['validators']:
block.validators.append(validator)
return block
except Exception as err:
print(f'An error occured retrieving block: {err}')
def get_block_results(self, height):
try:
response = requests.get(self.node_url + '/block_results?height=' + str(height))
response.raise_for_status()
data = response.json()
return data['result']
except Exception as err:
print(f'An error occured retrieving the results of block height: {err}')
# Need ANKR to turn on indexing at node level for this call to work properly
def get_transactions_by_block(self, height):
try:
response = requests.get(self.node_url + '/tx_search?query=\"tx.height=' + str(height) + '\"&prove=true')
response.raise_for_status()
data = response.json()
return data['result']
except Exception as err:
print(f'An error occured retrieving the transactions in block: {err}')
def get_transactions_by_hash(self, tx_hash):
try:
response = requests.get(self.node_url + '/tx?hash=' + tx_hash)
response.raise_for_status()
data = response.json()
return data
except Exception as err:
print(f'An error occured retrieving the transaction by hash: {err}')
# Currently returning the following response "Height must be less than or equal to the current blockchain height"
def get_block_validators(self, height):
try:
response = requests.get(self.node_url + '/validators?height=' + str(height))
response.raise_for_status()
data = response.json()
return data['result']
except Exception as err:
print(f'An error occured retrieving the validators for block height: {err}')