coinex-api 0.0.15__py3-none-any.whl → 0.0.17__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coinex/__init__.py +7 -0
- coinex/ccxt/__init__.py +101 -0
- coinex/ccxt/abstract/coinex.py +237 -0
- coinex/ccxt/async_support/__init__.py +80 -0
- coinex/ccxt/async_support/base/__init__.py +1 -0
- coinex/ccxt/async_support/base/exchange.py +2100 -0
- coinex/ccxt/async_support/base/throttler.py +50 -0
- coinex/ccxt/async_support/base/ws/__init__.py +38 -0
- coinex/ccxt/async_support/base/ws/aiohttp_client.py +147 -0
- coinex/ccxt/async_support/base/ws/cache.py +213 -0
- coinex/ccxt/async_support/base/ws/client.py +214 -0
- coinex/ccxt/async_support/base/ws/fast_client.py +97 -0
- coinex/ccxt/async_support/base/ws/functions.py +59 -0
- coinex/ccxt/async_support/base/ws/future.py +69 -0
- coinex/ccxt/async_support/base/ws/order_book.py +78 -0
- coinex/ccxt/async_support/base/ws/order_book_side.py +174 -0
- coinex/ccxt/async_support/coinex.py +5833 -0
- coinex/ccxt/base/__init__.py +27 -0
- coinex/ccxt/base/decimal_to_precision.py +174 -0
- coinex/ccxt/base/errors.py +267 -0
- coinex/ccxt/base/exchange.py +6769 -0
- coinex/ccxt/base/precise.py +297 -0
- coinex/ccxt/base/types.py +577 -0
- coinex/ccxt/coinex.py +5832 -0
- coinex/ccxt/pro/__init__.py +21 -0
- coinex/ccxt/pro/coinex.py +1366 -0
- coinex/ccxt/static_dependencies/README.md +1 -0
- coinex/ccxt/static_dependencies/__init__.py +1 -0
- coinex/ccxt/static_dependencies/ecdsa/__init__.py +14 -0
- coinex/ccxt/static_dependencies/ecdsa/_version.py +520 -0
- coinex/ccxt/static_dependencies/ecdsa/curves.py +56 -0
- coinex/ccxt/static_dependencies/ecdsa/der.py +221 -0
- coinex/ccxt/static_dependencies/ecdsa/ecdsa.py +310 -0
- coinex/ccxt/static_dependencies/ecdsa/ellipticcurve.py +197 -0
- coinex/ccxt/static_dependencies/ecdsa/keys.py +332 -0
- coinex/ccxt/static_dependencies/ecdsa/numbertheory.py +531 -0
- coinex/ccxt/static_dependencies/ecdsa/rfc6979.py +100 -0
- coinex/ccxt/static_dependencies/ecdsa/util.py +266 -0
- coinex/ccxt/static_dependencies/ethereum/__init__.py +7 -0
- coinex/ccxt/static_dependencies/ethereum/abi/__init__.py +16 -0
- coinex/ccxt/static_dependencies/ethereum/abi/abi.py +19 -0
- coinex/ccxt/static_dependencies/ethereum/abi/base.py +152 -0
- coinex/ccxt/static_dependencies/ethereum/abi/codec.py +217 -0
- coinex/ccxt/static_dependencies/ethereum/abi/constants.py +3 -0
- coinex/ccxt/static_dependencies/ethereum/abi/decoding.py +565 -0
- coinex/ccxt/static_dependencies/ethereum/abi/encoding.py +720 -0
- coinex/ccxt/static_dependencies/ethereum/abi/exceptions.py +139 -0
- coinex/ccxt/static_dependencies/ethereum/abi/grammar.py +443 -0
- coinex/ccxt/static_dependencies/ethereum/abi/packed.py +13 -0
- coinex/ccxt/static_dependencies/ethereum/abi/py.typed +0 -0
- coinex/ccxt/static_dependencies/ethereum/abi/registry.py +643 -0
- coinex/ccxt/static_dependencies/ethereum/abi/tools/__init__.py +3 -0
- coinex/ccxt/static_dependencies/ethereum/abi/tools/_strategies.py +230 -0
- coinex/ccxt/static_dependencies/ethereum/abi/utils/__init__.py +0 -0
- coinex/ccxt/static_dependencies/ethereum/abi/utils/numeric.py +83 -0
- coinex/ccxt/static_dependencies/ethereum/abi/utils/padding.py +27 -0
- coinex/ccxt/static_dependencies/ethereum/abi/utils/string.py +19 -0
- coinex/ccxt/static_dependencies/ethereum/account/__init__.py +3 -0
- coinex/ccxt/static_dependencies/ethereum/account/encode_typed_data/__init__.py +4 -0
- coinex/ccxt/static_dependencies/ethereum/account/encode_typed_data/encoding_and_hashing.py +239 -0
- coinex/ccxt/static_dependencies/ethereum/account/encode_typed_data/helpers.py +40 -0
- coinex/ccxt/static_dependencies/ethereum/account/messages.py +263 -0
- coinex/ccxt/static_dependencies/ethereum/account/py.typed +0 -0
- coinex/ccxt/static_dependencies/ethereum/hexbytes/__init__.py +5 -0
- coinex/ccxt/static_dependencies/ethereum/hexbytes/_utils.py +54 -0
- coinex/ccxt/static_dependencies/ethereum/hexbytes/main.py +65 -0
- coinex/ccxt/static_dependencies/ethereum/hexbytes/py.typed +0 -0
- coinex/ccxt/static_dependencies/ethereum/typing/__init__.py +63 -0
- coinex/ccxt/static_dependencies/ethereum/typing/abi.py +6 -0
- coinex/ccxt/static_dependencies/ethereum/typing/bls.py +7 -0
- coinex/ccxt/static_dependencies/ethereum/typing/discovery.py +5 -0
- coinex/ccxt/static_dependencies/ethereum/typing/encoding.py +7 -0
- coinex/ccxt/static_dependencies/ethereum/typing/enums.py +17 -0
- coinex/ccxt/static_dependencies/ethereum/typing/ethpm.py +9 -0
- coinex/ccxt/static_dependencies/ethereum/typing/evm.py +20 -0
- coinex/ccxt/static_dependencies/ethereum/typing/networks.py +1122 -0
- coinex/ccxt/static_dependencies/ethereum/typing/py.typed +0 -0
- coinex/ccxt/static_dependencies/ethereum/utils/__init__.py +115 -0
- coinex/ccxt/static_dependencies/ethereum/utils/abi.py +72 -0
- coinex/ccxt/static_dependencies/ethereum/utils/address.py +171 -0
- coinex/ccxt/static_dependencies/ethereum/utils/applicators.py +151 -0
- coinex/ccxt/static_dependencies/ethereum/utils/conversions.py +190 -0
- coinex/ccxt/static_dependencies/ethereum/utils/currency.py +107 -0
- coinex/ccxt/static_dependencies/ethereum/utils/curried/__init__.py +269 -0
- coinex/ccxt/static_dependencies/ethereum/utils/debug.py +20 -0
- coinex/ccxt/static_dependencies/ethereum/utils/decorators.py +132 -0
- coinex/ccxt/static_dependencies/ethereum/utils/encoding.py +6 -0
- coinex/ccxt/static_dependencies/ethereum/utils/exceptions.py +4 -0
- coinex/ccxt/static_dependencies/ethereum/utils/functional.py +75 -0
- coinex/ccxt/static_dependencies/ethereum/utils/hexadecimal.py +74 -0
- coinex/ccxt/static_dependencies/ethereum/utils/humanize.py +188 -0
- coinex/ccxt/static_dependencies/ethereum/utils/logging.py +159 -0
- coinex/ccxt/static_dependencies/ethereum/utils/module_loading.py +31 -0
- coinex/ccxt/static_dependencies/ethereum/utils/numeric.py +43 -0
- coinex/ccxt/static_dependencies/ethereum/utils/py.typed +0 -0
- coinex/ccxt/static_dependencies/ethereum/utils/toolz.py +76 -0
- coinex/ccxt/static_dependencies/ethereum/utils/types.py +54 -0
- coinex/ccxt/static_dependencies/ethereum/utils/typing/__init__.py +18 -0
- coinex/ccxt/static_dependencies/ethereum/utils/typing/misc.py +14 -0
- coinex/ccxt/static_dependencies/ethereum/utils/units.py +31 -0
- coinex/ccxt/static_dependencies/keccak/__init__.py +3 -0
- coinex/ccxt/static_dependencies/keccak/keccak.py +197 -0
- coinex/ccxt/static_dependencies/lark/__init__.py +38 -0
- coinex/ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
- coinex/ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
- coinex/ccxt/static_dependencies/lark/ast_utils.py +59 -0
- coinex/ccxt/static_dependencies/lark/common.py +86 -0
- coinex/ccxt/static_dependencies/lark/exceptions.py +292 -0
- coinex/ccxt/static_dependencies/lark/grammar.py +130 -0
- coinex/ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
- coinex/ccxt/static_dependencies/lark/grammars/common.lark +59 -0
- coinex/ccxt/static_dependencies/lark/grammars/lark.lark +62 -0
- coinex/ccxt/static_dependencies/lark/grammars/python.lark +302 -0
- coinex/ccxt/static_dependencies/lark/grammars/unicode.lark +7 -0
- coinex/ccxt/static_dependencies/lark/indenter.py +143 -0
- coinex/ccxt/static_dependencies/lark/lark.py +658 -0
- coinex/ccxt/static_dependencies/lark/lexer.py +678 -0
- coinex/ccxt/static_dependencies/lark/load_grammar.py +1428 -0
- coinex/ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
- coinex/ccxt/static_dependencies/lark/parser_frontends.py +257 -0
- coinex/ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
- coinex/ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
- coinex/ccxt/static_dependencies/lark/parsers/earley.py +314 -0
- coinex/ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
- coinex/ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
- coinex/ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
- coinex/ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
- coinex/ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
- coinex/ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
- coinex/ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
- coinex/ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
- coinex/ccxt/static_dependencies/lark/py.typed +0 -0
- coinex/ccxt/static_dependencies/lark/reconstruct.py +107 -0
- coinex/ccxt/static_dependencies/lark/tools/__init__.py +70 -0
- coinex/ccxt/static_dependencies/lark/tools/nearley.py +202 -0
- coinex/ccxt/static_dependencies/lark/tools/serialize.py +32 -0
- coinex/ccxt/static_dependencies/lark/tools/standalone.py +196 -0
- coinex/ccxt/static_dependencies/lark/tree.py +267 -0
- coinex/ccxt/static_dependencies/lark/tree_matcher.py +186 -0
- coinex/ccxt/static_dependencies/lark/tree_templates.py +180 -0
- coinex/ccxt/static_dependencies/lark/utils.py +343 -0
- coinex/ccxt/static_dependencies/lark/visitors.py +596 -0
- coinex/ccxt/static_dependencies/marshmallow/__init__.py +81 -0
- coinex/ccxt/static_dependencies/marshmallow/base.py +65 -0
- coinex/ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
- coinex/ccxt/static_dependencies/marshmallow/decorators.py +231 -0
- coinex/ccxt/static_dependencies/marshmallow/error_store.py +60 -0
- coinex/ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
- coinex/ccxt/static_dependencies/marshmallow/fields.py +2114 -0
- coinex/ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
- coinex/ccxt/static_dependencies/marshmallow/py.typed +0 -0
- coinex/ccxt/static_dependencies/marshmallow/schema.py +1228 -0
- coinex/ccxt/static_dependencies/marshmallow/types.py +12 -0
- coinex/ccxt/static_dependencies/marshmallow/utils.py +378 -0
- coinex/ccxt/static_dependencies/marshmallow/validate.py +678 -0
- coinex/ccxt/static_dependencies/marshmallow/warnings.py +2 -0
- coinex/ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
- coinex/ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
- coinex/ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
- coinex/ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
- coinex/ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
- coinex/ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
- coinex/ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
- coinex/ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
- coinex/ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
- coinex/ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
- coinex/ccxt/static_dependencies/msgpack/__init__.py +55 -0
- coinex/ccxt/static_dependencies/msgpack/_cmsgpack.pyx +11 -0
- coinex/ccxt/static_dependencies/msgpack/_packer.pyx +374 -0
- coinex/ccxt/static_dependencies/msgpack/_unpacker.pyx +547 -0
- coinex/ccxt/static_dependencies/msgpack/buff_converter.h +8 -0
- coinex/ccxt/static_dependencies/msgpack/exceptions.py +48 -0
- coinex/ccxt/static_dependencies/msgpack/ext.py +168 -0
- coinex/ccxt/static_dependencies/msgpack/fallback.py +951 -0
- coinex/ccxt/static_dependencies/msgpack/pack.h +89 -0
- coinex/ccxt/static_dependencies/msgpack/pack_template.h +820 -0
- coinex/ccxt/static_dependencies/msgpack/sysdep.h +194 -0
- coinex/ccxt/static_dependencies/msgpack/unpack.h +391 -0
- coinex/ccxt/static_dependencies/msgpack/unpack_define.h +95 -0
- coinex/ccxt/static_dependencies/msgpack/unpack_template.h +464 -0
- coinex/ccxt/static_dependencies/parsimonious/__init__.py +10 -0
- coinex/ccxt/static_dependencies/parsimonious/exceptions.py +105 -0
- coinex/ccxt/static_dependencies/parsimonious/expressions.py +479 -0
- coinex/ccxt/static_dependencies/parsimonious/grammar.py +487 -0
- coinex/ccxt/static_dependencies/parsimonious/nodes.py +325 -0
- coinex/ccxt/static_dependencies/parsimonious/utils.py +40 -0
- coinex/ccxt/static_dependencies/starknet/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/abi/v0/__init__.py +2 -0
- coinex/ccxt/static_dependencies/starknet/abi/v0/model.py +44 -0
- coinex/ccxt/static_dependencies/starknet/abi/v0/parser.py +216 -0
- coinex/ccxt/static_dependencies/starknet/abi/v0/schemas.py +72 -0
- coinex/ccxt/static_dependencies/starknet/abi/v0/shape.py +63 -0
- coinex/ccxt/static_dependencies/starknet/abi/v1/__init__.py +2 -0
- coinex/ccxt/static_dependencies/starknet/abi/v1/core_structures.json +14 -0
- coinex/ccxt/static_dependencies/starknet/abi/v1/model.py +39 -0
- coinex/ccxt/static_dependencies/starknet/abi/v1/parser.py +220 -0
- coinex/ccxt/static_dependencies/starknet/abi/v1/parser_transformer.py +179 -0
- coinex/ccxt/static_dependencies/starknet/abi/v1/schemas.py +66 -0
- coinex/ccxt/static_dependencies/starknet/abi/v1/shape.py +47 -0
- coinex/ccxt/static_dependencies/starknet/abi/v2/__init__.py +2 -0
- coinex/ccxt/static_dependencies/starknet/abi/v2/model.py +89 -0
- coinex/ccxt/static_dependencies/starknet/abi/v2/parser.py +293 -0
- coinex/ccxt/static_dependencies/starknet/abi/v2/parser_transformer.py +192 -0
- coinex/ccxt/static_dependencies/starknet/abi/v2/schemas.py +132 -0
- coinex/ccxt/static_dependencies/starknet/abi/v2/shape.py +107 -0
- coinex/ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
- coinex/ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
- coinex/ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
- coinex/ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
- coinex/ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
- coinex/ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
- coinex/ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
- coinex/ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
- coinex/ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
- coinex/ccxt/static_dependencies/starknet/common.py +15 -0
- coinex/ccxt/static_dependencies/starknet/constants.py +39 -0
- coinex/ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/hash/address.py +79 -0
- coinex/ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
- coinex/ccxt/static_dependencies/starknet/hash/selector.py +16 -0
- coinex/ccxt/static_dependencies/starknet/hash/storage.py +12 -0
- coinex/ccxt/static_dependencies/starknet/hash/utils.py +78 -0
- coinex/ccxt/static_dependencies/starknet/models/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
- coinex/ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
- coinex/ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
- coinex/ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
- coinex/ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
- coinex/ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
- coinex/ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
- coinex/ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
- coinex/ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
- coinex/ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
- coinex/ccxt/static_dependencies/starknet/utils/schema.py +13 -0
- coinex/ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
- coinex/ccxt/static_dependencies/starkware/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
- coinex/ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
- coinex/ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
- coinex/ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
- coinex/ccxt/static_dependencies/sympy/__init__.py +0 -0
- coinex/ccxt/static_dependencies/sympy/core/__init__.py +0 -0
- coinex/ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
- coinex/ccxt/static_dependencies/sympy/external/__init__.py +0 -0
- coinex/ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
- coinex/ccxt/static_dependencies/sympy/external/importtools.py +187 -0
- coinex/ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
- coinex/ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
- coinex/ccxt/static_dependencies/toolz/__init__.py +26 -0
- coinex/ccxt/static_dependencies/toolz/_signatures.py +784 -0
- coinex/ccxt/static_dependencies/toolz/_version.py +520 -0
- coinex/ccxt/static_dependencies/toolz/compatibility.py +30 -0
- coinex/ccxt/static_dependencies/toolz/curried/__init__.py +101 -0
- coinex/ccxt/static_dependencies/toolz/curried/exceptions.py +22 -0
- coinex/ccxt/static_dependencies/toolz/curried/operator.py +22 -0
- coinex/ccxt/static_dependencies/toolz/dicttoolz.py +339 -0
- coinex/ccxt/static_dependencies/toolz/functoolz.py +1049 -0
- coinex/ccxt/static_dependencies/toolz/itertoolz.py +1057 -0
- coinex/ccxt/static_dependencies/toolz/recipes.py +46 -0
- coinex/ccxt/static_dependencies/toolz/utils.py +9 -0
- coinex/ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
- coinex/ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
- coinex_api-0.0.17.dist-info/METADATA +425 -0
- coinex_api-0.0.17.dist-info/RECORD +288 -0
- coinex_api-0.0.15.dist-info/METADATA +0 -79
- coinex_api-0.0.15.dist-info/RECORD +0 -3
- {coinex_api-0.0.15.dist-info → coinex_api-0.0.17.dist-info}/WHEEL +0 -0
@@ -0,0 +1,229 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from collections import OrderedDict
|
4
|
+
from typing import Dict, List, Union
|
5
|
+
|
6
|
+
from ..abi.v0 import Abi as AbiV0
|
7
|
+
from ..abi.v1 import Abi as AbiV1
|
8
|
+
from ..abi.v2 import Abi as AbiV2
|
9
|
+
from ..cairo.data_types import (
|
10
|
+
ArrayType,
|
11
|
+
BoolType,
|
12
|
+
CairoType,
|
13
|
+
EnumType,
|
14
|
+
EventType,
|
15
|
+
FeltType,
|
16
|
+
NamedTupleType,
|
17
|
+
OptionType,
|
18
|
+
StructType,
|
19
|
+
TupleType,
|
20
|
+
UintType,
|
21
|
+
UnitType,
|
22
|
+
)
|
23
|
+
from .data_serializers import (
|
24
|
+
BoolSerializer,
|
25
|
+
ByteArraySerializer,
|
26
|
+
)
|
27
|
+
from .data_serializers.array_serializer import ArraySerializer
|
28
|
+
from .data_serializers.cairo_data_serializer import (
|
29
|
+
CairoDataSerializer,
|
30
|
+
)
|
31
|
+
from .data_serializers.enum_serializer import EnumSerializer
|
32
|
+
from .data_serializers.felt_serializer import FeltSerializer
|
33
|
+
from .data_serializers.named_tuple_serializer import (
|
34
|
+
NamedTupleSerializer,
|
35
|
+
)
|
36
|
+
from .data_serializers.option_serializer import (
|
37
|
+
OptionSerializer,
|
38
|
+
)
|
39
|
+
from .data_serializers.output_serializer import (
|
40
|
+
OutputSerializer,
|
41
|
+
)
|
42
|
+
from .data_serializers.payload_serializer import (
|
43
|
+
PayloadSerializer,
|
44
|
+
)
|
45
|
+
from .data_serializers.struct_serializer import (
|
46
|
+
StructSerializer,
|
47
|
+
)
|
48
|
+
from .data_serializers.tuple_serializer import TupleSerializer
|
49
|
+
from .data_serializers.uint256_serializer import (
|
50
|
+
Uint256Serializer,
|
51
|
+
)
|
52
|
+
from .data_serializers.uint_serializer import UintSerializer
|
53
|
+
from .data_serializers.unit_serializer import UnitSerializer
|
54
|
+
from .errors import InvalidTypeException
|
55
|
+
from .function_serialization_adapter import (
|
56
|
+
FunctionSerializationAdapter,
|
57
|
+
FunctionSerializationAdapterV1,
|
58
|
+
)
|
59
|
+
|
60
|
+
_uint256_type = StructType("Uint256", OrderedDict(low=FeltType(), high=FeltType()))
|
61
|
+
_byte_array_type = StructType(
|
62
|
+
"core::byte_array::ByteArray",
|
63
|
+
OrderedDict(
|
64
|
+
data=ArrayType(FeltType()),
|
65
|
+
pending_word=FeltType(),
|
66
|
+
pending_word_len=UintType(bits=32),
|
67
|
+
),
|
68
|
+
)
|
69
|
+
|
70
|
+
|
71
|
+
def serializer_for_type(cairo_type: CairoType) -> CairoDataSerializer:
|
72
|
+
"""
|
73
|
+
Create a serializer for cairo type.
|
74
|
+
|
75
|
+
:param cairo_type: CairoType.
|
76
|
+
:return: CairoDataSerializer.
|
77
|
+
"""
|
78
|
+
# pylint: disable=too-many-return-statements, too-many-branches
|
79
|
+
if isinstance(cairo_type, FeltType):
|
80
|
+
return FeltSerializer()
|
81
|
+
|
82
|
+
if isinstance(cairo_type, BoolType):
|
83
|
+
return BoolSerializer()
|
84
|
+
|
85
|
+
if isinstance(cairo_type, StructType):
|
86
|
+
# Special case: Uint256 is represented as struct
|
87
|
+
if cairo_type == _uint256_type:
|
88
|
+
return Uint256Serializer()
|
89
|
+
|
90
|
+
if cairo_type == _byte_array_type:
|
91
|
+
return ByteArraySerializer()
|
92
|
+
|
93
|
+
return StructSerializer(
|
94
|
+
OrderedDict(
|
95
|
+
(name, serializer_for_type(member_type))
|
96
|
+
for name, member_type in cairo_type.types.items()
|
97
|
+
)
|
98
|
+
)
|
99
|
+
|
100
|
+
if isinstance(cairo_type, ArrayType):
|
101
|
+
return ArraySerializer(serializer_for_type(cairo_type.inner_type))
|
102
|
+
|
103
|
+
if isinstance(cairo_type, TupleType):
|
104
|
+
return TupleSerializer(
|
105
|
+
[serializer_for_type(member) for member in cairo_type.types]
|
106
|
+
)
|
107
|
+
|
108
|
+
if isinstance(cairo_type, NamedTupleType):
|
109
|
+
return NamedTupleSerializer(
|
110
|
+
OrderedDict(
|
111
|
+
(name, serializer_for_type(member_type))
|
112
|
+
for name, member_type in cairo_type.types.items()
|
113
|
+
)
|
114
|
+
)
|
115
|
+
|
116
|
+
if isinstance(cairo_type, UintType):
|
117
|
+
return UintSerializer(bits=cairo_type.bits)
|
118
|
+
|
119
|
+
if isinstance(cairo_type, OptionType):
|
120
|
+
return OptionSerializer(serializer_for_type(cairo_type.type))
|
121
|
+
|
122
|
+
if isinstance(cairo_type, UnitType):
|
123
|
+
return UnitSerializer()
|
124
|
+
|
125
|
+
if isinstance(cairo_type, EnumType):
|
126
|
+
return EnumSerializer(
|
127
|
+
OrderedDict(
|
128
|
+
(name, serializer_for_type(variant_type))
|
129
|
+
for name, variant_type in cairo_type.variants.items()
|
130
|
+
)
|
131
|
+
)
|
132
|
+
if isinstance(cairo_type, EventType):
|
133
|
+
return serializer_for_payload(cairo_type.types)
|
134
|
+
|
135
|
+
raise InvalidTypeException(f"Received unknown Cairo type '{cairo_type}'.")
|
136
|
+
|
137
|
+
|
138
|
+
# We don't want to require users to use OrderedDict. Regular python requires order since python 3.7.
|
139
|
+
def serializer_for_payload(payload: Dict[str, CairoType]) -> PayloadSerializer:
|
140
|
+
"""
|
141
|
+
Create PayloadSerializer for types listed in a dictionary. Please note that the order of fields in the dict is
|
142
|
+
very important. Make sure the keys are provided in the right order.
|
143
|
+
|
144
|
+
:param payload: dictionary with cairo types.
|
145
|
+
:return: PayloadSerializer that can be used to (de)serialize events/function calls.
|
146
|
+
"""
|
147
|
+
return PayloadSerializer(
|
148
|
+
OrderedDict(
|
149
|
+
(name, serializer_for_type(cairo_type))
|
150
|
+
for name, cairo_type in payload.items()
|
151
|
+
)
|
152
|
+
)
|
153
|
+
|
154
|
+
|
155
|
+
def serializer_for_outputs(payload: List[CairoType]) -> OutputSerializer:
|
156
|
+
"""
|
157
|
+
Create OutputSerializer for types in list. Please note that the order of fields in the list is
|
158
|
+
very important. Make sure the types are provided in the right order.
|
159
|
+
|
160
|
+
:param payload: list with cairo types.
|
161
|
+
:return: OutputSerializer that can be used to deserialize function outputs.
|
162
|
+
"""
|
163
|
+
return OutputSerializer(
|
164
|
+
serializers=[serializer_for_type(cairo_type) for cairo_type in payload]
|
165
|
+
)
|
166
|
+
|
167
|
+
|
168
|
+
EventV0 = AbiV0.Event
|
169
|
+
EventV1 = AbiV1.Event
|
170
|
+
EventV2 = EventType
|
171
|
+
|
172
|
+
|
173
|
+
def serializer_for_event(event: EventV0 | EventV1 | EventV2) -> PayloadSerializer:
|
174
|
+
"""
|
175
|
+
Create serializer for an event.
|
176
|
+
|
177
|
+
:param event: parsed event.
|
178
|
+
:return: PayloadSerializer that can be used to (de)serialize events.
|
179
|
+
"""
|
180
|
+
if isinstance(event, EventV0):
|
181
|
+
return serializer_for_payload(event.data)
|
182
|
+
if isinstance(event, EventV1):
|
183
|
+
return serializer_for_payload(event.inputs)
|
184
|
+
return serializer_for_payload(event.types)
|
185
|
+
|
186
|
+
|
187
|
+
def serializer_for_function(
|
188
|
+
abi_function: AbiV0.Function,
|
189
|
+
) -> FunctionSerializationAdapter:
|
190
|
+
"""
|
191
|
+
Create FunctionSerializationAdapter for serializing function inputs and deserializing function outputs.
|
192
|
+
|
193
|
+
:param abi_function: parsed function's abi.
|
194
|
+
:return: FunctionSerializationAdapter.
|
195
|
+
"""
|
196
|
+
return FunctionSerializationAdapter(
|
197
|
+
inputs_serializer=serializer_for_payload(abi_function.inputs),
|
198
|
+
outputs_deserializer=serializer_for_payload(abi_function.outputs),
|
199
|
+
)
|
200
|
+
|
201
|
+
|
202
|
+
def serializer_for_function_v1(
|
203
|
+
abi_function: Union[AbiV1.Function, AbiV2.Function],
|
204
|
+
) -> FunctionSerializationAdapter:
|
205
|
+
"""
|
206
|
+
Create FunctionSerializationAdapter for serializing function inputs and deserializing function outputs.
|
207
|
+
|
208
|
+
:param abi_function: parsed function's abi.
|
209
|
+
:return: FunctionSerializationAdapter.
|
210
|
+
"""
|
211
|
+
return FunctionSerializationAdapterV1(
|
212
|
+
inputs_serializer=serializer_for_payload(abi_function.inputs),
|
213
|
+
outputs_deserializer=serializer_for_outputs(abi_function.outputs),
|
214
|
+
)
|
215
|
+
|
216
|
+
|
217
|
+
def serializer_for_constructor_v2(
|
218
|
+
abi_function: AbiV2.Constructor,
|
219
|
+
) -> FunctionSerializationAdapter:
|
220
|
+
"""
|
221
|
+
Create FunctionSerializationAdapter for serializing constructor inputs.
|
222
|
+
|
223
|
+
:param abi_function: parsed constructor's abi.
|
224
|
+
:return: FunctionSerializationAdapter.
|
225
|
+
"""
|
226
|
+
return FunctionSerializationAdapterV1(
|
227
|
+
inputs_serializer=serializer_for_payload(abi_function.inputs),
|
228
|
+
outputs_deserializer=serializer_for_outputs([]),
|
229
|
+
)
|
@@ -0,0 +1,110 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from dataclasses import dataclass, field
|
4
|
+
from typing import Dict, List, Set, Tuple
|
5
|
+
|
6
|
+
from ..cairo.felt import CairoData
|
7
|
+
from .data_serializers.output_serializer import (
|
8
|
+
OutputSerializer,
|
9
|
+
)
|
10
|
+
from .data_serializers.payload_serializer import (
|
11
|
+
PayloadSerializer,
|
12
|
+
)
|
13
|
+
from .errors import InvalidTypeException
|
14
|
+
from .tuple_dataclass import TupleDataclass
|
15
|
+
|
16
|
+
|
17
|
+
@dataclass
|
18
|
+
class FunctionSerializationAdapter:
|
19
|
+
"""
|
20
|
+
Class serializing ``*args`` and ``**kwargs`` by adapting them to function inputs.
|
21
|
+
"""
|
22
|
+
|
23
|
+
inputs_serializer: PayloadSerializer
|
24
|
+
outputs_deserializer: PayloadSerializer
|
25
|
+
|
26
|
+
expected_args: Tuple[str] = field(init=False)
|
27
|
+
|
28
|
+
def __post_init__(self):
|
29
|
+
self.expected_args = tuple(
|
30
|
+
self.inputs_serializer.serializers.keys()
|
31
|
+
) # pyright: ignore
|
32
|
+
|
33
|
+
def serialize(self, *args, **kwargs) -> CairoData:
|
34
|
+
"""
|
35
|
+
Method using args and kwargs to match members and serialize them separately.
|
36
|
+
|
37
|
+
:return: Members serialized separately in SerializedPayload.
|
38
|
+
"""
|
39
|
+
named_arguments = self._merge_arguments(args, kwargs)
|
40
|
+
return self.inputs_serializer.serialize(named_arguments)
|
41
|
+
|
42
|
+
def deserialize(self, data: List[int]) -> TupleDataclass:
|
43
|
+
"""
|
44
|
+
Deserializes data into TupleDataclass containing python representations.
|
45
|
+
|
46
|
+
:return: cairo data.
|
47
|
+
"""
|
48
|
+
return self.outputs_deserializer.deserialize(data)
|
49
|
+
|
50
|
+
def _merge_arguments(self, args: Tuple, kwargs: Dict) -> Dict:
|
51
|
+
"""
|
52
|
+
Merges positional and keyed arguments.
|
53
|
+
"""
|
54
|
+
# After this line we know that len(args) <= len(self.expected_args)
|
55
|
+
self._ensure_no_unnecessary_positional_args(args)
|
56
|
+
|
57
|
+
named_arguments = dict(kwargs)
|
58
|
+
for arg, input_name in zip(args, self.expected_args):
|
59
|
+
if input_name in kwargs:
|
60
|
+
raise InvalidTypeException(
|
61
|
+
f"Both positional and named argument provided for '{input_name}'."
|
62
|
+
)
|
63
|
+
named_arguments[input_name] = arg
|
64
|
+
|
65
|
+
expected_args = set(self.expected_args)
|
66
|
+
provided_args = set(named_arguments.keys())
|
67
|
+
|
68
|
+
# named_arguments might have unnecessary arguments coming from kwargs (we ensure that
|
69
|
+
# len(args) <= len(self.expected_args) above)
|
70
|
+
self._ensure_no_unnecessary_args(expected_args, provided_args)
|
71
|
+
|
72
|
+
# there might be some argument missing (not provided)
|
73
|
+
self._ensure_no_missing_args(expected_args, provided_args)
|
74
|
+
|
75
|
+
return named_arguments
|
76
|
+
|
77
|
+
def _ensure_no_unnecessary_positional_args(self, args: Tuple):
|
78
|
+
if len(args) > len(self.expected_args):
|
79
|
+
raise InvalidTypeException(
|
80
|
+
f"Provided {len(args)} positional arguments, {len(self.expected_args)} possible."
|
81
|
+
)
|
82
|
+
|
83
|
+
@staticmethod
|
84
|
+
def _ensure_no_unnecessary_args(expected_args: Set[str], provided_args: Set[str]):
|
85
|
+
excessive_arguments = provided_args - expected_args
|
86
|
+
if excessive_arguments:
|
87
|
+
raise InvalidTypeException(
|
88
|
+
f"Unnecessary named arguments provided: '{', '.join(excessive_arguments)}'."
|
89
|
+
)
|
90
|
+
|
91
|
+
@staticmethod
|
92
|
+
def _ensure_no_missing_args(expected_args: Set[str], provided_args: Set[str]):
|
93
|
+
missing_arguments = expected_args - provided_args
|
94
|
+
if missing_arguments:
|
95
|
+
raise InvalidTypeException(
|
96
|
+
f"Missing arguments: '{', '.join(missing_arguments)}'."
|
97
|
+
)
|
98
|
+
|
99
|
+
|
100
|
+
@dataclass
|
101
|
+
class FunctionSerializationAdapterV1(FunctionSerializationAdapter):
|
102
|
+
outputs_deserializer: OutputSerializer
|
103
|
+
|
104
|
+
def deserialize(self, data: List[int]) -> Tuple:
|
105
|
+
"""
|
106
|
+
Deserializes data into TupleDataclass containing python representations.
|
107
|
+
|
108
|
+
:return: cairo data.
|
109
|
+
"""
|
110
|
+
return self.outputs_deserializer.deserialize(data)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from dataclasses import dataclass, fields, make_dataclass
|
4
|
+
from typing import Dict, Optional, Tuple
|
5
|
+
|
6
|
+
|
7
|
+
@dataclass(frozen=True, eq=False)
|
8
|
+
class TupleDataclass:
|
9
|
+
"""
|
10
|
+
Dataclass that behaves like a tuple at the same time. Used when data has defined order and names.
|
11
|
+
For instance in case of named tuples or function responses.
|
12
|
+
"""
|
13
|
+
|
14
|
+
# getattr is called when attribute is not found in object. For instance when using object.unknown_attribute.
|
15
|
+
# This way pyright will know that there might be some arguments it doesn't know about and will stop complaining
|
16
|
+
# about some fields that don't exist statically.
|
17
|
+
def __getattr__(self, item):
|
18
|
+
# This should always fail - only attributes that don't exist end up in here.
|
19
|
+
# We use __getattribute__ to get the native error.
|
20
|
+
return super().__getattribute__(item)
|
21
|
+
|
22
|
+
def __getitem__(self, item: int):
|
23
|
+
field = fields(self)[item]
|
24
|
+
return getattr(self, field.name)
|
25
|
+
|
26
|
+
def __iter__(self):
|
27
|
+
return (getattr(self, field.name) for field in fields(self))
|
28
|
+
|
29
|
+
def as_tuple(self) -> Tuple:
|
30
|
+
"""
|
31
|
+
Creates a regular tuple from TupleDataclass.
|
32
|
+
"""
|
33
|
+
return tuple(self)
|
34
|
+
|
35
|
+
def as_dict(self) -> Dict:
|
36
|
+
"""
|
37
|
+
Creates a regular dict from TupleDataclass.
|
38
|
+
"""
|
39
|
+
return {field.name: getattr(self, field.name) for field in fields(self)}
|
40
|
+
|
41
|
+
# Added for backward compatibility with previous implementation based on NamedTuple
|
42
|
+
def _asdict(self):
|
43
|
+
return self.as_dict()
|
44
|
+
|
45
|
+
def __eq__(self, other):
|
46
|
+
if isinstance(other, TupleDataclass):
|
47
|
+
return self.as_tuple() == other.as_tuple()
|
48
|
+
return self.as_tuple() == other
|
49
|
+
|
50
|
+
@staticmethod
|
51
|
+
def from_dict(data: Dict, *, name: Optional[str] = None) -> TupleDataclass:
|
52
|
+
result_class = make_dataclass(
|
53
|
+
name or "TupleDataclass",
|
54
|
+
fields=[(key, type(value)) for key, value in data.items()],
|
55
|
+
bases=(TupleDataclass,),
|
56
|
+
frozen=True,
|
57
|
+
eq=False,
|
58
|
+
)
|
59
|
+
return result_class(**data)
|
File without changes
|
@@ -0,0 +1,86 @@
|
|
1
|
+
from typing import List, Optional, Union
|
2
|
+
|
3
|
+
from ..abi.v2 import shape as ShapeV2
|
4
|
+
from ..abi.v0 import AbiParser as AbiParserV0
|
5
|
+
from ..abi.v1 import AbiParser as AbiParserV1
|
6
|
+
from ..abi.v2 import AbiParser as AbiParserV2
|
7
|
+
from ..serialization import (
|
8
|
+
FunctionSerializationAdapter,
|
9
|
+
serializer_for_function,
|
10
|
+
)
|
11
|
+
from ..serialization.factory import (
|
12
|
+
serializer_for_constructor_v2,
|
13
|
+
serializer_for_function_v1,
|
14
|
+
)
|
15
|
+
|
16
|
+
|
17
|
+
def translate_constructor_args(
|
18
|
+
abi: List, constructor_args: Optional[Union[List, dict]], *, cairo_version: int = 1
|
19
|
+
) -> List[int]:
|
20
|
+
serializer = (
|
21
|
+
_get_constructor_serializer_v1(abi)
|
22
|
+
if cairo_version == 1
|
23
|
+
else _get_constructor_serializer_v0(abi)
|
24
|
+
)
|
25
|
+
|
26
|
+
if serializer is None or len(serializer.inputs_serializer.serializers) == 0:
|
27
|
+
return []
|
28
|
+
|
29
|
+
if not constructor_args:
|
30
|
+
raise ValueError(
|
31
|
+
"Provided contract has a constructor and no arguments were provided."
|
32
|
+
)
|
33
|
+
|
34
|
+
args, kwargs = (
|
35
|
+
([], constructor_args)
|
36
|
+
if isinstance(constructor_args, dict)
|
37
|
+
else (constructor_args, {})
|
38
|
+
)
|
39
|
+
return serializer.serialize(*args, **kwargs)
|
40
|
+
|
41
|
+
|
42
|
+
def _get_constructor_serializer_v1(abi: List) -> Optional[FunctionSerializationAdapter]:
|
43
|
+
if _is_abi_v2(abi):
|
44
|
+
parsed = AbiParserV2(abi).parse()
|
45
|
+
constructor = parsed.constructor
|
46
|
+
|
47
|
+
if constructor is None or not constructor.inputs:
|
48
|
+
return None
|
49
|
+
|
50
|
+
return serializer_for_constructor_v2(constructor)
|
51
|
+
|
52
|
+
parsed = AbiParserV1(abi).parse()
|
53
|
+
constructor = parsed.functions.get("constructor", None)
|
54
|
+
|
55
|
+
# Constructor might not accept any arguments
|
56
|
+
if constructor is None or not constructor.inputs:
|
57
|
+
return None
|
58
|
+
|
59
|
+
return serializer_for_function_v1(constructor)
|
60
|
+
|
61
|
+
|
62
|
+
def _is_abi_v2(abi: List) -> bool:
|
63
|
+
for entry in abi:
|
64
|
+
if entry["type"] in [
|
65
|
+
ShapeV2.CONSTRUCTOR_ENTRY,
|
66
|
+
ShapeV2.L1_HANDLER_ENTRY,
|
67
|
+
ShapeV2.INTERFACE_ENTRY,
|
68
|
+
ShapeV2.IMPL_ENTRY,
|
69
|
+
]:
|
70
|
+
return True
|
71
|
+
if entry["type"] == ShapeV2.EVENT_ENTRY:
|
72
|
+
if "inputs" in entry:
|
73
|
+
return False
|
74
|
+
if "kind" in entry:
|
75
|
+
return True
|
76
|
+
return False
|
77
|
+
|
78
|
+
|
79
|
+
def _get_constructor_serializer_v0(abi: List) -> Optional[FunctionSerializationAdapter]:
|
80
|
+
parsed = AbiParserV0(abi).parse()
|
81
|
+
|
82
|
+
# Constructor might not accept any arguments
|
83
|
+
if not parsed.constructor or not parsed.constructor.inputs:
|
84
|
+
return None
|
85
|
+
|
86
|
+
return serializer_for_function(parsed.constructor)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
from typing import Iterable, TypeVar, Union
|
2
|
+
|
3
|
+
T = TypeVar("T")
|
4
|
+
|
5
|
+
|
6
|
+
# pyright: reportGeneralTypeIssues=false
|
7
|
+
def ensure_iterable(value: Union[T, Iterable[T]]) -> Iterable[T]:
|
8
|
+
try:
|
9
|
+
iter(value)
|
10
|
+
# Now we now it is iterable
|
11
|
+
return value
|
12
|
+
except TypeError:
|
13
|
+
return [value]
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
from ..marshmallow import EXCLUDE, RAISE
|
4
|
+
from ..marshmallow import Schema as MarshmallowSchema
|
5
|
+
|
6
|
+
MARSHMALLOW_UKNOWN_EXCLUDE = os.environ.get("STARKNET_PY_MARSHMALLOW_UKNOWN_EXCLUDE")
|
7
|
+
|
8
|
+
|
9
|
+
class Schema(MarshmallowSchema):
|
10
|
+
class Meta:
|
11
|
+
unknown = (
|
12
|
+
EXCLUDE if (MARSHMALLOW_UKNOWN_EXCLUDE or "").lower() == "true" else RAISE
|
13
|
+
)
|
@@ -0,0 +1,182 @@
|
|
1
|
+
from dataclasses import dataclass
|
2
|
+
from typing import Dict, List, Union, cast
|
3
|
+
|
4
|
+
from ...marshmallow import Schema, fields, post_load
|
5
|
+
|
6
|
+
from ..cairo.felt import encode_shortstring
|
7
|
+
from ..hash.selector import get_selector_from_name
|
8
|
+
from ..hash.utils import compute_hash_on_elements
|
9
|
+
from ..models.typed_data import StarkNetDomainDict, TypedDataDict
|
10
|
+
|
11
|
+
|
12
|
+
@dataclass(frozen=True)
|
13
|
+
class Parameter:
|
14
|
+
"""
|
15
|
+
Dataclass representing a Parameter object
|
16
|
+
"""
|
17
|
+
|
18
|
+
name: str
|
19
|
+
type: str
|
20
|
+
|
21
|
+
|
22
|
+
@dataclass(frozen=True)
|
23
|
+
class TypedData:
|
24
|
+
"""
|
25
|
+
Dataclass representing a TypedData object
|
26
|
+
"""
|
27
|
+
|
28
|
+
types: Dict[str, List[Parameter]]
|
29
|
+
primary_type: str
|
30
|
+
domain: StarkNetDomainDict
|
31
|
+
message: dict
|
32
|
+
|
33
|
+
@staticmethod
|
34
|
+
def from_dict(data: TypedDataDict) -> "TypedData":
|
35
|
+
"""
|
36
|
+
Create TypedData dataclass from dictionary.
|
37
|
+
|
38
|
+
:param data: TypedData dictionary.
|
39
|
+
:return: TypedData dataclass instance.
|
40
|
+
"""
|
41
|
+
return cast(TypedData, TypedDataSchema().load(data))
|
42
|
+
|
43
|
+
def _is_struct(self, type_name: str) -> bool:
|
44
|
+
return type_name in self.types
|
45
|
+
|
46
|
+
def _encode_value(self, type_name: str, value: Union[int, str, dict, list]) -> int:
|
47
|
+
if is_pointer(type_name) and isinstance(value, list):
|
48
|
+
type_name = strip_pointer(type_name)
|
49
|
+
|
50
|
+
if self._is_struct(type_name):
|
51
|
+
return compute_hash_on_elements(
|
52
|
+
[self.struct_hash(type_name, data) for data in value]
|
53
|
+
)
|
54
|
+
return compute_hash_on_elements([int(get_hex(val), 16) for val in value])
|
55
|
+
|
56
|
+
if self._is_struct(type_name) and isinstance(value, dict):
|
57
|
+
return self.struct_hash(type_name, value)
|
58
|
+
|
59
|
+
value = cast(Union[int, str], value)
|
60
|
+
return int(get_hex(value), 16)
|
61
|
+
|
62
|
+
def _encode_data(self, type_name: str, data: dict) -> List[int]:
|
63
|
+
values = []
|
64
|
+
for param in self.types[type_name]:
|
65
|
+
encoded_value = self._encode_value(param.type, data[param.name])
|
66
|
+
values.append(encoded_value)
|
67
|
+
|
68
|
+
return values
|
69
|
+
|
70
|
+
def _get_dependencies(self, type_name: str) -> List[str]:
|
71
|
+
if type_name not in self.types:
|
72
|
+
# type_name is a primitive type, has no dependencies
|
73
|
+
return []
|
74
|
+
|
75
|
+
dependencies = set()
|
76
|
+
|
77
|
+
def collect_deps(type_name: str) -> None:
|
78
|
+
for param in self.types[type_name]:
|
79
|
+
fixed_type = strip_pointer(param.type)
|
80
|
+
if fixed_type in self.types and fixed_type not in dependencies:
|
81
|
+
dependencies.add(fixed_type)
|
82
|
+
# recursive call
|
83
|
+
collect_deps(fixed_type)
|
84
|
+
|
85
|
+
# collect dependencies into a set
|
86
|
+
collect_deps(type_name)
|
87
|
+
return [type_name, *list(dependencies)]
|
88
|
+
|
89
|
+
def _encode_type(self, type_name: str) -> str:
|
90
|
+
primary, *dependencies = self._get_dependencies(type_name)
|
91
|
+
types = [primary, *sorted(dependencies)]
|
92
|
+
|
93
|
+
def make_dependency_str(dependency):
|
94
|
+
lst = [f"{t.name}:{t.type}" for t in self.types[dependency]]
|
95
|
+
return f"{dependency}({','.join(lst)})"
|
96
|
+
|
97
|
+
return "".join([make_dependency_str(x) for x in types])
|
98
|
+
|
99
|
+
def type_hash(self, type_name: str) -> int:
|
100
|
+
"""
|
101
|
+
Calculate the hash of a type name.
|
102
|
+
|
103
|
+
:param type_name: Name of the type.
|
104
|
+
:return: Hash of the type name.
|
105
|
+
"""
|
106
|
+
return get_selector_from_name(self._encode_type(type_name))
|
107
|
+
|
108
|
+
def struct_hash(self, type_name: str, data: dict) -> int:
|
109
|
+
"""
|
110
|
+
Calculate the hash of a struct.
|
111
|
+
|
112
|
+
:param type_name: Name of the type.
|
113
|
+
:param data: Data defining the struct.
|
114
|
+
:return: Hash of the struct.
|
115
|
+
"""
|
116
|
+
return compute_hash_on_elements(
|
117
|
+
[self.type_hash(type_name), *self._encode_data(type_name, data)]
|
118
|
+
)
|
119
|
+
|
120
|
+
def message_hash(self, account_address: int) -> int:
|
121
|
+
"""
|
122
|
+
Calculate the hash of the message.
|
123
|
+
|
124
|
+
:param account_address: Address of an account.
|
125
|
+
:return: Hash of the message.
|
126
|
+
"""
|
127
|
+
message = [
|
128
|
+
encode_shortstring("StarkNet Message"),
|
129
|
+
self.struct_hash("StarkNetDomain", cast(dict, self.domain)),
|
130
|
+
account_address,
|
131
|
+
self.struct_hash(self.primary_type, self.message),
|
132
|
+
]
|
133
|
+
|
134
|
+
return compute_hash_on_elements(message)
|
135
|
+
|
136
|
+
|
137
|
+
def get_hex(value: Union[int, str]) -> str:
|
138
|
+
if isinstance(value, int):
|
139
|
+
return hex(value)
|
140
|
+
if value[:2] == "0x":
|
141
|
+
return value
|
142
|
+
if value.isnumeric():
|
143
|
+
return hex(int(value))
|
144
|
+
return hex(encode_shortstring(value))
|
145
|
+
|
146
|
+
|
147
|
+
def is_pointer(value: str) -> bool:
|
148
|
+
return len(value) > 0 and value[-1] == "*"
|
149
|
+
|
150
|
+
|
151
|
+
def strip_pointer(value: str) -> str:
|
152
|
+
if is_pointer(value):
|
153
|
+
return value[:-1]
|
154
|
+
return value
|
155
|
+
|
156
|
+
|
157
|
+
# pylint: disable=unused-argument
|
158
|
+
# pylint: disable=no-self-use
|
159
|
+
|
160
|
+
|
161
|
+
class ParameterSchema(Schema):
|
162
|
+
name = fields.String(data_key="name", required=True)
|
163
|
+
type = fields.String(data_key="type", required=True)
|
164
|
+
|
165
|
+
@post_load
|
166
|
+
def make_dataclass(self, data, **kwargs) -> Parameter:
|
167
|
+
return Parameter(**data)
|
168
|
+
|
169
|
+
|
170
|
+
class TypedDataSchema(Schema):
|
171
|
+
types = fields.Dict(
|
172
|
+
data_key="types",
|
173
|
+
keys=fields.Str(),
|
174
|
+
values=fields.List(fields.Nested(ParameterSchema())),
|
175
|
+
)
|
176
|
+
primary_type = fields.String(data_key="primaryType", required=True)
|
177
|
+
domain = fields.Dict(data_key="domain", required=True)
|
178
|
+
message = fields.Dict(data_key="message", required=True)
|
179
|
+
|
180
|
+
@post_load
|
181
|
+
def make_dataclass(self, data, **kwargs) -> TypedData:
|
182
|
+
return TypedData(**data)
|
File without changes
|
File without changes
|