chainlib

Generic blockchain access library and tooling
Log | Files | Refs | README | LICENSE

commit 62123850c87d94b3512d32c85b8b815142c8229e
parent 52426078be1bbe5677d31f6c5a19f7e755003e1b
Author: nolash <dev@holbrook.no>
Date:   Thu, 11 Feb 2021 08:45:26 +0100

Rename package

Diffstat:
Rcic_tools/eth/address.py -> chainlib/eth/address.py | 0
Achainlib/eth/block.py | 21+++++++++++++++++++++
Rcic_tools/eth/connection.py -> chainlib/eth/connection.py | 0
Rcic_tools/eth/constant.py -> chainlib/eth/constant.py | 0
Rcic_tools/eth/erc20.py -> chainlib/eth/erc20.py | 0
Rcic_tools/eth/error.py -> chainlib/eth/error.py | 0
Rcic_tools/eth/gas.py -> chainlib/eth/gas.py | 0
Rcic_tools/eth/hash.py -> chainlib/eth/hash.py | 0
Rcic_tools/eth/nonce.py -> chainlib/eth/nonce.py | 0
Rcic_tools/eth/rpc.py -> chainlib/eth/rpc.py | 0
Rcic_tools/eth/runnable/__init__.py -> chainlib/eth/runnable/__init__.py | 0
Rcic_tools/eth/runnable/balance.py -> chainlib/eth/runnable/balance.py | 0
Rcic_tools/eth/runnable/checksum.py -> chainlib/eth/runnable/checksum.py | 0
Rcic_tools/eth/runnable/decode.py -> chainlib/eth/runnable/decode.py | 0
Rcic_tools/eth/runnable/gas.py -> chainlib/eth/runnable/gas.py | 0
Rcic_tools/eth/runnable/subscribe.py -> chainlib/eth/runnable/subscribe.py | 0
Achainlib/eth/runnable/transfer.py | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rcic_tools/eth/tx.py -> chainlib/eth/tx.py | 0
Dcic_tools/cic_eth/runnable/users.py | 252-------------------------------------------------------------------------------
Dcic_tools/eth/runnable/transfer.py | 115-------------------------------------------------------------------------------
Mrequirements.txt | 7-------
Msetup.cfg | 15++++++++-------
22 files changed, 144 insertions(+), 381 deletions(-)

diff --git a/cic_tools/eth/address.py b/chainlib/eth/address.py diff --git a/chainlib/eth/block.py b/chainlib/eth/block.py @@ -0,0 +1,21 @@ +from cic_tools.eth.rpc import jsonrpc_template + + +def block(self): + o = jsonrpc_template() + o['method'] = 'eth_blockNumber' + return o + + +def block_by_hash(self, hsh): + o = jsonrpc_template() + o['method'] = 'eth_getBlock' + o['params'].append(hsh) + return o + + +def block_by_number(self, n): + o = jsonrpc_template() + o['method'] = 'eth_getBlock' + o['params'].append(n) + return o diff --git a/cic_tools/eth/connection.py b/chainlib/eth/connection.py diff --git a/cic_tools/eth/constant.py b/chainlib/eth/constant.py diff --git a/cic_tools/eth/erc20.py b/chainlib/eth/erc20.py diff --git a/cic_tools/eth/error.py b/chainlib/eth/error.py diff --git a/cic_tools/eth/gas.py b/chainlib/eth/gas.py diff --git a/cic_tools/eth/hash.py b/chainlib/eth/hash.py diff --git a/cic_tools/eth/nonce.py b/chainlib/eth/nonce.py diff --git a/cic_tools/eth/rpc.py b/chainlib/eth/rpc.py diff --git a/cic_tools/eth/runnable/__init__.py b/chainlib/eth/runnable/__init__.py diff --git a/cic_tools/eth/runnable/balance.py b/chainlib/eth/runnable/balance.py diff --git a/cic_tools/eth/runnable/checksum.py b/chainlib/eth/runnable/checksum.py diff --git a/cic_tools/eth/runnable/decode.py b/chainlib/eth/runnable/decode.py diff --git a/cic_tools/eth/runnable/gas.py b/chainlib/eth/runnable/gas.py diff --git a/cic_tools/eth/runnable/subscribe.py b/chainlib/eth/runnable/subscribe.py diff --git a/chainlib/eth/runnable/transfer.py b/chainlib/eth/runnable/transfer.py @@ -0,0 +1,115 @@ +#!python3 + +"""Token transfer script + +.. moduleauthor:: Louis Holbrook <dev@holbrook.no> +.. pgp:: 0826EDA1702D1E87C6E2875121D2E7BB88C2A746 + +""" + +# SPDX-License-Identifier: GPL-3.0-or-later + +# standard imports +import os +import json +import argparse +import logging + +# third-party imports +from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer +from crypto_dev_signer.keystore import DictKeystore +from crypto_dev_signer.eth.helper import EthTxExecutor +from hexathon import ( + add_0x, + strip_0x, + ) + +# local imports +from cic_tools.eth.address import to_checksum +from cic_tools.eth.connection import HTTPConnection +from cic_tools.eth.rpc import jsonrpc_template +from cic_tools.eth.nonce import DefaultNonceOracle +from cic_tools.eth.gas import DefaultGasOracle +from cic_tools.eth.erc20 import ERC20TxFactory + + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + +logging.getLogger('web3').setLevel(logging.WARNING) +logging.getLogger('urllib3').setLevel(logging.WARNING) + +default_abi_dir = '/usr/local/share/cic/solidity/abi' +argparser = argparse.ArgumentParser() +argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='Web3 provider url (http only)') +argparser.add_argument('-w', action='store_true', help='Wait for the last transaction to be confirmed') +argparser.add_argument('-ww', action='store_true', help='Wait for every transaction to be confirmed') +argparser.add_argument('-i', '--chain-spec', dest='i', type=str, default='Ethereum:1', help='Chain specification string') +argparser.add_argument('--token-address', required='True', dest='t', type=str, help='Token address') +argparser.add_argument('-a', '--sender-address', dest='s', type=str, help='Sender account address') +argparser.add_argument('-y', '--key-file', dest='y', type=str, help='Ethereum keystore file to use for signing') +argparser.add_argument('--abi-dir', dest='abi_dir', type=str, default=default_abi_dir, help='Directory containing bytecode and abi (default {})'.format(default_abi_dir)) +argparser.add_argument('-u', '--unsafe', dest='u', action='store_true', help='Auto-convert address to checksum adddress') +argparser.add_argument('-v', action='store_true', help='Be verbose') +argparser.add_argument('-vv', action='store_true', help='Be more verbose') +argparser.add_argument('recipient', type=str, help='Recipient account address') +argparser.add_argument('amount', type=int, help='Amount of tokens to mint and gift') +args = argparser.parse_args() + + +if args.vv: + logg.setLevel(logging.DEBUG) +elif args.v: + logg.setLevel(logging.INFO) + +block_all = args.ww +block_last = args.w or block_all + +signer_address = None +keystore = DictKeystore() +if args.y != None: + logg.debug('loading keystore file {}'.format(args.y)) + signer_address = keystore.import_keystore_file(args.y) + logg.debug('now have key for signer address {}'.format(signer_address)) +signer = EIP155Signer(keystore) + +conn = HTTPConnection(args.p) +nonce_oracle = DefaultNonceOracle(signer_address, conn) +gas_oracle = DefaultGasOracle(conn) + +chain_pair = args.i.split(':') +chain_id = int(chain_pair[1]) + +value = args.amount + +g = ERC20TxFactory(signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle, chain_id=chain_id) + + +def balance(token_address, address): + o = g.erc20_balance(token_address, address) + r = conn.do(o) + hx = strip_0x(r) + return int(hx, 16) + + +def main(): + recipient = args.recipient + if not args.u and recipient != add_0x(args.recipient): + raise ValueError('invalid checksum address') + + logg.debug('sender {} balance before: {}'.format(signer_address, balance(args.t, signer_address))) + logg.debug('recipient {} balance before: {}'.format(recipient, balance(args.t, recipient))) + + (tx_hash_hex, o) = g.erc20_transfer(args.t, signer_address, recipient, value) + conn.do(o) + + if block_last: + conn.wait(tx_hash_hex) + logg.debug('sender {} balance after: {}'.format(signer_address, balance(args.t, signer_address))) + logg.debug('recipient {} balance after: {}'.format(recipient, balance(args.t, recipient))) + + print(tx_hash_hex) + + +if __name__ == '__main__': + main() diff --git a/cic_tools/eth/tx.py b/chainlib/eth/tx.py diff --git a/cic_tools/cic_eth/runnable/users.py b/cic_tools/cic_eth/runnable/users.py @@ -1,252 +0,0 @@ -#!/usr/bin/python - -# standard imports -import json -import time -import datetime -import random -import logging -import os -import base64 -import hashlib -import sys -import uuid -import argparse - -# third-party imports -import redis -import vobject -import celery -from faker import Faker -import cic_registry -import confini -from cic_eth.api import Api - -logging.basicConfig(level=logging.DEBUG) -logg = logging.getLogger() - -fake = Faker(['sl', 'en_US', 'no', 'de', 'ro']) - -#f = open('cic.conf', 'r') -#config = json.load(f) -#f.close() -# - -default_config_dir = os.environ.get('CONFINI_DIR', '/usr/local/etc/cic') - -argparser = argparse.ArgumentParser() -argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='Web3 provider url (http only)') -argparser.add_argument('-c', type=str, default=default_config_dir, help='config root to use') -argparser.add_argument('-q', type=str, default='cic-eth', help='Task queue') -argparser.add_argument('-i', '--chain-spec', dest='i', type=str, help='chain spec') -argparser.add_argument('--redis-host-callback', dest='redis_host_callback', default='localhost', type=str, help='redis host to use for callback') -argparser.add_argument('--redis-port-callback', dest='redis_port_callback', default=6379, type=int, help='redis port to use for callback') -argparser.add_argument('--timeout', default=1.0, type=int, help='timeout to wait for account create callback') -argparser.add_argument('-v', action='store_true', help='Be verbose') -argparser.add_argument('-vv', help='be more verbose', action='store_true') -argparser.add_argument('count', help='Number of users to generate', type=int) -args = argparser.parse_args() - -if args.v == True: - logging.getLogger().setLevel(logging.INFO) -elif args.vv == True: - logging.getLogger().setLevel(logging.DEBUG) - -config_dir = os.path.join(args.c) -config = confini.Config(config_dir, os.environ.get('CONFINI_ENV_PREFIX')) -config.process() -args_override = { - 'ETH_PROVIDER': getattr(args, 'p'), - 'CIC_CHAIN_SPEC': getattr(args, 'i'), -} -config.dict_override(args_override, 'cli flag') -logg.debug('config loaded from {}:\n{}'.format(config_dir, config)) - - -dt_now = datetime.datetime.utcnow() -dt_then = dt_now - datetime.timedelta(weeks=150) -ts_now = int(dt_now.timestamp()) -ts_then = int(dt_then.timestamp()) - -queue = args.q - -celery_app = celery.Celery(broker=config.get('CELERY_BROKER_URL'), backend=config.get('CELERY_RESULT_URL')) - -redis_host = config.get('REDIS_HOST') -redis_port = config.get('REDIS_PORT') -redis_db = config.get('REDIS_DB') -redis_channel = str(uuid.uuid4()) -r = redis.Redis(redis_host, redis_port, redis_db) -ps = r.pubsub() -ps.subscribe(redis_channel) -ps.get_message() - -api = Api( - config.get('CIC_CHAIN_SPEC'), - queue=args.q, - callback_param='{}:{}:{}:{}'.format(args.redis_host_callback, args.redis_port_callback, redis_db, redis_channel), - callback_task='cic_eth.callbacks.redis.redis', - callback_queue=queue, - ) - -gift_max = 10000 -gift_factor = (10**9) - -user_count = args.count - -categories = [ - "food/water", - "fuel/energy", - "education", - "health", - "shop", - "environment", - "transport", - "farming/labor", - "savingsgroup", - ] - -phone_idx = [] - - -def genPhoneIndex(phone): - h = hashlib.new('sha256') - h.update(phone.encode('utf-8')) - h.update(b'cic.msisdn') - return h.digest().hex() - - -def genId(addr, typ): - h = hashlib.new('sha256') - h.update(bytes.fromhex(addr[2:])) - h.update(typ.encode('utf-8')) - return h.digest().hex() - - -def genDate(): - - logg.info(ts_then) - ts = random.randint(ts_then, ts_now) - return datetime.datetime.fromtimestamp(ts).timestamp() - - -def genPhone(): - return fake.msisdn() - - -def genPersonal(phone): - fn = fake.first_name() - ln = fake.last_name() - e = fake.email() - - v = vobject.vCard() - first_name = fake.first_name() - last_name = fake.last_name() - v.add('n') - v.n.value = vobject.vcard.Name(family=last_name, given=first_name) - v.add('fn') - v.fn.value = '{} {}'.format(first_name, last_name) - v.add('tel') - v.tel.typ_param = 'CELL' - v.tel.value = phone - v.add('email') - v.email.value = fake.email() - - vcard_serialized = v.serialize() - vcard_base64 = base64.b64encode(vcard_serialized.encode('utf-8')) - - return vcard_base64.decode('utf-8') - - -def genCats(): - i = random.randint(0, 3) - return random.choices(categories, k=i) - - -def genAmount(): - return random.randint(0, gift_max) * gift_factor - - -def gen(): - old_blockchain_address = '0x' + os.urandom(20).hex() - t = api.create_account(register=True) - - ps.get_message() - m = ps.get_message(timeout=args.timeout) - new_blockchain_address = json.loads(m['data']) - - #new_blockchain_address = t.get() - gender = random.choice(['female', 'male', 'other']) - phone = genPhone() - v = genPersonal(phone) - o = { - 'date_registered': genDate(), - 'vcard': v, - 'gender': gender, - 'key': { - 'ethereum': [ - old_blockchain_address, - new_blockchain_address, - ], - }, - 'location': { - 'latitude': str(fake.latitude()), - 'longitude': str(fake.longitude()), - 'external': { # add osm lookup - } - }, - 'selling': genCats(), - } - uid = genId(new_blockchain_address, 'cic.person') - - return (uid, phone, o) - - -def prepareLocalFilePath(datadir, address): - parts = [ - address[:2], - address[2:4], - ] - dirs = '{}/{}/{}'.format( - datadir, - parts[0], - parts[1], - ) - os.makedirs(dirs, exist_ok=True) - return dirs - - -if __name__ == '__main__': - - os.makedirs('data/person', exist_ok=True) - os.makedirs('data/phone', exist_ok=True) - - fa = open('./data/amounts', 'w') - fb = open('./data/addresses', 'w') - - #for i in range(10): - for i in range(int(user_count)): - - (uid, phone, o) = gen() - eth = o['key']['ethereum'][1] - - print(o) - - d = prepareLocalFilePath('./data/person', uid) - f = open('{}/{}'.format(d, uid), 'w') - json.dump(o, f) - f.close() - - pidx = genPhoneIndex(phone) - d = prepareLocalFilePath('./data/phone', uid) - f = open('{}/{}'.format(d, pidx), 'w') - f.write(eth) - f.close() - - amount = genAmount() - fa.write('{},{}\n'.format(eth,amount)) - fb.write('{}\n'.format(eth)) - logg.debug('pidx {}, uid {}, eth {}, amount {}'.format(pidx, uid, eth, amount)) - - fb.close() - fa.close() diff --git a/cic_tools/eth/runnable/transfer.py b/cic_tools/eth/runnable/transfer.py @@ -1,115 +0,0 @@ -#!python3 - -"""Token transfer script - -.. moduleauthor:: Louis Holbrook <dev@holbrook.no> -.. pgp:: 0826EDA1702D1E87C6E2875121D2E7BB88C2A746 - -""" - -# SPDX-License-Identifier: GPL-3.0-or-later - -# standard imports -import os -import json -import argparse -import logging - -# third-party imports -from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer -from crypto_dev_signer.keystore import DictKeystore -from crypto_dev_signer.eth.helper import EthTxExecutor -from hexathon import ( - add_0x, - strip_0x, - ) - -# local imports -from cic_tools.eth.address import to_checksum -from cic_tools.eth.connection import HTTPConnection -from cic_tools.eth.rpc import jsonrpc_template -from cic_tools.eth.nonce import DefaultNonceOracle -from cic_tools.eth.gas import DefaultGasOracle -from cic_tools.eth.erc20 import ERC20TxFactory - - -logging.basicConfig(level=logging.WARNING) -logg = logging.getLogger() - -logging.getLogger('web3').setLevel(logging.WARNING) -logging.getLogger('urllib3').setLevel(logging.WARNING) - -default_abi_dir = '/usr/local/share/cic/solidity/abi' -argparser = argparse.ArgumentParser() -argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='Web3 provider url (http only)') -argparser.add_argument('-w', action='store_true', help='Wait for the last transaction to be confirmed') -argparser.add_argument('-ww', action='store_true', help='Wait for every transaction to be confirmed') -argparser.add_argument('-i', '--chain-spec', dest='i', type=str, default='Ethereum:1', help='Chain specification string') -argparser.add_argument('--token-address', required='True', dest='t', type=str, help='Token address') -argparser.add_argument('-a', '--sender-address', dest='s', type=str, help='Sender account address') -argparser.add_argument('-y', '--key-file', dest='y', type=str, help='Ethereum keystore file to use for signing') -argparser.add_argument('--abi-dir', dest='abi_dir', type=str, default=default_abi_dir, help='Directory containing bytecode and abi (default {})'.format(default_abi_dir)) -argparser.add_argument('-u', '--unsafe', dest='u', action='store_true', help='Auto-convert address to checksum adddress') -argparser.add_argument('-v', action='store_true', help='Be verbose') -argparser.add_argument('-vv', action='store_true', help='Be more verbose') -argparser.add_argument('recipient', type=str, help='Recipient account address') -argparser.add_argument('amount', type=int, help='Amount of tokens to mint and gift') -args = argparser.parse_args() - - -if args.vv: - logg.setLevel(logging.DEBUG) -elif args.v: - logg.setLevel(logging.INFO) - -block_last = args.w -block_all = args.ww - -signer_address = None -keystore = DictKeystore() -if args.y != None: - logg.debug('loading keystore file {}'.format(args.y)) - signer_address = keystore.import_keystore_file(args.y) - logg.debug('now have key for signer address {}'.format(signer_address)) -signer = EIP155Signer(keystore) - -conn = HTTPConnection(args.p) -nonce_oracle = DefaultNonceOracle(signer_address, conn) -gas_oracle = DefaultGasOracle(conn) - -chain_pair = args.i.split(':') -chain_id = int(chain_pair[1]) - -value = args.amount - -g = ERC20TxFactory(signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle, chain_id=chain_id) - - -def balance(token_address, address): - o = g.erc20_balance(token_address, address) - r = conn.do(o) - hx = strip_0x(r) - return int(hx, 16) - - -def main(): - recipient = args.recipient - if not args.u and recipient != add_0x(args.recipient): - raise ValueError('invalid checksum address') - - logg.debug('sender {} balance before: {}'.format(signer_address, balance(args.t, signer_address))) - logg.debug('recipient {} balance before: {}'.format(recipient, balance(args.t, recipient))) - - (tx_hash_hex, o) = g.erc20_transfer(args.t, signer_address, recipient, value) - conn.do(o) - - if block_last: - conn.wait(tx_hash_hex) - logg.debug('sender {} balance after: {}'.format(signer_address, balance(args.t, signer_address))) - logg.debug('recipient {} balance after: {}'.format(recipient, balance(args.t, recipient))) - - print(tx_hash_hex) - - -if __name__ == '__main__': - main() diff --git a/requirements.txt b/requirements.txt @@ -1,12 +1,5 @@ cryptocurrency-cli-tools==0.0.4 -giftable-erc20-token~=0.0.7b7 -eth-accounts-index~=0.0.10a7 -erc20-single-shot-faucet~=0.2.0a6 -erc20-approval-escrow~=0.3.0a5 -cic-eth~=0.10.0a25 -vobject==0.9.6.1 faker==4.17.1 -eth-address-index~=0.1.0a6 crypto-dev-signer~=0.4.13rc2 pysha3==1.0.2 hexathon==0.0.1a2 diff --git a/setup.cfg b/setup.cfg @@ -1,7 +1,7 @@ [metadata] -name = cic-tools +name = chainlib version = 0.0.1a4 -description = Executable tools for CIC network +description = Generic blockchain access library and tooling author = Louis Holbrook author_email = dev@holbrook.no url = https://gitlab.com/grassrootseconomics/cic-tools @@ -27,11 +27,12 @@ licence_files = [options] python_requires = >= 3.6 packages = - cic_tools.eth - cic_tools.eth.runnable + chainlib.eth + chainlib.eth.runnable [options.entry_points] console_scripts = - eth-balance = cic_tools.eth.runnable.balance:main - eth-checksum = cic_tools.eth.runnable.checksum:main - eth-gas = cic_tools.eth.runnable.gas:main + eth-balance = chainlib.eth.runnable.balance:main + eth-checksum = chainlib.eth.runnable.checksum:main + eth-gas = chainlib.eth.runnable.gas:main + eth-transfer = chainlib.eth.runnable.transfer:main