From 9aeeae1f3bf432dbf72b25b66122e2e15b76a084 Mon Sep 17 00:00:00 2001 From: Igor Urbanik Date: Tue, 9 Aug 2022 15:01:13 +0200 Subject: [PATCH] Initial draft --- protostar/commands/deploy/deploy_command.py | 1 + .../commands/test/cheatcodes/__init__.py | 1 + .../test/cheatcodes/deploy_cheatcode.py | 5 ++ .../test/cheatcodes/network_config.py | 9 ++++ .../cheatcodes/migrator_call_cheatcode.py | 35 +++++++++++++ .../cheatcodes/migrator_declare_cheatcode.py | 23 +++++++++ .../migrator_deploy_contract_cheatcode.py | 16 ++++++ .../cheatcodes/migrator_invoke_cheatcode.py | 37 ++++++++++++++ protostar/migrator/migrator.py | 10 ++++ .../migrator/migrator_cheatcodes_factory.py | 13 +++++ protostar/starknet_gateway/gateway_facade.py | 51 +++++++++++++++++++ website/docs/cli-reference.md | 4 ++ 12 files changed, 205 insertions(+) create mode 100644 protostar/commands/test/cheatcodes/network_config.py create mode 100644 protostar/migrator/cheatcodes/migrator_call_cheatcode.py create mode 100644 protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py diff --git a/protostar/commands/deploy/deploy_command.py b/protostar/commands/deploy/deploy_command.py index e8f3ae6cdc..ba914bd0eb 100644 --- a/protostar/commands/deploy/deploy_command.py +++ b/protostar/commands/deploy/deploy_command.py @@ -86,6 +86,7 @@ def arguments(self) -> List[Command.Argument]: is_array=True, ), Command.Argument( + # Note: This will be removed with the mainnet whitelist name="token", description="Used by whitelisted users for deploying contracts in Alpha MainNet.", type="str", diff --git a/protostar/commands/test/cheatcodes/__init__.py b/protostar/commands/test/cheatcodes/__init__.py index 0a000d6829..811e497703 100644 --- a/protostar/commands/test/cheatcodes/__init__.py +++ b/protostar/commands/test/cheatcodes/__init__.py @@ -6,6 +6,7 @@ from .expect_revert_cheatcode import ExpectRevertCheatcode from .given_cheatcode import GivenCheatcode from .mock_call_cheatcode import MockCallCheatcode +from .network_config import CheatcodeNetworkConfig, get_default_network_config from .prepare_cheatcode import PrepareCheatcode, PreparedContract from .reflect_cheatcode import ReflectCheatcode from .reject_cheatcode import RejectCheatcode diff --git a/protostar/commands/test/cheatcodes/deploy_cheatcode.py b/protostar/commands/test/cheatcodes/deploy_cheatcode.py index e81ce87581..2280ab2f2a 100644 --- a/protostar/commands/test/cheatcodes/deploy_cheatcode.py +++ b/protostar/commands/test/cheatcodes/deploy_cheatcode.py @@ -7,6 +7,11 @@ from protostar.commands.test.cheatcodes.prepare_cheatcode import PreparedContract from protostar.starknet.cheatcode import Cheatcode +from protostar.commands.test.test_environment_exceptions import ( + KeywordOnlyArgumentCheatcodeException, +) + +from protostar.commands.test.cheatcodes.network_config import CheatcodeNetworkConfig from protostar.migrator.cheatcodes.migrator_deploy_contract_cheatcode import ( DeployedContract, diff --git a/protostar/commands/test/cheatcodes/network_config.py b/protostar/commands/test/cheatcodes/network_config.py new file mode 100644 index 0000000000..5d41b89b46 --- /dev/null +++ b/protostar/commands/test/cheatcodes/network_config.py @@ -0,0 +1,9 @@ +from typing_extensions import TypedDict + + +class CheatcodeNetworkConfig(TypedDict): + wait_for_acceptance: bool + + +def get_default_network_config() -> CheatcodeNetworkConfig: + return CheatcodeNetworkConfig(wait_for_acceptance=False) diff --git a/protostar/migrator/cheatcodes/migrator_call_cheatcode.py b/protostar/migrator/cheatcodes/migrator_call_cheatcode.py new file mode 100644 index 0000000000..902f4a98fb --- /dev/null +++ b/protostar/migrator/cheatcodes/migrator_call_cheatcode.py @@ -0,0 +1,35 @@ +import asyncio +from typing import Callable, Dict, Any, Optional + +from starknet_py.net.models import AddressRepresentation + +from protostar.starknet.cheatcode import Cheatcode +from protostar.starknet_gateway import GatewayFacade + + +class MigratorCallCheatcode(Cheatcode): + def __init__( + self, + syscall_dependencies: Cheatcode.SyscallDependencies, + gateway_facade: GatewayFacade, + ): + super().__init__(syscall_dependencies) + self._gateway_facade = gateway_facade + + @property + def name(self) -> str: + return "call" + + def build(self) -> Callable: + return self.call + + def call(self, address: AddressRepresentation, function_name: str, inputs: Optional[Dict[str, Any]] = None): + + output = asyncio.run( + self._gateway_facade.call( + address=address, + function_name=function_name, + inputs=inputs, + ) + ) + diff --git a/protostar/migrator/cheatcodes/migrator_declare_cheatcode.py b/protostar/migrator/cheatcodes/migrator_declare_cheatcode.py index 86def33229..9fec2c14f1 100644 --- a/protostar/migrator/cheatcodes/migrator_declare_cheatcode.py +++ b/protostar/migrator/cheatcodes/migrator_declare_cheatcode.py @@ -8,10 +8,23 @@ CheatcodeException, KeywordOnlyArgumentCheatcodeException, ) +<<<<<<< HEAD +from protostar.commands.test.test_environment_exceptions import ( + CheatcodeException, + KeywordOnlyArgumentCheatcodeException, +) +======= +>>>>>>> master from protostar.starknet.cheatcode import Cheatcode from protostar.starknet_gateway import GatewayFacade from protostar.starknet_gateway.gateway_facade import CompilationOutputNotFoundException +<<<<<<< HEAD +from protostar.commands.test.cheatcodes import ( + CheatcodeNetworkConfig, + get_default_network_config, +) +======= from .network_config import CheatcodeNetworkConfig, ValidatedCheatcodeNetworkConfig @@ -25,6 +38,7 @@ def __call__( self, contract_path_str: str, *args, config: Optional[Any] = None ) -> DeclaredContract: ... +>>>>>>> master class MigratorDeclareCheatcode(Cheatcode): @@ -59,16 +73,25 @@ def _declare( if len(args) > 0: raise KeywordOnlyArgumentCheatcodeException(self.name, ["config"]) +<<<<<<< HEAD + if not config: + config = get_default_network_config() +======= validated_config = ValidatedCheatcodeNetworkConfig.from_dict( config or CheatcodeNetworkConfig() ) +>>>>>>> master try: response = asyncio.run( self._gateway_facade.declare( compiled_contract_path=Path(contract_path_str), token=self._config.token, +<<<<<<< HEAD + wait_for_acceptance=config["wait_for_acceptance"], +======= wait_for_acceptance=validated_config.wait_for_acceptance, +>>>>>>> master ) ) diff --git a/protostar/migrator/cheatcodes/migrator_deploy_contract_cheatcode.py b/protostar/migrator/cheatcodes/migrator_deploy_contract_cheatcode.py index aa34aae54a..50c14d82b2 100644 --- a/protostar/migrator/cheatcodes/migrator_deploy_contract_cheatcode.py +++ b/protostar/migrator/cheatcodes/migrator_deploy_contract_cheatcode.py @@ -12,6 +12,12 @@ KeywordOnlyArgumentCheatcodeException, ) +<<<<<<< HEAD +from protostar.commands.test.cheatcodes import ( + CheatcodeNetworkConfig, + get_default_network_config, +) +======= from .network_config import CheatcodeNetworkConfig, ValidatedCheatcodeNetworkConfig @@ -31,6 +37,7 @@ def __call__( config: Optional[Any] = None, ) -> DeployedContract: ... +>>>>>>> master class MigratorDeployContractCheatcode(Cheatcode): @@ -70,16 +77,25 @@ def _deploy_contract( if isinstance(constructor_args, collections.Mapping): assert False, "Data Transformer is not supported" +<<<<<<< HEAD + if not config: + config = get_default_network_config() +======= validated_config = ValidatedCheatcodeNetworkConfig.from_dict( config or CheatcodeNetworkConfig() ) +>>>>>>> master response = asyncio.run( self._gateway_facade.deploy( compiled_contract_path=Path(contract_path), inputs=constructor_args, token=self._config.token, +<<<<<<< HEAD + wait_for_acceptance=config["wait_for_acceptance"], +======= wait_for_acceptance=validated_config.wait_for_acceptance, +>>>>>>> master ) ) diff --git a/protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py b/protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py new file mode 100644 index 0000000000..c1d3ec00e8 --- /dev/null +++ b/protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py @@ -0,0 +1,37 @@ +import asyncio +from typing import Callable, Dict, Any, Optional + +from starknet_py.net.models import AddressRepresentation + +from protostar.starknet.cheatcode import Cheatcode +from protostar.starknet_gateway import GatewayFacade + + +class MigratorInvokeCheatcode(Cheatcode): + def __init__( + self, + syscall_dependencies: Cheatcode.SyscallDependencies, + gateway_facade: GatewayFacade, + ): + super().__init__(syscall_dependencies) + self._gateway_facade = gateway_facade + + @property + def name(self) -> str: + return "invoke" + + def build(self) -> Callable: + return self.invoke + + # TODO: consider CheatcodeNetworkConfig instead of wait_for_acceptance + async def invoke(self, address: AddressRepresentation, function_name: str, inputs: Optional[Dict[str, Any]] = None, wait_for_acceptance: bool = False): + + asyncio.run( + self._gateway_facade.invoke( + address=address, + function_name=function_name, + inputs=inputs, + wait_for_acceptance=wait_for_acceptance + ) + ) + diff --git a/protostar/migrator/migrator.py b/protostar/migrator/migrator.py index d10b267a45..a77b4489b6 100644 --- a/protostar/migrator/migrator.py +++ b/protostar/migrator/migrator.py @@ -55,6 +55,15 @@ def set_migration_execution_environemnt_config( self._migrator_execution_environment_config = config async def build(self, migration_file_path: Path): +<<<<<<< HEAD + facade = self._gateway_facade_builder.build() + + if self._logger: + assert self._log_color_provider + facade.set_logger(self._logger, self._log_color_provider) + + self._migrator_execution_environment_builder.set_gateway_facade(facade) +======= gateway_facade = self._gateway_facade_builder.build() if self._logger: @@ -64,6 +73,7 @@ async def build(self, migration_file_path: Path): self._migrator_execution_environment_builder.set_gateway_facade( gateway_facade ) +>>>>>>> master migrator_execution_env = ( await self._migrator_execution_environment_builder.build( diff --git a/protostar/migrator/migrator_cheatcodes_factory.py b/protostar/migrator/migrator_cheatcodes_factory.py index 60f54304a5..65cf3ceb9c 100644 --- a/protostar/migrator/migrator_cheatcodes_factory.py +++ b/protostar/migrator/migrator_cheatcodes_factory.py @@ -9,6 +9,9 @@ from protostar.migrator.cheatcodes.migrator_deploy_contract_cheatcode import ( MigratorDeployContractCheatcode, ) +from protostar.migrator.cheatcodes.migrator_call_cheatcode import MigratorCallCheatcode +from protostar.migrator.cheatcodes.migrator_invoke_cheatcode import MigratorInvokeCheatcode + from protostar.starknet.cheatcode import Cheatcode from protostar.starknet.cheatcode_factory import CheatcodeFactory from protostar.starknet_gateway.gateway_facade import GatewayFacade @@ -18,6 +21,10 @@ class MigratorCheatcodeFactory(CheatcodeFactory): @dataclass class Config: +<<<<<<< HEAD + signature: Optional[List[str]] = None +======= +>>>>>>> master token: Optional[str] = None def __init__( @@ -43,6 +50,10 @@ def build( syscall_dependencies, self.gateway_facade, config=MigratorDeclareCheatcode.Config( +<<<<<<< HEAD + signature=self._config.signature, +======= +>>>>>>> master token=self._config.token, ), ), @@ -51,4 +62,6 @@ def build( self.gateway_facade, config=MigratorDeployContractCheatcode.Config(token=self._config.token), ), + MigratorInvokeCheatcode(syscall_dependencies, self.gateway_facade), + MigratorCallCheatcode(syscall_dependencies, self.gateway_facade), ] diff --git a/protostar/starknet_gateway/gateway_facade.py b/protostar/starknet_gateway/gateway_facade.py index 850db0ec32..17349d8485 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -1,6 +1,10 @@ from logging import Logger from pathlib import Path +<<<<<<< HEAD +from typing import Callable, List, Optional, Dict, Any +======= from typing import Callable, List, Optional +>>>>>>> master import dataclasses from starkware.starknet.services.api.gateway.transaction import DECLARE_SENDER_ADDRESS @@ -9,7 +13,12 @@ from starknet_py.net.gateway_client import GatewayClient from starknet_py.transactions.deploy import make_deploy_tx from starknet_py.transactions.declare import make_declare_tx +<<<<<<< HEAD +from starknet_py.net.models import StarknetChainId, AddressRepresentation +from starknet_py.contract import Contract +======= from starknet_py.net.models import StarknetChainId +>>>>>>> master from protostar.protostar_exception import ProtostarException from protostar.starknet_gateway.gateway_response import ( @@ -49,6 +58,11 @@ def build(self) -> "GatewayFacade": # Starknet.py ignores chain parameter when # `mainnet` or `testnet` is passed into the client # `StarknetChainId.TESTNET` also works for devnet +<<<<<<< HEAD + # chain parameter is going to be removed soon + # so we won't have to rely on this behaviour +======= +>>>>>>> master GatewayFacade.map_to_starknet_py_naming(self._network), chain=StarknetChainId.TESTNET, ) @@ -182,6 +196,33 @@ async def declare( class_hash=result.class_hash, transaction_hash=result.transaction_hash, ) +<<<<<<< HEAD + + async def call(self, address: AddressRepresentation, function_name: str, inputs: Dict[str, Any]): + # TODO: + # Add registering request + # Consider returning something other than a NamedTuple + # Consider catching exceptions + # Check whether the awaits make sense + + contract = await Contract.from_address( + address=address, client=self._gateway_client + ) + call_output = await contract.functions[function_name].call(**inputs) + print("CALL OUTPUT: ", call_output) + + async def invoke(self, address: AddressRepresentation, function_name: str, inputs: Dict[str, Any], wait_for_acceptance: bool = False): + contract = await Contract.from_address( + address=address, client=self._gateway_client + ) + result = await contract.functions[function_name].invoke(**inputs) + + if wait_for_acceptance: + result = await result.wait_for_acceptance() + + print("INVOKE: ", result) +======= +>>>>>>> master def _register_request( self, action: StarknetRequest.Action, payload: StarknetRequest.Payload @@ -227,16 +268,26 @@ def register_response(response: StarknetRequest.Payload): return register_response +<<<<<<< HEAD + @classmethod + def map_to_starknet_py_naming(cls, name: str) -> str: +======= @staticmethod def map_to_starknet_py_naming(name: str) -> str: +>>>>>>> master if name == "alpha-goerli": return "testnet" if name == "alpha-mainnet": return "mainnet" return name +<<<<<<< HEAD + @classmethod + def map_from_starknet_py_naming(cls, name: str) -> str: +======= @staticmethod def map_from_starknet_py_naming(name: str) -> str: +>>>>>>> master if name == "testnet": return "alpha-goerli" if name == "mainnet": diff --git a/website/docs/cli-reference.md b/website/docs/cli-reference.md index d1b85853fc..b89c409b9d 100644 --- a/website/docs/cli-reference.md +++ b/website/docs/cli-reference.md @@ -76,7 +76,11 @@ Supported StarkNet networks: #### `--salt INT` An optional salt controlling where the contract will be deployed. The contract deployment address is determined by the hash of contract, salt and caller. If the salt is not supplied, the contract will be deployed with a random salt. #### `--token STRING` +<<<<<<< HEAD +Used for deploying contracts in Alpha MainNet. +======= Used by whitelisted users for deploying contracts in Alpha MainNet. +>>>>>>> master #### `--wait-for-acceptance` Waits for transaction to be accepted on chain. ### `init`