Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace data transfomer in some modules #642

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions starknet_py/contract.py
Expand Up @@ -68,7 +68,7 @@ def parsed_abi(self) -> Abi:
return AbiParser(self.abi).parse()

@staticmethod
def from_abi(address: int, abi: ABI) -> "ContractData":
def from_abi(address: int, abi: ABI) -> ContractData:
Copy link
Contributor Author

@Solpatium Solpatium Jan 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use __future__.annotations in this file, so we can use types normally.

return ContractData(
address=address,
abi=abi,
Expand Down Expand Up @@ -221,7 +221,7 @@ class DeployResult(SentTransaction):
"""

# We ensure this is not None in __post_init__
deployed_contract: "Contract" = None # pyright: ignore
deployed_contract: Contract = None # pyright: ignore
"""A Contract instance representing the deployed contract."""

def __post_init__(self):
Expand Down Expand Up @@ -495,7 +495,7 @@ async def from_address(
proxy_config: Union[bool, ProxyConfig] = False,
*,
client: Optional[Client] = None,
) -> "Contract":
) -> Contract:
"""
Fetches ABI for given contract and creates a new Contract instance with it. If you know ABI statically you
should create Contract's instances directly instead of using this function to avoid unnecessary API calls.
Expand Down
47 changes: 38 additions & 9 deletions starknet_py/net/account/account.py
@@ -1,9 +1,22 @@
import dataclasses
import re
from collections import OrderedDict
from typing import Dict, Iterable, List, Optional, Tuple, TypeVar, Union

from starkware.starknet.public.abi import get_selector_from_name

from starknet_py.cairo.serialization.data_serializers.array_serializer import (
ArraySerializer,
)
from starknet_py.cairo.serialization.data_serializers.felt_serializer import (
FeltSerializer,
)
from starknet_py.cairo.serialization.data_serializers.payload_serializer import (
PayloadSerializer,
)
from starknet_py.cairo.serialization.data_serializers.struct_serializer import (
StructSerializer,
)
from starknet_py.common import create_compiled_contract
from starknet_py.net import KeyPair
from starknet_py.net.account.account_deployment_result import AccountDeploymentResult
Expand Down Expand Up @@ -37,9 +50,6 @@
)
from starknet_py.net.signer import BaseSigner
from starknet_py.net.signer.stark_curve_signer import StarkCurveSigner
from starknet_py.utils.data_transformer.execute_transformer import (
execute_transformer_v1,
)
from starknet_py.utils.iterable import ensure_iterable
from starknet_py.utils.typed_data import TypedData as TypedDataDataclass

Expand Down Expand Up @@ -129,8 +139,10 @@ async def _prepare_invoke_function(
"""
nonce = await self.get_nonce()

calldata_py = _merge_calls(ensure_iterable(calls))
wrapped_calldata, _ = execute_transformer_v1.from_python(*calldata_py)
call_descriptions, calldata = _merge_calls(ensure_iterable(calls))
wrapped_calldata = _execute_payload_serializer.serialize(
{"call_array": call_descriptions, "calldata": calldata}
)

transaction = Invoke(
calldata=wrapped_calldata,
Expand Down Expand Up @@ -409,11 +421,28 @@ def _parse_call(call: Call, entire_calldata: List) -> Tuple[Dict, List]:
return _data, entire_calldata


def _merge_calls(calls: Iterable[Call]) -> List:
calldata = []
def _merge_calls(calls: Iterable[Call]) -> Tuple[List[Dict], List[int]]:
call_descriptions = []
entire_calldata = []
for call in calls:
data, entire_calldata = _parse_call(call, entire_calldata)
calldata.append(data)
call_descriptions.append(data)

return call_descriptions, entire_calldata


return [calldata, entire_calldata]
_felt_serializer = FeltSerializer()
_call_description = StructSerializer(
OrderedDict(
to=_felt_serializer,
selector=_felt_serializer,
data_offset=_felt_serializer,
data_len=_felt_serializer,
)
)
_execute_payload_serializer = PayloadSerializer(
OrderedDict(
call_array=ArraySerializer(_call_description),
calldata=ArraySerializer(_felt_serializer),
)
)
3 changes: 1 addition & 2 deletions starknet_py/net/models/abi/model.py
@@ -1,8 +1,7 @@
from __future__ import annotations

from collections import OrderedDict
from dataclasses import dataclass
from typing import Dict, Optional
from typing import Dict, Optional, OrderedDict
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need OrderedDict type here (not class) :|


from starknet_py.cairo.data_types import CairoType, StructType

Expand Down
43 changes: 37 additions & 6 deletions starknet_py/net/udc_deployer/deployer.py
Expand Up @@ -5,16 +5,14 @@
from starkware.starknet.definitions.fields import ContractAddressSalt
from starkware.starknet.public.abi import get_selector_from_name

from starknet_py.cairo.serialization.factory import serializer_for_function
from starknet_py.common import int_from_hex
from starknet_py.constants import DEFAULT_DEPLOYER_ADDRESS
from starknet_py.net.client_models import Call, Hash
from starknet_py.net.models import AddressRepresentation, compute_address, parse_address
from starknet_py.net.models.abi.parser import AbiParser
from starknet_py.utils.contructor_args_translator import translate_constructor_args
from starknet_py.utils.crypto.facade import pedersen_hash
from starknet_py.utils.data_transformer.universal_deployer_serializer import (
deploy_contract_abi,
universal_deployer_serializer,
)
from starknet_py.utils.sync import add_sync_methods

ContractDeployment = NamedTuple("ContractDeployment", [("udc", Call), ("address", int)])
Expand Down Expand Up @@ -90,8 +88,7 @@ def create_deployment_call_raw(
salt = cast(int, salt or ContractAddressSalt.get_random_value())
class_hash = int_from_hex(class_hash)

calldata, _ = universal_deployer_serializer.from_python(
value_types=deploy_contract_abi["inputs"],
calldata = deployer_serializer.serialize(
classHash=class_hash,
salt=salt,
unique=int(self._unique),
Expand Down Expand Up @@ -123,3 +120,37 @@ def _compute_address(
salt=salt,
deployer_address=deployer_address,
)


deployer_abi = AbiParser(
[
{
"data": [
{"name": "address", "type": "felt"},
{"name": "deployer", "type": "felt"},
{"name": "unique", "type": "felt"},
{"name": "classHash", "type": "felt"},
{"name": "calldata_len", "type": "felt"},
{"name": "calldata", "type": "felt*"},
{"name": "salt", "type": "felt"},
],
"keys": [],
"name": "ContractDeployed",
"type": "event",
},
{
"inputs": [
{"name": "classHash", "type": "felt"},
{"name": "salt", "type": "felt"},
{"name": "unique", "type": "felt"},
{"name": "calldata_len", "type": "felt"},
{"name": "calldata", "type": "felt*"},
],
"name": "deployContract",
"outputs": [{"name": "address", "type": "felt"}],
"type": "function",
},
]
).parse()

deployer_serializer = serializer_for_function(deployer_abi.functions["deployContract"])
7 changes: 3 additions & 4 deletions starknet_py/tests/e2e/fixtures/environment_check.py
@@ -1,9 +1,8 @@
import pytest

from starknet_py.constants import DEFAULT_DEPLOYER_ADDRESS
from starknet_py.utils.data_transformer.universal_deployer_serializer import (
universal_deployer_abi,
)
from starknet_py.net.models.abi.parser import AbiParser
from starknet_py.net.udc_deployer.deployer import deployer_abi


@pytest.fixture(scope="module", autouse=True)
Expand All @@ -20,4 +19,4 @@ async def check_if_udc_is_deployed(client):
async def check_if_udc_has_expected_abi(gateway_client):
code = await gateway_client.get_code(contract_address=DEFAULT_DEPLOYER_ADDRESS)

assert code.abi == universal_deployer_abi
assert AbiParser(code.abi).parse() == deployer_abi
17 changes: 5 additions & 12 deletions starknet_py/utils/contructor_args_translator.py
@@ -1,20 +1,16 @@
from typing import List, Optional, Union

from starkware.starknet.public.abi_structs import identifier_manager_from_abi

from starknet_py.utils.data_transformer import FunctionCallSerializer
from starknet_py.cairo.serialization.factory import serializer_for_function
from starknet_py.net.models.abi.parser import AbiParser


def translate_constructor_args(
abi: List, constructor_args: Optional[Union[List, dict]]
) -> List[int]:
constructor_abi = next(
(member for member in abi if member["type"] == "constructor"),
None,
)
parsed = AbiParser(abi).parse()
Comment on lines -11 to +10
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️


# Constructor might not accept any arguments
if not constructor_abi or not constructor_abi["inputs"]:
if not parsed.constructor or not parsed.constructor.inputs:
return []

if not constructor_args:
Expand All @@ -27,7 +23,4 @@ def translate_constructor_args(
if isinstance(constructor_args, dict)
else (constructor_args, {})
)
calldata, _args = FunctionCallSerializer(
constructor_abi, identifier_manager_from_abi(abi)
).from_python(*args, **kwargs)
return calldata
return serializer_for_function(parsed.constructor).serialize(*args, **kwargs)