chainlib-eth

Ethereum implementation of the chainlib interface
Log | Files | Refs | README | LICENSE

commit 0e0dbf180ebeaed0cb5e9b3e6c33de0dd03070b7
parent e4d6b8d8454fcef2aed7930dfb352bcad7da7cd4
Author: nolash <dev@holbrook.no>
Date:   Wed,  6 Oct 2021 07:44:53 +0200

Split cli helper classes to respective files

Diffstat:
Dchainlib/eth/cli.py | 123-------------------------------------------------------------------------------
Achainlib/eth/cli/__init__.py | 4++++
Achainlib/eth/cli/arg.py | 9+++++++++
Achainlib/eth/cli/config.py | 33+++++++++++++++++++++++++++++++++
Achainlib/eth/cli/encode.py | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Achainlib/eth/cli/rpc.py | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Achainlib/eth/cli/wallet.py | 19+++++++++++++++++++
Mchainlib/eth/runnable/encode.py | 70++--------------------------------------------------------------------
Msetup.cfg | 2++
9 files changed, 209 insertions(+), 191 deletions(-)

diff --git a/chainlib/eth/cli.py b/chainlib/eth/cli.py @@ -1,123 +0,0 @@ -# standard imports -import os -import logging - -# external imports -from chainlib.cli import ( - ArgumentParser, - argflag_std_read, - argflag_std_write, - argflag_std_base, - reset as argflag_reset, - Config as BaseConfig, - Wallet as BaseWallet, - Rpc as BaseRpc, Flag, - ) -from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer - -# local imports -from chainlib.eth.address import AddressChecksum -from chainlib.eth.connection import EthHTTPConnection -from chainlib.eth.gas import ( - OverrideGasOracle, - RPCGasOracle, - ) -from chainlib.eth.nonce import ( - OverrideNonceOracle, - RPCNonceOracle, - ) - -logg = logging.getLogger(__name__) - -script_dir = os.path.dirname(os.path.realpath(__file__)) - - -class Wallet(BaseWallet): - """Convenience constructor to set Ethereum defaults for chainlib cli Wallet object - - :param checksummer: Address checksummer object - :type checksummer: Implementation of chainlib.eth.address.AddressChecksum - """ - def __init__(self, checksummer=AddressChecksum): - super(Wallet, self).__init__(EIP155Signer, checksummer=checksummer) - - -class Rpc(BaseRpc): - """Convenience constructor to set Ethereum defaults for chainlib cli Rpc object - - - """ - def __init__(self, wallet=None): - super(Rpc, self).__init__(EthHTTPConnection, wallet=wallet) - - - def connect_by_config(self, config): - """ - - If the standard arguments for nonce and fee price/price have been defined (which generate the configuration keys "_NONCE", "_FEE_PRICE" and "_FEE_LIMIT" respectively) , the corresponding overrides for fee and nonce generators will be defined. - - """ - super(Rpc, self).connect_by_config(config) - - if self.can_sign(): - nonce = None - try: - nonce = config.get('_NONCE') - except KeyError: - pass - if nonce != None: - self.nonce_oracle = OverrideNonceOracle(self.get_sender_address(), nonce, id_generator=self.id_generator) - else: - self.nonce_oracle = RPCNonceOracle(self.get_sender_address(), self.conn, id_generator=self.id_generator) - - fee_price = None - fee_limit = None - try: - fee_price = config.get('_FEE_PRICE') - except KeyError: - pass - - try: - fee_limit = config.get('_FEE_LIMIT') - except KeyError: - pass - - if fee_price != None or fee_limit != None: - self.fee_oracle = OverrideGasOracle(price=fee_price, limit=fee_limit, conn=self.conn, id_generator=self.id_generator) - else: - self.fee_oracle = RPCGasOracle(self.conn, id_generator=self.id_generator) - - error_parser = None - if config.get('RPC_DIALECT') == 'openethereum': - from chainlib.eth.dialect.openethereum import DialectErrorParser - self.error_parser = DialectErrorParser() - - return self.conn - - - def get_gas_oracle(self): - return self.get_fee_oracle() - - -class Config(BaseConfig): - """Convenience constructor to set Ethereum defaults for the chainlib cli config object - """ - default_base_config_dir = os.path.join(script_dir, 'data', 'config') - default_fee_limit = 21000 - - @classmethod - def from_args(cls, args, arg_flags=0x0f, env=os.environ, extra_args={}, base_config_dir=None, default_config_dir=None, user_config_dir=None, default_fee_limit=None, logger=None, load_callback=None): - super(Config, cls).override_defaults(base_dir=cls.default_base_config_dir) - if default_fee_limit == None: - default_fee_limit = cls.default_fee_limit - config = BaseConfig.from_args(args, arg_flags=arg_flags, env=env, extra_args=extra_args, base_config_dir=base_config_dir, default_config_dir=default_config_dir, user_config_dir=user_config_dir, default_fee_limit=default_fee_limit, logger=logger, load_callback=load_callback) - - if not config.get('RPC_DIALECT'): - config.add('default', 'RPC_DIALECT', exists_ok=True) - elif config.get('RPC_DIALECT') not in [ - 'openethereum', - 'default', - ]: - raise ValueError('unknown rpc dialect {}'.format(config.get('RPC_DIALECT'))) - - return config diff --git a/chainlib/eth/cli/__init__.py b/chainlib/eth/cli/__init__.py @@ -0,0 +1,4 @@ +from .arg import * +from .config import Config +from .rpc import Rpc +from .wallet import Wallet diff --git a/chainlib/eth/cli/arg.py b/chainlib/eth/cli/arg.py @@ -0,0 +1,9 @@ +# external imports +from chainlib.cli import ( + ArgumentParser, + argflag_std_read, + argflag_std_write, + argflag_std_base, + reset as argflag_reset, + Flag, + ) diff --git a/chainlib/eth/cli/config.py b/chainlib/eth/cli/config.py @@ -0,0 +1,33 @@ +# standard imports +import os + +# external imports +from chainlib.cli import Config as BaseConfig + +script_dir = os.path.dirname(os.path.realpath(__file__)) +data_dir = os.path.join(script_dir, '..') + + +class Config(BaseConfig): + """Convenience constructor to set Ethereum defaults for the chainlib cli config object + """ + default_base_config_dir = os.path.join(data_dir, 'data', 'config') + default_fee_limit = 21000 + + @classmethod + def from_args(cls, args, arg_flags=0x0f, env=os.environ, extra_args={}, base_config_dir=None, default_config_dir=None, user_config_dir=None, default_fee_limit=None, logger=None, load_callback=None): + super(Config, cls).override_defaults(base_dir=cls.default_base_config_dir) + if default_fee_limit == None: + default_fee_limit = cls.default_fee_limit + config = BaseConfig.from_args(args, arg_flags=arg_flags, env=env, extra_args=extra_args, base_config_dir=base_config_dir, default_config_dir=default_config_dir, user_config_dir=user_config_dir, default_fee_limit=default_fee_limit, logger=logger, load_callback=load_callback) + + if not config.get('RPC_DIALECT'): + config.add('default', 'RPC_DIALECT', exists_ok=True) + elif config.get('RPC_DIALECT') not in [ + 'openethereum', + 'default', + ]: + raise ValueError('unknown rpc dialect {}'.format(config.get('RPC_DIALECT'))) + + return config + diff --git a/chainlib/eth/cli/encode.py b/chainlib/eth/cli/encode.py @@ -0,0 +1,70 @@ +# standard imports +import re +import logging + +# external imports +from chainlib.eth.contract import ABIContractType + +logg = logging.getLogger(__name__) + + +class CLIEncoder: + + __re_uint = r'^([uU])[int]*([0-9]+)?$' + __re_bytes = r'^([bB])[ytes]*([0-9]+)?$' + __re_string = r'^([sS])[tring]*$' + __translations = [ + 'to_uint', + 'to_bytes', + 'to_string', + ] + + def to_uint(self, typ): + s = None + a = None + m = re.match(self.__re_uint, typ) + if m == None: + return None + + n = m.group(2) + if m.group(2) == None: + n = 256 + s = 'UINT256'.format(m.group(2)) + a = getattr(ABIContractType, s) + return (s, a) + + + def to_bytes(self, typ): + s = None + a = None + m = re.match(self.__re_bytes, typ) + if m == None: + return None + + n = m.group(2) + if n == None: + n = 32 + s = 'BYTES{}'.format(n) + a = getattr(ABIContractType, s) + return (s, a) + + + def to_string(self, typ): + m = re.match(self.__re_string, typ) + if m == None: + return None + s = 'STRING' + a = getattr(ABIContractType, s) + return (s, a) + + + def translate_type(self, typ): + r = None + for tr in self.__translations: + r = getattr(self, tr)(typ) + if r != None: + break + if r == None: + raise ValueError('no translation for type {}'.format(typ)) + logg.debug('type {} translated to {}'.format(typ, r[0])) + return r[1] diff --git a/chainlib/eth/cli/rpc.py b/chainlib/eth/cli/rpc.py @@ -0,0 +1,70 @@ +# external imports +from chainlib.cli import Rpc as BaseRpc +from chainlib.eth.connection import EthHTTPConnection + +# local imports +from chainlib.eth.gas import ( + OverrideGasOracle, + RPCGasOracle, + ) +from chainlib.eth.nonce import ( + OverrideNonceOracle, + RPCNonceOracle, + ) + + +class Rpc(BaseRpc): + """Convenience constructor to set Ethereum defaults for chainlib cli Rpc object + + + """ + def __init__(self, wallet=None): + super(Rpc, self).__init__(EthHTTPConnection, wallet=wallet) + + + def connect_by_config(self, config): + """ + + If the standard arguments for nonce and fee price/price have been defined (which generate the configuration keys "_NONCE", "_FEE_PRICE" and "_FEE_LIMIT" respectively) , the corresponding overrides for fee and nonce generators will be defined. + + """ + super(Rpc, self).connect_by_config(config) + + if self.can_sign(): + nonce = None + try: + nonce = config.get('_NONCE') + except KeyError: + pass + if nonce != None: + self.nonce_oracle = OverrideNonceOracle(self.get_sender_address(), nonce, id_generator=self.id_generator) + else: + self.nonce_oracle = RPCNonceOracle(self.get_sender_address(), self.conn, id_generator=self.id_generator) + + fee_price = None + fee_limit = None + try: + fee_price = config.get('_FEE_PRICE') + except KeyError: + pass + + try: + fee_limit = config.get('_FEE_LIMIT') + except KeyError: + pass + + if fee_price != None or fee_limit != None: + self.fee_oracle = OverrideGasOracle(price=fee_price, limit=fee_limit, conn=self.conn, id_generator=self.id_generator) + else: + self.fee_oracle = RPCGasOracle(self.conn, id_generator=self.id_generator) + + error_parser = None + if config.get('RPC_DIALECT') == 'openethereum': + from chainlib.eth.dialect.openethereum import DialectErrorParser + self.error_parser = DialectErrorParser() + + return self.conn + + + def get_gas_oracle(self): + return self.get_fee_oracle() diff --git a/chainlib/eth/cli/wallet.py b/chainlib/eth/cli/wallet.py @@ -0,0 +1,19 @@ +# external imports +from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer +from chainlib.cli import Wallet as BaseWallet + +# local imports +from chainlib.eth.address import AddressChecksum + + +class Wallet(BaseWallet): + """Convenience constructor to set Ethereum defaults for chainlib cli Wallet object + + :param checksummer: Address checksummer object + :type checksummer: Implementation of chainlib.eth.address.AddressChecksum + """ + def __init__(self, checksummer=AddressChecksum): + super(Wallet, self).__init__(EIP155Signer, checksummer=checksummer) + + + diff --git a/chainlib/eth/runnable/encode.py b/chainlib/eth/runnable/encode.py @@ -8,11 +8,11 @@ import json import argparse import logging import urllib -import re import sha3 # external imports import chainlib.eth.cli +from chainlib.eth.cli.encode import CLIEncoder from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer from crypto_dev_signer.keystore.dict import DictKeystore from hexathon import ( @@ -41,15 +41,11 @@ from chainlib.eth.tx import ( TxFormat, raw, ) -from chainlib.eth.contract import ( - ABIMethodEncoder, - ABIContractEncoder, - ABIContractType, - ) from chainlib.error import SignerMissingException from chainlib.chain import ChainSpec from chainlib.eth.runnable.util import decode_for_puny_humans from chainlib.eth.jsonrpc import to_blockheight_param +from chainlib.eth.contract import ABIContractEncoder logging.basicConfig(level=logging.WARNING) logg = logging.getLogger() @@ -89,68 +85,6 @@ except AttributeError: pass -class CLIEncoder: - - __re_uint = r'^([uU])[int]*([0-9]+)?$' - __re_bytes = r'^([bB])[ytes]*([0-9]+)?$' - __re_string = r'^([sS])[tring]*$' - __translations = [ - 'to_uint', - 'to_bytes', - 'to_string', - ] - - def to_uint(self, typ): - s = None - a = None - m = re.match(self.__re_uint, typ) - if m == None: - return None - - n = m.group(2) - if m.group(2) == None: - n = 256 - s = 'UINT256'.format(m.group(2)) - a = getattr(ABIContractType, s) - return (s, a) - - - def to_bytes(self, typ): - s = None - a = None - m = re.match(self.__re_bytes, typ) - if m == None: - return None - - n = m.group(2) - if n == None: - n = 32 - s = 'BYTES{}'.format(n) - a = getattr(ABIContractType, s) - return (s, a) - - - def to_string(self, typ): - m = re.match(self.__re_string, typ) - if m == None: - return None - s = 'STRING' - a = getattr(ABIContractType, s) - return (s, a) - - - def translate_type(self, typ): - r = None - for tr in self.__translations: - r = getattr(self, tr)(typ) - if r != None: - break - if r == None: - raise ValueError('no translation for type {}'.format(typ)) - logg.debug('type {} translated to {}'.format(typ, r[0])) - return r[1] - - def main(): signer_address = ZERO_ADDRESS diff --git a/setup.cfg b/setup.cfg @@ -32,6 +32,7 @@ packages = chainlib.eth.runnable chainlib.eth.pytest chainlib.eth.unittest + chainlib.eth.cli [options.entry_points] console_scripts = @@ -41,6 +42,7 @@ console_scripts = eth-raw = chainlib.eth.runnable.raw:main eth-get = chainlib.eth.runnable.get:main eth-decode = chainlib.eth.runnable.decode:main + eth-encode = chainlib.eth.runnable.encode:main eth-info = chainlib.eth.runnable.info:main eth-nonce = chainlib.eth.runnable.count:main eth = chainlib.eth.runnable.info:main