add
This commit is contained in:
2
ccxt/static_dependencies/starknet/abi/v2/__init__.py
Normal file
2
ccxt/static_dependencies/starknet/abi/v2/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from .model import Abi
|
||||
from .parser import AbiParser, AbiParsingError
|
||||
89
ccxt/static_dependencies/starknet/abi/v2/model.py
Normal file
89
ccxt/static_dependencies/starknet/abi/v2/model.py
Normal file
@@ -0,0 +1,89 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, List, Optional, OrderedDict, Union
|
||||
|
||||
from ...cairo.data_types import CairoType, EnumType, EventType, StructType
|
||||
|
||||
|
||||
@dataclass
|
||||
class Abi:
|
||||
"""
|
||||
Dataclass representing class abi. Contains parsed functions, enums, events and structures.
|
||||
"""
|
||||
|
||||
# pylint: disable=too-many-instance-attributes
|
||||
|
||||
@dataclass
|
||||
class Function:
|
||||
"""
|
||||
Dataclass representing function's abi.
|
||||
"""
|
||||
|
||||
name: str
|
||||
inputs: OrderedDict[str, CairoType]
|
||||
outputs: List[CairoType]
|
||||
|
||||
@dataclass
|
||||
class Constructor:
|
||||
"""
|
||||
Dataclass representing constructor's abi.
|
||||
"""
|
||||
|
||||
name: str
|
||||
inputs: OrderedDict[str, CairoType]
|
||||
|
||||
@dataclass
|
||||
class EventStruct:
|
||||
"""
|
||||
Dataclass representing struct event's abi.
|
||||
"""
|
||||
|
||||
name: str
|
||||
members: OrderedDict[str, CairoType]
|
||||
|
||||
@dataclass
|
||||
class EventEnum:
|
||||
"""
|
||||
Dataclass representing enum event's abi.
|
||||
"""
|
||||
|
||||
name: str
|
||||
variants: OrderedDict[str, CairoType]
|
||||
|
||||
Event = Union[EventStruct, EventEnum]
|
||||
|
||||
@dataclass
|
||||
class Interface:
|
||||
"""
|
||||
Dataclass representing an interface.
|
||||
"""
|
||||
|
||||
name: str
|
||||
items: OrderedDict[
|
||||
str, Abi.Function
|
||||
] # Only functions can be defined in the interface
|
||||
|
||||
@dataclass
|
||||
class Impl:
|
||||
"""
|
||||
Dataclass representing an impl.
|
||||
"""
|
||||
|
||||
name: str
|
||||
interface_name: str
|
||||
|
||||
defined_structures: Dict[
|
||||
str, StructType
|
||||
] #: Abi of structures defined by the class.
|
||||
defined_enums: Dict[str, EnumType] #: Abi of enums defined by the class.
|
||||
functions: Dict[str, Function] #: Functions defined by the class.
|
||||
events: Dict[str, EventType] #: Events defined by the class
|
||||
constructor: Optional[
|
||||
Constructor
|
||||
] #: Contract's constructor. It is None if class doesn't define one.
|
||||
l1_handler: Optional[
|
||||
Dict[str, Function]
|
||||
] #: Handlers of L1 messages. It is None if class doesn't define one.
|
||||
interfaces: Dict[str, Interface]
|
||||
implementations: Dict[str, Impl]
|
||||
293
ccxt/static_dependencies/starknet/abi/v2/parser.py
Normal file
293
ccxt/static_dependencies/starknet/abi/v2/parser.py
Normal file
@@ -0,0 +1,293 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
import json
|
||||
from collections import OrderedDict, defaultdict
|
||||
from typing import DefaultDict, Dict, List, Optional, Tuple, TypeVar, Union, cast
|
||||
|
||||
from ....marshmallow import EXCLUDE
|
||||
|
||||
from .model import Abi
|
||||
from .schemas import ContractAbiEntrySchema
|
||||
from .shape import (
|
||||
CONSTRUCTOR_ENTRY,
|
||||
ENUM_ENTRY,
|
||||
EVENT_ENTRY,
|
||||
FUNCTION_ENTRY,
|
||||
IMPL_ENTRY,
|
||||
INTERFACE_ENTRY,
|
||||
L1_HANDLER_ENTRY,
|
||||
STRUCT_ENTRY,
|
||||
ConstructorDict,
|
||||
EventDict,
|
||||
EventEnumVariantDict,
|
||||
EventStructMemberDict,
|
||||
FunctionDict,
|
||||
ImplDict,
|
||||
InterfaceDict,
|
||||
TypedParameterDict,
|
||||
)
|
||||
from ...cairo.data_types import CairoType, EnumType, EventType, StructType
|
||||
from ...cairo.v2.type_parser import TypeParser
|
||||
|
||||
|
||||
class AbiParsingError(ValueError):
|
||||
"""
|
||||
Error raised when something wrong goes during abi parsing.
|
||||
"""
|
||||
|
||||
|
||||
class AbiParser:
|
||||
"""
|
||||
Utility class for parsing abi into a dataclass.
|
||||
"""
|
||||
|
||||
# Entries from ABI grouped by entry type
|
||||
_grouped: DefaultDict[str, List[Dict]]
|
||||
# lazy init property
|
||||
_type_parser: Optional[TypeParser] = None
|
||||
|
||||
def __init__(self, abi_list: List[Dict]):
|
||||
"""
|
||||
Abi parser constructor. Ensures that abi satisfies the abi schema.
|
||||
|
||||
:param abi_list: Contract's ABI as a list of dictionaries.
|
||||
"""
|
||||
abi = [
|
||||
ContractAbiEntrySchema().load(entry, unknown=EXCLUDE) for entry in abi_list
|
||||
]
|
||||
grouped = defaultdict(list)
|
||||
for entry in abi:
|
||||
assert isinstance(entry, dict)
|
||||
grouped[entry["type"]].append(entry)
|
||||
|
||||
self._grouped = grouped
|
||||
|
||||
def parse(self) -> Abi:
|
||||
"""
|
||||
Parse abi provided to constructor and return it as a dataclass. Ensures that there are no cycles in the abi.
|
||||
|
||||
:raises: AbiParsingError: on any parsing error.
|
||||
:return: Abi dataclass.
|
||||
"""
|
||||
structures, enums = self._parse_structures_and_enums()
|
||||
events_dict = cast(
|
||||
Dict[str, EventDict],
|
||||
AbiParser._group_by_entry_name(
|
||||
self._grouped[EVENT_ENTRY], "defined events"
|
||||
),
|
||||
)
|
||||
|
||||
events: Dict[str, EventType] = {}
|
||||
for name, event in events_dict.items():
|
||||
events[name] = self._parse_event(event)
|
||||
assert self._type_parser is not None
|
||||
self._type_parser.add_defined_type(events[name])
|
||||
|
||||
functions_dict = cast(
|
||||
Dict[str, FunctionDict],
|
||||
AbiParser._group_by_entry_name(
|
||||
self._grouped[FUNCTION_ENTRY], "defined functions"
|
||||
),
|
||||
)
|
||||
interfaces_dict = cast(
|
||||
Dict[str, InterfaceDict],
|
||||
AbiParser._group_by_entry_name(
|
||||
self._grouped[INTERFACE_ENTRY], "defined interfaces"
|
||||
),
|
||||
)
|
||||
impls_dict = cast(
|
||||
Dict[str, ImplDict],
|
||||
AbiParser._group_by_entry_name(self._grouped[IMPL_ENTRY], "defined impls"),
|
||||
)
|
||||
l1_handlers_dict = cast(
|
||||
Dict[str, FunctionDict],
|
||||
AbiParser._group_by_entry_name(
|
||||
self._grouped[L1_HANDLER_ENTRY], "defined L1 handlers"
|
||||
),
|
||||
)
|
||||
constructors = self._grouped[CONSTRUCTOR_ENTRY]
|
||||
|
||||
if len(constructors) > 1:
|
||||
raise AbiParsingError("Constructor in ABI must be defined at most once.")
|
||||
|
||||
return Abi(
|
||||
defined_structures=structures,
|
||||
defined_enums=enums,
|
||||
constructor=(
|
||||
self._parse_constructor(cast(ConstructorDict, constructors[0]))
|
||||
if constructors
|
||||
else None
|
||||
),
|
||||
l1_handler={
|
||||
name: self._parse_function(entry)
|
||||
for name, entry in l1_handlers_dict.items()
|
||||
},
|
||||
functions={
|
||||
name: self._parse_function(entry)
|
||||
for name, entry in functions_dict.items()
|
||||
},
|
||||
events=events,
|
||||
interfaces={
|
||||
name: self._parse_interface(entry)
|
||||
for name, entry in interfaces_dict.items()
|
||||
},
|
||||
implementations={
|
||||
name: self._parse_impl(entry) for name, entry in impls_dict.items()
|
||||
},
|
||||
)
|
||||
|
||||
@property
|
||||
def type_parser(self) -> TypeParser:
|
||||
if self._type_parser:
|
||||
return self._type_parser
|
||||
|
||||
raise RuntimeError("Tried to get type_parser before it was set.")
|
||||
|
||||
def _parse_structures_and_enums(
|
||||
self,
|
||||
) -> Tuple[Dict[str, StructType], Dict[str, EnumType]]:
|
||||
structs_dict = AbiParser._group_by_entry_name(
|
||||
self._grouped[STRUCT_ENTRY], "defined structures"
|
||||
)
|
||||
enums_dict = AbiParser._group_by_entry_name(
|
||||
self._grouped[ENUM_ENTRY], "defined enums"
|
||||
)
|
||||
|
||||
# Contains sorted members of the struct
|
||||
struct_members: Dict[str, List[TypedParameterDict]] = {}
|
||||
structs: Dict[str, StructType] = {}
|
||||
|
||||
# Contains sorted members of the enum
|
||||
enum_members: Dict[str, List[TypedParameterDict]] = {}
|
||||
enums: Dict[str, EnumType] = {}
|
||||
|
||||
# Example problem (with a simplified json structure):
|
||||
# [{name: User, fields: {id: Uint256}}, {name: "Uint256", ...}]
|
||||
# User refers to Uint256 even though it is not known yet (will be parsed next).
|
||||
# This is why it is important to create the structure types first. This way other types can already refer to
|
||||
# them when parsing types, even thought their fields are not filled yet.
|
||||
# At the end we will mutate those structures to contain the right fields. An alternative would be to use
|
||||
# topological sorting with an additional "unresolved type", so this flow is much easier.
|
||||
for name, struct in structs_dict.items():
|
||||
structs[name] = StructType(name, OrderedDict())
|
||||
struct_members[name] = struct["members"]
|
||||
|
||||
for name, enum in enums_dict.items():
|
||||
enums[name] = EnumType(name, OrderedDict())
|
||||
enum_members[name] = enum["variants"]
|
||||
|
||||
# Now parse the types of members and save them.
|
||||
defined_structs_enums: Dict[str, Union[StructType, EnumType]] = dict(structs)
|
||||
defined_structs_enums.update(enums)
|
||||
|
||||
self._type_parser = TypeParser(defined_structs_enums) # pyright: ignore
|
||||
for name, struct in structs.items():
|
||||
members = self._parse_members(
|
||||
cast(List[TypedParameterDict], struct_members[name]),
|
||||
f"members of structure '{name}'",
|
||||
)
|
||||
struct.types.update(members)
|
||||
for name, enum in enums.items():
|
||||
members = self._parse_members(
|
||||
cast(List[TypedParameterDict], enum_members[name]),
|
||||
f"members of enum '{name}'",
|
||||
)
|
||||
enum.variants.update(members)
|
||||
|
||||
# All types have their members assigned now
|
||||
|
||||
self._check_for_cycles(defined_structs_enums)
|
||||
|
||||
return structs, enums
|
||||
|
||||
@staticmethod
|
||||
def _check_for_cycles(structs: Dict[str, Union[StructType, EnumType]]):
|
||||
# We want to avoid creating our own cycle checker as it would make it more complex. json module has a built-in
|
||||
# checker for cycles.
|
||||
try:
|
||||
_to_json(structs)
|
||||
except ValueError as err:
|
||||
raise AbiParsingError(err) from ValueError
|
||||
|
||||
def _parse_function(self, function: FunctionDict) -> Abi.Function:
|
||||
return Abi.Function(
|
||||
name=function["name"],
|
||||
inputs=self._parse_members(function["inputs"], function["name"]),
|
||||
outputs=list(
|
||||
self.type_parser.parse_inline_type(param["type"])
|
||||
for param in function["outputs"]
|
||||
),
|
||||
)
|
||||
|
||||
def _parse_constructor(self, constructor: ConstructorDict) -> Abi.Constructor:
|
||||
return Abi.Constructor(
|
||||
name=constructor["name"],
|
||||
inputs=self._parse_members(constructor["inputs"], constructor["name"]),
|
||||
)
|
||||
|
||||
def _parse_event(self, event: EventDict) -> EventType:
|
||||
members_ = event.get("members", event.get("variants"))
|
||||
assert isinstance(members_, list)
|
||||
return EventType(
|
||||
name=event["name"],
|
||||
types=self._parse_members(
|
||||
cast(List[TypedParameterDict], members_), event["name"]
|
||||
),
|
||||
)
|
||||
|
||||
TypedParam = TypeVar(
|
||||
"TypedParam", TypedParameterDict, EventStructMemberDict, EventEnumVariantDict
|
||||
)
|
||||
|
||||
def _parse_members(
|
||||
self, params: List[TypedParam], entity_name: str
|
||||
) -> OrderedDict[str, CairoType]:
|
||||
# Without cast, it complains that 'Type "TypedParameterDict" cannot be assigned to type "T@_group_by_name"'
|
||||
members = AbiParser._group_by_entry_name(cast(List[Dict], params), entity_name)
|
||||
return OrderedDict(
|
||||
(name, self.type_parser.parse_inline_type(param["type"]))
|
||||
for name, param in members.items()
|
||||
)
|
||||
|
||||
def _parse_interface(self, interface: InterfaceDict) -> Abi.Interface:
|
||||
return Abi.Interface(
|
||||
name=interface["name"],
|
||||
items=OrderedDict(
|
||||
(entry["name"], self._parse_function(entry))
|
||||
for entry in interface["items"]
|
||||
),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _parse_impl(impl: ImplDict) -> Abi.Impl:
|
||||
return Abi.Impl(
|
||||
name=impl["name"],
|
||||
interface_name=impl["interface_name"],
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _group_by_entry_name(
|
||||
dicts: List[Dict], entity_name: str
|
||||
) -> OrderedDict[str, Dict]:
|
||||
grouped = OrderedDict()
|
||||
for entry in dicts:
|
||||
name = entry["name"]
|
||||
if name in grouped:
|
||||
raise AbiParsingError(
|
||||
f"Name '{name}' was used more than once in {entity_name}."
|
||||
)
|
||||
grouped[name] = entry
|
||||
return grouped
|
||||
|
||||
|
||||
def _to_json(value):
|
||||
class DataclassSupportingEncoder(json.JSONEncoder):
|
||||
def default(self, o):
|
||||
# Dataclasses are not supported by json. Additionally, dataclasses.asdict() works recursively and doesn't
|
||||
# check for cycles, so we need to flatten dataclasses (by ONE LEVEL) ourselves.
|
||||
if dataclasses.is_dataclass(o):
|
||||
return tuple(getattr(o, field.name) for field in dataclasses.fields(o))
|
||||
return super().default(o)
|
||||
|
||||
return json.dumps(value, cls=DataclassSupportingEncoder)
|
||||
192
ccxt/static_dependencies/starknet/abi/v2/parser_transformer.py
Normal file
192
ccxt/static_dependencies/starknet/abi/v2/parser_transformer.py
Normal file
@@ -0,0 +1,192 @@
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from ....lark import *
|
||||
from ....lark import Token, Transformer
|
||||
|
||||
from ...cairo.data_types import (
|
||||
ArrayType,
|
||||
BoolType,
|
||||
CairoType,
|
||||
FeltType,
|
||||
OptionType,
|
||||
TupleType,
|
||||
TypeIdentifier,
|
||||
UintType,
|
||||
UnitType,
|
||||
)
|
||||
|
||||
ABI_EBNF = """
|
||||
IDENTIFIER: /[a-zA-Z_][a-zA-Z_0-9]*/
|
||||
|
||||
type: "@"? actual_type
|
||||
|
||||
actual_type: type_unit
|
||||
| type_bool
|
||||
| type_felt
|
||||
| type_bytes
|
||||
| type_uint
|
||||
| type_contract_address
|
||||
| type_class_hash
|
||||
| type_storage_address
|
||||
| type_option
|
||||
| type_array
|
||||
| type_span
|
||||
| tuple
|
||||
| type_identifier
|
||||
|
||||
|
||||
type_unit: "()"
|
||||
type_felt: "core::felt252"
|
||||
type_bytes: "core::bytes_31::bytes31"
|
||||
type_bool: "core::bool"
|
||||
type_uint: "core::integer::u" INT
|
||||
type_contract_address: "core::starknet::contract_address::ContractAddress"
|
||||
type_class_hash: "core::starknet::class_hash::ClassHash"
|
||||
type_storage_address: "core::starknet::storage_access::StorageAddress"
|
||||
type_option: "core::option::Option::<" (type | type_identifier) ">"
|
||||
type_array: "core::array::Array::<" (type | type_identifier) ">"
|
||||
type_span: "core::array::Span::<" (type | type_identifier) ">"
|
||||
|
||||
tuple: "(" type? ("," type?)* ")"
|
||||
|
||||
type_identifier: (IDENTIFIER | "::")+ ("<" (type | ",")+ ">")?
|
||||
|
||||
|
||||
%import common.INT
|
||||
%import common.WS
|
||||
%ignore WS
|
||||
"""
|
||||
|
||||
|
||||
class ParserTransformer(Transformer):
|
||||
"""
|
||||
Transforms the lark tree into CairoTypes.
|
||||
"""
|
||||
|
||||
def __init__(self, type_identifiers: Optional[dict] = None) -> None:
|
||||
if type_identifiers is None:
|
||||
type_identifiers = {}
|
||||
self.type_identifiers = type_identifiers
|
||||
super(Transformer, self).__init__()
|
||||
|
||||
# pylint: disable=no-self-use
|
||||
|
||||
def __default__(self, data: str, children, meta):
|
||||
raise TypeError(f"Unable to parse tree node of type {data}.")
|
||||
|
||||
def type(self, value: List[Optional[CairoType]]) -> Optional[CairoType]:
|
||||
"""
|
||||
Tokens are read bottom-up, so here all of them are parsed and should be just returned.
|
||||
`Optional` is added in case of the unit type.
|
||||
"""
|
||||
assert len(value) == 1
|
||||
return value[0]
|
||||
|
||||
def actual_type(self, value) -> Optional[CairoType]:
|
||||
return value[0]
|
||||
|
||||
def type_felt(self, _value: List[Any]) -> FeltType:
|
||||
"""
|
||||
Felt does not contain any additional arguments, so `_value` is just an empty list.
|
||||
"""
|
||||
return FeltType()
|
||||
|
||||
def type_bytes(self, _value: List[Any]) -> FeltType:
|
||||
"""
|
||||
Felt does not contain any additional arguments, so `_value` is just an empty list.
|
||||
"""
|
||||
return FeltType()
|
||||
|
||||
def type_bool(self, _value: List[Any]) -> BoolType:
|
||||
"""
|
||||
Bool does not contain any additional arguments, so `_value` is just an empty list.
|
||||
"""
|
||||
return BoolType()
|
||||
|
||||
def type_uint(self, value: List[Token]) -> UintType:
|
||||
"""
|
||||
Uint type contains information about its size. It is present in the value[0].
|
||||
"""
|
||||
return UintType(int(value[0]))
|
||||
|
||||
def type_unit(self, _value: List[Any]) -> UnitType:
|
||||
"""
|
||||
`()` type.
|
||||
"""
|
||||
return UnitType()
|
||||
|
||||
def type_option(self, value: List[CairoType]) -> OptionType:
|
||||
"""
|
||||
Option includes an information about which type it eventually represents.
|
||||
`Optional` is added in case of the unit type.
|
||||
"""
|
||||
return OptionType(value[0])
|
||||
|
||||
def type_array(self, value: List[CairoType]) -> ArrayType:
|
||||
"""
|
||||
Array contains values of type under `value[0]`.
|
||||
"""
|
||||
return ArrayType(value[0])
|
||||
|
||||
def type_span(self, value: List[CairoType]) -> ArrayType:
|
||||
"""
|
||||
Span contains values of type under `value[0]`.
|
||||
"""
|
||||
return ArrayType(value[0])
|
||||
|
||||
def type_identifier(self, tokens: List[Token]) -> TypeIdentifier:
|
||||
"""
|
||||
Structs and enums are defined as follows: (IDENTIFIER | "::")+ [some not important info]
|
||||
where IDENTIFIER is a string.
|
||||
|
||||
Tokens would contain strings and types (if it is present).
|
||||
We are interested only in the strings because a structure (or enum) name can be built from them.
|
||||
"""
|
||||
name = "::".join(token for token in tokens if isinstance(token, str))
|
||||
if name in self.type_identifiers:
|
||||
return self.type_identifiers[name]
|
||||
return TypeIdentifier(name)
|
||||
|
||||
def type_contract_address(self, _value: List[Any]) -> FeltType:
|
||||
"""
|
||||
ContractAddress is represented by the felt252.
|
||||
"""
|
||||
return FeltType()
|
||||
|
||||
def type_class_hash(self, _value: List[Any]) -> FeltType:
|
||||
"""
|
||||
ClassHash is represented by the felt252.
|
||||
"""
|
||||
return FeltType()
|
||||
|
||||
def type_storage_address(self, _value: List[Any]) -> FeltType:
|
||||
"""
|
||||
StorageAddress is represented by the felt252.
|
||||
"""
|
||||
return FeltType()
|
||||
|
||||
def tuple(self, types: List[CairoType]) -> TupleType:
|
||||
"""
|
||||
Tuple contains values defined in the `types` argument.
|
||||
"""
|
||||
return TupleType(types)
|
||||
|
||||
|
||||
def parse(
|
||||
code: str,
|
||||
type_identifiers,
|
||||
) -> CairoType:
|
||||
"""
|
||||
Parse the given string and return a CairoType.
|
||||
"""
|
||||
grammar_parser = lark.Lark(
|
||||
grammar=ABI_EBNF,
|
||||
start="type",
|
||||
parser="earley",
|
||||
)
|
||||
parsed_lark_tree = grammar_parser.parse(code)
|
||||
|
||||
parser_transformer = ParserTransformer(type_identifiers)
|
||||
cairo_type = parser_transformer.transform(parsed_lark_tree)
|
||||
|
||||
return cairo_type
|
||||
132
ccxt/static_dependencies/starknet/abi/v2/schemas.py
Normal file
132
ccxt/static_dependencies/starknet/abi/v2/schemas.py
Normal file
@@ -0,0 +1,132 @@
|
||||
from ....marshmallow import Schema, fields
|
||||
from ....marshmallow_oneofschema import OneOfSchema
|
||||
|
||||
from .shape import (
|
||||
CONSTRUCTOR_ENTRY,
|
||||
DATA_KIND,
|
||||
ENUM_ENTRY,
|
||||
EVENT_ENTRY,
|
||||
FUNCTION_ENTRY,
|
||||
IMPL_ENTRY,
|
||||
INTERFACE_ENTRY,
|
||||
L1_HANDLER_ENTRY,
|
||||
NESTED_KIND,
|
||||
STRUCT_ENTRY,
|
||||
)
|
||||
|
||||
|
||||
class TypeSchema(Schema):
|
||||
type = fields.String(data_key="type", required=True)
|
||||
|
||||
|
||||
class TypedParameterSchema(TypeSchema):
|
||||
name = fields.String(data_key="name", required=True)
|
||||
|
||||
|
||||
class FunctionBaseSchema(Schema):
|
||||
name = fields.String(data_key="name", required=True)
|
||||
inputs = fields.List(
|
||||
fields.Nested(TypedParameterSchema()), data_key="inputs", required=True
|
||||
)
|
||||
outputs = fields.List(
|
||||
fields.Nested(TypeSchema()), data_key="outputs", required=True
|
||||
)
|
||||
state_mutability = fields.String(data_key="state_mutability", default=None)
|
||||
|
||||
|
||||
class FunctionAbiEntrySchema(FunctionBaseSchema):
|
||||
type = fields.Constant(FUNCTION_ENTRY, data_key="type", required=True)
|
||||
|
||||
|
||||
class ConstructorAbiEntrySchema(Schema):
|
||||
type = fields.Constant(CONSTRUCTOR_ENTRY, data_key="type", required=True)
|
||||
name = fields.String(data_key="name", required=True)
|
||||
inputs = fields.List(
|
||||
fields.Nested(TypedParameterSchema()), data_key="inputs", required=True
|
||||
)
|
||||
|
||||
|
||||
class L1HandlerAbiEntrySchema(FunctionBaseSchema):
|
||||
type = fields.Constant(L1_HANDLER_ENTRY, data_key="type", required=True)
|
||||
|
||||
|
||||
class EventStructMemberSchema(TypedParameterSchema):
|
||||
kind = fields.Constant(DATA_KIND, data_key="kind", required=True)
|
||||
|
||||
|
||||
class EventStructAbiEntrySchema(Schema):
|
||||
type = fields.Constant(EVENT_ENTRY, data_key="type", required=True)
|
||||
name = fields.String(data_key="name", required=True)
|
||||
kind = fields.Constant(STRUCT_ENTRY, data_key="kind", required=True)
|
||||
members = fields.List(
|
||||
fields.Nested(EventStructMemberSchema()), data_key="members", required=True
|
||||
)
|
||||
|
||||
|
||||
class EventEnumVariantSchema(TypedParameterSchema):
|
||||
kind = fields.Constant(NESTED_KIND, data_key="kind", required=True)
|
||||
|
||||
|
||||
class EventEnumAbiEntrySchema(Schema):
|
||||
type = fields.Constant(EVENT_ENTRY, data_key="type", required=True)
|
||||
name = fields.String(data_key="name", required=True)
|
||||
kind = fields.Constant(ENUM_ENTRY, data_key="kind", required=True)
|
||||
variants = fields.List(
|
||||
fields.Nested(EventEnumVariantSchema()), data_key="variants", required=True
|
||||
)
|
||||
|
||||
|
||||
class EventAbiEntrySchema(OneOfSchema):
|
||||
type_field = "kind"
|
||||
type_field_remove = False
|
||||
type_schemas = {
|
||||
STRUCT_ENTRY: EventStructAbiEntrySchema,
|
||||
ENUM_ENTRY: EventEnumAbiEntrySchema,
|
||||
}
|
||||
|
||||
|
||||
class StructAbiEntrySchema(Schema):
|
||||
type = fields.Constant(STRUCT_ENTRY, data_key="type", required=True)
|
||||
name = fields.String(data_key="name", required=True)
|
||||
members = fields.List(
|
||||
fields.Nested(TypedParameterSchema()), data_key="members", required=True
|
||||
)
|
||||
|
||||
|
||||
class EnumAbiEntrySchema(Schema):
|
||||
type = fields.Constant(ENUM_ENTRY, data_key="type", required=True)
|
||||
name = fields.String(data_key="name", required=True)
|
||||
variants = fields.List(
|
||||
fields.Nested(TypedParameterSchema(), data_key="variants", required=True)
|
||||
)
|
||||
|
||||
|
||||
class ImplAbiEntrySchema(Schema):
|
||||
type = fields.Constant(IMPL_ENTRY, data_key="type", required=True)
|
||||
name = fields.String(data_key="name", required=True)
|
||||
interface_name = fields.String(data_key="interface_name", required=True)
|
||||
|
||||
|
||||
class InterfaceAbiEntrySchema(Schema):
|
||||
type = fields.Constant(INTERFACE_ENTRY, data_key="type", required=True)
|
||||
name = fields.String(data_key="name", required=True)
|
||||
|
||||
items = fields.List(
|
||||
fields.Nested(
|
||||
FunctionAbiEntrySchema(), data_key="items", required=True
|
||||
) # for now only functions can be defined here
|
||||
)
|
||||
|
||||
|
||||
class ContractAbiEntrySchema(OneOfSchema):
|
||||
type_field_remove = False
|
||||
type_schemas = {
|
||||
FUNCTION_ENTRY: FunctionAbiEntrySchema,
|
||||
EVENT_ENTRY: EventAbiEntrySchema,
|
||||
STRUCT_ENTRY: StructAbiEntrySchema,
|
||||
ENUM_ENTRY: EnumAbiEntrySchema,
|
||||
CONSTRUCTOR_ENTRY: ConstructorAbiEntrySchema,
|
||||
L1_HANDLER_ENTRY: L1HandlerAbiEntrySchema,
|
||||
IMPL_ENTRY: ImplAbiEntrySchema,
|
||||
INTERFACE_ENTRY: InterfaceAbiEntrySchema,
|
||||
}
|
||||
107
ccxt/static_dependencies/starknet/abi/v2/shape.py
Normal file
107
ccxt/static_dependencies/starknet/abi/v2/shape.py
Normal file
@@ -0,0 +1,107 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import List, Literal, Optional, TypedDict, Union
|
||||
|
||||
STRUCT_ENTRY = "struct"
|
||||
EVENT_ENTRY = "event"
|
||||
FUNCTION_ENTRY = "function"
|
||||
ENUM_ENTRY = "enum"
|
||||
CONSTRUCTOR_ENTRY = "constructor"
|
||||
L1_HANDLER_ENTRY = "l1_handler"
|
||||
IMPL_ENTRY = "impl"
|
||||
INTERFACE_ENTRY = "interface"
|
||||
|
||||
DATA_KIND = "data"
|
||||
NESTED_KIND = "nested"
|
||||
|
||||
|
||||
class TypeDict(TypedDict):
|
||||
type: str
|
||||
|
||||
|
||||
class TypedParameterDict(TypeDict):
|
||||
name: str
|
||||
|
||||
|
||||
class StructDict(TypedDict):
|
||||
type: Literal["struct"]
|
||||
name: str
|
||||
members: List[TypedParameterDict]
|
||||
|
||||
|
||||
class FunctionBaseDict(TypedDict):
|
||||
name: str
|
||||
inputs: List[TypedParameterDict]
|
||||
outputs: List[TypeDict]
|
||||
state_mutability: Optional[Literal["external", "view"]]
|
||||
|
||||
|
||||
class FunctionDict(FunctionBaseDict):
|
||||
type: Literal["function"]
|
||||
|
||||
|
||||
class ConstructorDict(TypedDict):
|
||||
type: Literal["constructor"]
|
||||
name: str
|
||||
inputs: List[TypedParameterDict]
|
||||
|
||||
|
||||
class L1HandlerDict(FunctionBaseDict):
|
||||
type: Literal["l1_handler"]
|
||||
|
||||
|
||||
class EventBaseDict(TypedDict):
|
||||
type: Literal["event"]
|
||||
name: str
|
||||
|
||||
|
||||
class EventStructMemberDict(TypedParameterDict):
|
||||
kind: Literal["data"]
|
||||
|
||||
|
||||
class EventStructDict(EventBaseDict):
|
||||
kind: Literal["struct"]
|
||||
members: List[EventStructMemberDict]
|
||||
|
||||
|
||||
class EventEnumVariantDict(TypedParameterDict):
|
||||
kind: Literal["nested"]
|
||||
|
||||
|
||||
class EventEnumDict(EventBaseDict):
|
||||
kind: Literal["enum"]
|
||||
variants: List[EventEnumVariantDict]
|
||||
|
||||
|
||||
EventDict = Union[EventStructDict, EventEnumDict]
|
||||
|
||||
|
||||
class EnumDict(TypedDict):
|
||||
type: Literal["enum"]
|
||||
name: str
|
||||
variants: List[TypedParameterDict]
|
||||
|
||||
|
||||
class ImplDict(TypedDict):
|
||||
type: Literal["impl"]
|
||||
name: str
|
||||
interface_name: str
|
||||
|
||||
|
||||
class InterfaceDict(TypedDict):
|
||||
type: Literal["interface"]
|
||||
name: str
|
||||
items: List[FunctionDict] # for now only functions can be defined here
|
||||
|
||||
|
||||
AbiDictEntry = Union[
|
||||
StructDict,
|
||||
FunctionDict,
|
||||
EventDict,
|
||||
EnumDict,
|
||||
ConstructorDict,
|
||||
L1HandlerDict,
|
||||
ImplDict,
|
||||
InterfaceDict,
|
||||
]
|
||||
AbiDictList = List[AbiDictEntry]
|
||||
Reference in New Issue
Block a user