diff --git a/chainlib/eth/cli/__init__.py b/chainlib/eth/cli/__init__.py new file mode 100644 index 0000000..3d8554e --- /dev/null +++ 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 new file mode 100644 index 0000000..99a4b9e --- /dev/null +++ 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 new file mode 100644 index 0000000..2b47fdd --- /dev/null +++ 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 new file mode 100644 index 0000000..11cf0b7 --- /dev/null +++ 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.py b/chainlib/eth/cli/rpc.py similarity index 50% rename from chainlib/eth/cli.py rename to chainlib/eth/cli/rpc.py index 6b32162..a9975a7 100644 --- a/chainlib/eth/cli.py +++ b/chainlib/eth/cli/rpc.py @@ -1,23 +1,8 @@ -# 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 +from chainlib.cli import Rpc as BaseRpc +from chainlib.eth.connection import EthHTTPConnection # local imports -from chainlib.eth.address import AddressChecksum -from chainlib.eth.connection import EthHTTPConnection from chainlib.eth.gas import ( OverrideGasOracle, RPCGasOracle, @@ -27,20 +12,6 @@ from chainlib.eth.nonce import ( 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 @@ -97,27 +68,3 @@ class Rpc(BaseRpc): 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/wallet.py b/chainlib/eth/cli/wallet.py new file mode 100644 index 0000000..94c3f78 --- /dev/null +++ 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 index 0edb446..bed4c70 100644 --- 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 index d9de2e5..596249d 100644 --- 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