73 lines
2.1 KiB
Python
73 lines
2.1 KiB
Python
from typing import (
|
|
Any,
|
|
Dict,
|
|
)
|
|
|
|
from .conversions import (
|
|
to_bytes
|
|
)
|
|
|
|
from ...keccak import (
|
|
SHA3 as keccak,
|
|
)
|
|
|
|
|
|
def collapse_if_tuple(abi: Dict[str, Any]) -> str:
|
|
"""
|
|
Converts a tuple from a dict to a parenthesized list of its types.
|
|
|
|
>>> from eth_utils.abi import collapse_if_tuple
|
|
>>> collapse_if_tuple(
|
|
... {
|
|
... 'components': [
|
|
... {'name': 'anAddress', 'type': 'address'},
|
|
... {'name': 'anInt', 'type': 'uint256'},
|
|
... {'name': 'someBytes', 'type': 'bytes'},
|
|
... ],
|
|
... 'type': 'tuple',
|
|
... }
|
|
... )
|
|
'(address,uint256,bytes)'
|
|
"""
|
|
typ = abi["type"]
|
|
if not isinstance(typ, str):
|
|
raise TypeError(
|
|
f"The 'type' must be a string, but got {repr(typ)} of type {type(typ)}"
|
|
)
|
|
elif not typ.startswith("tuple"):
|
|
return typ
|
|
|
|
delimited = ",".join(collapse_if_tuple(c) for c in abi["components"])
|
|
# Whatever comes after "tuple" is the array dims. The ABI spec states that
|
|
# this will have the form "", "[]", or "[k]".
|
|
array_dim = typ[5:]
|
|
collapsed = f"({delimited}){array_dim}"
|
|
|
|
return collapsed
|
|
|
|
|
|
def _abi_to_signature(abi: Dict[str, Any]) -> str:
|
|
fn_input_types = ",".join(
|
|
[collapse_if_tuple(abi_input) for abi_input in abi.get("inputs", [])]
|
|
)
|
|
function_signature = f"{abi['name']}({fn_input_types})"
|
|
return function_signature
|
|
|
|
|
|
def function_signature_to_4byte_selector(event_signature: str) -> bytes:
|
|
return keccak(to_bytes(text=event_signature.replace(" ", "")))[:4]
|
|
|
|
|
|
def function_abi_to_4byte_selector(function_abi: Dict[str, Any]) -> bytes:
|
|
function_signature = _abi_to_signature(function_abi)
|
|
return function_signature_to_4byte_selector(function_signature)
|
|
|
|
|
|
def event_signature_to_log_topic(event_signature: str) -> bytes:
|
|
return keccak(to_bytes(text=event_signature.replace(" ", "")))
|
|
|
|
|
|
def event_abi_to_log_topic(event_abi: Dict[str, Any]) -> bytes:
|
|
event_signature = _abi_to_signature(event_abi)
|
|
return event_signature_to_log_topic(event_signature)
|