Source code for genlayer.py.eth.calldata
__all__ = (
'signature_of',
'type_name_of',
'selector_of',
'MethodEncoder',
'encode',
'decode',
)
from ..keccak import Keccak256
import typing
from genlayer.py.types import *
import genlayer.py._internal.reflect as reflect
from ._internal.builder import build
from ._internal.codecs import EncodeState, DecoderState
from .support import *
[docs]
def type_name_of(t: type) -> str:
return build(t).name
[docs]
def signature_of[*T](name: str, params: typing.Type[tuple[*T]]) -> str:
"""
calculates signature that is used for making method selector
"""
return name + build(params).name
[docs]
def selector_of[*T](name: str, params: typing.Type[tuple[*T]]) -> bytes:
return Keccak256(signature_of(name, params).encode('utf-8')).digest()[:4]
[docs]
def encode[T](params: typing.Type[T], args: T) -> bytes:
encoder = build(params)
state = EncodeState(0, bytearray(), [])
encoder.encode(state, args)
state.run_tails()
return bytes(state.result)
[docs]
def decode[T](expected: typing.Type[T], encoded: collections.abc.Buffer) -> T:
encoder = build(expected)
state = DecoderState(memoryview(encoded), 0, 0)
return encoder.decode(state)
[docs]
class MethodEncoder:
__slots__ = ('_encoder', '_selector', '_decoder')
[docs]
def __init__(self, name: str, params: tuple[typing.Any, ...], ret: type):
self._encoder = build(tuple[InplaceTuple, *params])
if reflect.is_none_type(ret):
self._decoder = None
else:
self._decoder = build(ret)
selector_str = name + self._encoder.name
self._selector = Keccak256(selector_str.encode('utf-8')).digest()[:4]
[docs]
def encode_call(self, args: tuple[typing.Any, ...]) -> bytes:
state = EncodeState(4, bytearray(self._selector), [])
self._encoder.encode(state, args)
state.run_tails()
return bytes(state.result)
[docs]
def decode_ret(self, data: collections.abc.Buffer) -> typing.Any:
state = DecoderState(memoryview(data), 0, 0)
if self._decoder is None:
return None
return self._decoder.decode(state)