Files
ccxt_with_mt5/ccxt/static_dependencies/ethereum/abi/base.py
lz_db 0fab423a18 add
2025-11-16 12:31:03 +08:00

153 lines
4.7 KiB
Python

import functools
from ..typing.abi import (
TypeStr,
)
from .grammar import (
BasicType,
TupleType,
normalize,
parse,
)
def parse_type_str(expected_base=None, with_arrlist=False):
"""
Used by BaseCoder subclasses as a convenience for implementing the
``from_type_str`` method required by ``ABIRegistry``. Useful if normalizing
then parsing a type string with an (optional) expected base is required in
that method.
"""
def decorator(old_from_type_str):
@functools.wraps(old_from_type_str)
def new_from_type_str(cls, type_str, registry):
normalized_type_str = normalize(type_str)
abi_type = parse(normalized_type_str)
type_str_repr = repr(type_str)
if type_str != normalized_type_str:
type_str_repr = "{} (normalized to {})".format(
type_str_repr,
repr(normalized_type_str),
)
if expected_base is not None:
if not isinstance(abi_type, BasicType):
raise ValueError(
"Cannot create {} for non-basic type {}".format(
cls.__name__,
type_str_repr,
)
)
if abi_type.base != expected_base:
raise ValueError(
"Cannot create {} for type {}: expected type with "
"base '{}'".format(
cls.__name__,
type_str_repr,
expected_base,
)
)
if not with_arrlist and abi_type.arrlist is not None:
raise ValueError(
"Cannot create {} for type {}: expected type with "
"no array dimension list".format(
cls.__name__,
type_str_repr,
)
)
if with_arrlist and abi_type.arrlist is None:
raise ValueError(
"Cannot create {} for type {}: expected type with "
"array dimension list".format(
cls.__name__,
type_str_repr,
)
)
# Perform general validation of default solidity types
abi_type.validate()
return old_from_type_str(cls, abi_type, registry)
return classmethod(new_from_type_str)
return decorator
def parse_tuple_type_str(old_from_type_str):
"""
Used by BaseCoder subclasses as a convenience for implementing the
``from_type_str`` method required by ``ABIRegistry``. Useful if normalizing
then parsing a tuple type string is required in that method.
"""
@functools.wraps(old_from_type_str)
def new_from_type_str(cls, type_str, registry):
normalized_type_str = normalize(type_str)
abi_type = parse(normalized_type_str)
type_str_repr = repr(type_str)
if type_str != normalized_type_str:
type_str_repr = "{} (normalized to {})".format(
type_str_repr,
repr(normalized_type_str),
)
if not isinstance(abi_type, TupleType):
raise ValueError(
"Cannot create {} for non-tuple type {}".format(
cls.__name__,
type_str_repr,
)
)
abi_type.validate()
return old_from_type_str(cls, abi_type, registry)
return classmethod(new_from_type_str)
class BaseCoder:
"""
Base class for all encoder and decoder classes.
"""
is_dynamic = False
def __init__(self, **kwargs):
cls = type(self)
# Ensure no unrecognized kwargs were given
for key, value in kwargs.items():
if not hasattr(cls, key):
raise AttributeError(
"Property {key} not found on {cls_name} class. "
"`{cls_name}.__init__` only accepts keyword arguments which are "
"present on the {cls_name} class.".format(
key=key,
cls_name=cls.__name__,
)
)
setattr(self, key, value)
# Validate given combination of kwargs
self.validate()
def validate(self):
pass
@classmethod
def from_type_str(
cls, type_str: TypeStr, registry
) -> "BaseCoder": # pragma: no cover
"""
Used by :any:`ABIRegistry` to get an appropriate encoder or decoder
instance for the given type string and type registry.
"""
raise NotImplementedError("Must implement `from_type_str`")