230 lines
7.1 KiB
Python
230 lines
7.1 KiB
Python
from __future__ import annotations
|
|
|
|
from collections import OrderedDict
|
|
from typing import Dict, List, Union
|
|
|
|
from ..abi.v0 import Abi as AbiV0
|
|
from ..abi.v1 import Abi as AbiV1
|
|
from ..abi.v2 import Abi as AbiV2
|
|
from ..cairo.data_types import (
|
|
ArrayType,
|
|
BoolType,
|
|
CairoType,
|
|
EnumType,
|
|
EventType,
|
|
FeltType,
|
|
NamedTupleType,
|
|
OptionType,
|
|
StructType,
|
|
TupleType,
|
|
UintType,
|
|
UnitType,
|
|
)
|
|
from .data_serializers import (
|
|
BoolSerializer,
|
|
ByteArraySerializer,
|
|
)
|
|
from .data_serializers.array_serializer import ArraySerializer
|
|
from .data_serializers.cairo_data_serializer import (
|
|
CairoDataSerializer,
|
|
)
|
|
from .data_serializers.enum_serializer import EnumSerializer
|
|
from .data_serializers.felt_serializer import FeltSerializer
|
|
from .data_serializers.named_tuple_serializer import (
|
|
NamedTupleSerializer,
|
|
)
|
|
from .data_serializers.option_serializer import (
|
|
OptionSerializer,
|
|
)
|
|
from .data_serializers.output_serializer import (
|
|
OutputSerializer,
|
|
)
|
|
from .data_serializers.payload_serializer import (
|
|
PayloadSerializer,
|
|
)
|
|
from .data_serializers.struct_serializer import (
|
|
StructSerializer,
|
|
)
|
|
from .data_serializers.tuple_serializer import TupleSerializer
|
|
from .data_serializers.uint256_serializer import (
|
|
Uint256Serializer,
|
|
)
|
|
from .data_serializers.uint_serializer import UintSerializer
|
|
from .data_serializers.unit_serializer import UnitSerializer
|
|
from .errors import InvalidTypeException
|
|
from .function_serialization_adapter import (
|
|
FunctionSerializationAdapter,
|
|
FunctionSerializationAdapterV1,
|
|
)
|
|
|
|
_uint256_type = StructType("Uint256", OrderedDict(low=FeltType(), high=FeltType()))
|
|
_byte_array_type = StructType(
|
|
"core::byte_array::ByteArray",
|
|
OrderedDict(
|
|
data=ArrayType(FeltType()),
|
|
pending_word=FeltType(),
|
|
pending_word_len=UintType(bits=32),
|
|
),
|
|
)
|
|
|
|
|
|
def serializer_for_type(cairo_type: CairoType) -> CairoDataSerializer:
|
|
"""
|
|
Create a serializer for cairo type.
|
|
|
|
:param cairo_type: CairoType.
|
|
:return: CairoDataSerializer.
|
|
"""
|
|
# pylint: disable=too-many-return-statements, too-many-branches
|
|
if isinstance(cairo_type, FeltType):
|
|
return FeltSerializer()
|
|
|
|
if isinstance(cairo_type, BoolType):
|
|
return BoolSerializer()
|
|
|
|
if isinstance(cairo_type, StructType):
|
|
# Special case: Uint256 is represented as struct
|
|
if cairo_type == _uint256_type:
|
|
return Uint256Serializer()
|
|
|
|
if cairo_type == _byte_array_type:
|
|
return ByteArraySerializer()
|
|
|
|
return StructSerializer(
|
|
OrderedDict(
|
|
(name, serializer_for_type(member_type))
|
|
for name, member_type in cairo_type.types.items()
|
|
)
|
|
)
|
|
|
|
if isinstance(cairo_type, ArrayType):
|
|
return ArraySerializer(serializer_for_type(cairo_type.inner_type))
|
|
|
|
if isinstance(cairo_type, TupleType):
|
|
return TupleSerializer(
|
|
[serializer_for_type(member) for member in cairo_type.types]
|
|
)
|
|
|
|
if isinstance(cairo_type, NamedTupleType):
|
|
return NamedTupleSerializer(
|
|
OrderedDict(
|
|
(name, serializer_for_type(member_type))
|
|
for name, member_type in cairo_type.types.items()
|
|
)
|
|
)
|
|
|
|
if isinstance(cairo_type, UintType):
|
|
return UintSerializer(bits=cairo_type.bits)
|
|
|
|
if isinstance(cairo_type, OptionType):
|
|
return OptionSerializer(serializer_for_type(cairo_type.type))
|
|
|
|
if isinstance(cairo_type, UnitType):
|
|
return UnitSerializer()
|
|
|
|
if isinstance(cairo_type, EnumType):
|
|
return EnumSerializer(
|
|
OrderedDict(
|
|
(name, serializer_for_type(variant_type))
|
|
for name, variant_type in cairo_type.variants.items()
|
|
)
|
|
)
|
|
if isinstance(cairo_type, EventType):
|
|
return serializer_for_payload(cairo_type.types)
|
|
|
|
raise InvalidTypeException(f"Received unknown Cairo type '{cairo_type}'.")
|
|
|
|
|
|
# We don't want to require users to use OrderedDict. Regular python requires order since python 3.7.
|
|
def serializer_for_payload(payload: Dict[str, CairoType]) -> PayloadSerializer:
|
|
"""
|
|
Create PayloadSerializer for types listed in a dictionary. Please note that the order of fields in the dict is
|
|
very important. Make sure the keys are provided in the right order.
|
|
|
|
:param payload: dictionary with cairo types.
|
|
:return: PayloadSerializer that can be used to (de)serialize events/function calls.
|
|
"""
|
|
return PayloadSerializer(
|
|
OrderedDict(
|
|
(name, serializer_for_type(cairo_type))
|
|
for name, cairo_type in payload.items()
|
|
)
|
|
)
|
|
|
|
|
|
def serializer_for_outputs(payload: List[CairoType]) -> OutputSerializer:
|
|
"""
|
|
Create OutputSerializer for types in list. Please note that the order of fields in the list is
|
|
very important. Make sure the types are provided in the right order.
|
|
|
|
:param payload: list with cairo types.
|
|
:return: OutputSerializer that can be used to deserialize function outputs.
|
|
"""
|
|
return OutputSerializer(
|
|
serializers=[serializer_for_type(cairo_type) for cairo_type in payload]
|
|
)
|
|
|
|
|
|
EventV0 = AbiV0.Event
|
|
EventV1 = AbiV1.Event
|
|
EventV2 = EventType
|
|
|
|
|
|
def serializer_for_event(event: EventV0 | EventV1 | EventV2) -> PayloadSerializer:
|
|
"""
|
|
Create serializer for an event.
|
|
|
|
:param event: parsed event.
|
|
:return: PayloadSerializer that can be used to (de)serialize events.
|
|
"""
|
|
if isinstance(event, EventV0):
|
|
return serializer_for_payload(event.data)
|
|
if isinstance(event, EventV1):
|
|
return serializer_for_payload(event.inputs)
|
|
return serializer_for_payload(event.types)
|
|
|
|
|
|
def serializer_for_function(
|
|
abi_function: AbiV0.Function,
|
|
) -> FunctionSerializationAdapter:
|
|
"""
|
|
Create FunctionSerializationAdapter for serializing function inputs and deserializing function outputs.
|
|
|
|
:param abi_function: parsed function's abi.
|
|
:return: FunctionSerializationAdapter.
|
|
"""
|
|
return FunctionSerializationAdapter(
|
|
inputs_serializer=serializer_for_payload(abi_function.inputs),
|
|
outputs_deserializer=serializer_for_payload(abi_function.outputs),
|
|
)
|
|
|
|
|
|
def serializer_for_function_v1(
|
|
abi_function: Union[AbiV1.Function, AbiV2.Function],
|
|
) -> FunctionSerializationAdapter:
|
|
"""
|
|
Create FunctionSerializationAdapter for serializing function inputs and deserializing function outputs.
|
|
|
|
:param abi_function: parsed function's abi.
|
|
:return: FunctionSerializationAdapter.
|
|
"""
|
|
return FunctionSerializationAdapterV1(
|
|
inputs_serializer=serializer_for_payload(abi_function.inputs),
|
|
outputs_deserializer=serializer_for_outputs(abi_function.outputs),
|
|
)
|
|
|
|
|
|
def serializer_for_constructor_v2(
|
|
abi_function: AbiV2.Constructor,
|
|
) -> FunctionSerializationAdapter:
|
|
"""
|
|
Create FunctionSerializationAdapter for serializing constructor inputs.
|
|
|
|
:param abi_function: parsed constructor's abi.
|
|
:return: FunctionSerializationAdapter.
|
|
"""
|
|
return FunctionSerializationAdapterV1(
|
|
inputs_serializer=serializer_for_payload(abi_function.inputs),
|
|
outputs_deserializer=serializer_for_outputs([]),
|
|
)
|