From 9aeeae1f3bf432dbf72b25b66122e2e15b76a084 Mon Sep 17 00:00:00 2001 From: Igor Urbanik Date: Tue, 9 Aug 2022 15:01:13 +0200 Subject: [PATCH 01/49] 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` From 3616fb0cbf244a845e4f12d28394bdb65174e2e4 Mon Sep 17 00:00:00 2001 From: Igor Urbanik Date: Tue, 9 Aug 2022 15:07:29 +0200 Subject: [PATCH 02/49] Removed artifacts --- .../cheatcodes/migrator_declare_cheatcode.py | 23 ---------------- .../migrator_deploy_contract_cheatcode.py | 16 ------------ protostar/migrator/migrator.py | 10 ------- .../migrator/migrator_cheatcodes_factory.py | 8 ------ protostar/starknet_gateway/gateway_facade.py | 26 ------------------- website/docs/cli-reference.md | 4 --- 6 files changed, 87 deletions(-) diff --git a/protostar/migrator/cheatcodes/migrator_declare_cheatcode.py b/protostar/migrator/cheatcodes/migrator_declare_cheatcode.py index 9fec2c14f1..86def33229 100644 --- a/protostar/migrator/cheatcodes/migrator_declare_cheatcode.py +++ b/protostar/migrator/cheatcodes/migrator_declare_cheatcode.py @@ -8,23 +8,10 @@ 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 @@ -38,7 +25,6 @@ def __call__( self, contract_path_str: str, *args, config: Optional[Any] = None ) -> DeclaredContract: ... ->>>>>>> master class MigratorDeclareCheatcode(Cheatcode): @@ -73,25 +59,16 @@ 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 50c14d82b2..aa34aae54a 100644 --- a/protostar/migrator/cheatcodes/migrator_deploy_contract_cheatcode.py +++ b/protostar/migrator/cheatcodes/migrator_deploy_contract_cheatcode.py @@ -12,12 +12,6 @@ KeywordOnlyArgumentCheatcodeException, ) -<<<<<<< HEAD -from protostar.commands.test.cheatcodes import ( - CheatcodeNetworkConfig, - get_default_network_config, -) -======= from .network_config import CheatcodeNetworkConfig, ValidatedCheatcodeNetworkConfig @@ -37,7 +31,6 @@ def __call__( config: Optional[Any] = None, ) -> DeployedContract: ... ->>>>>>> master class MigratorDeployContractCheatcode(Cheatcode): @@ -77,25 +70,16 @@ 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/migrator.py b/protostar/migrator/migrator.py index a77b4489b6..d10b267a45 100644 --- a/protostar/migrator/migrator.py +++ b/protostar/migrator/migrator.py @@ -55,15 +55,6 @@ 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: @@ -73,7 +64,6 @@ 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 65cf3ceb9c..1712e9b635 100644 --- a/protostar/migrator/migrator_cheatcodes_factory.py +++ b/protostar/migrator/migrator_cheatcodes_factory.py @@ -21,10 +21,6 @@ class MigratorCheatcodeFactory(CheatcodeFactory): @dataclass class Config: -<<<<<<< HEAD - signature: Optional[List[str]] = None -======= ->>>>>>> master token: Optional[str] = None def __init__( @@ -50,10 +46,6 @@ def build( syscall_dependencies, self.gateway_facade, config=MigratorDeclareCheatcode.Config( -<<<<<<< HEAD - signature=self._config.signature, -======= ->>>>>>> master token=self._config.token, ), ), diff --git a/protostar/starknet_gateway/gateway_facade.py b/protostar/starknet_gateway/gateway_facade.py index 17349d8485..76c6fdef8f 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -1,10 +1,6 @@ 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 @@ -13,12 +9,8 @@ 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 ( @@ -58,11 +50,6 @@ 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, ) @@ -196,7 +183,6 @@ 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: @@ -221,8 +207,6 @@ async def invoke(self, address: AddressRepresentation, function_name: str, input result = await result.wait_for_acceptance() print("INVOKE: ", result) -======= ->>>>>>> master def _register_request( self, action: StarknetRequest.Action, payload: StarknetRequest.Payload @@ -268,26 +252,16 @@ 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 b89c409b9d..d1b85853fc 100644 --- a/website/docs/cli-reference.md +++ b/website/docs/cli-reference.md @@ -76,11 +76,7 @@ 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` From 6ac63e427efddd464e7b7cf3de305c75b1052fab Mon Sep 17 00:00:00 2001 From: Igor Urbanik Date: Tue, 9 Aug 2022 15:10:27 +0200 Subject: [PATCH 03/49] Cleanup --- protostar/commands/deploy/deploy_command.py | 1 - protostar/commands/test/cheatcodes/__init__.py | 1 - .../commands/test/cheatcodes/deploy_cheatcode.py | 5 ----- .../commands/test/cheatcodes/network_config.py | 9 --------- .../migrator/cheatcodes/migrator_call_cheatcode.py | 8 ++++++-- .../cheatcodes/migrator_invoke_cheatcode.py | 11 ++++++++--- protostar/migrator/migrator_cheatcodes_factory.py | 4 +++- protostar/starknet_gateway/gateway_facade.py | 14 +++++++++++--- 8 files changed, 28 insertions(+), 25 deletions(-) delete mode 100644 protostar/commands/test/cheatcodes/network_config.py diff --git a/protostar/commands/deploy/deploy_command.py b/protostar/commands/deploy/deploy_command.py index ba914bd0eb..e8f3ae6cdc 100644 --- a/protostar/commands/deploy/deploy_command.py +++ b/protostar/commands/deploy/deploy_command.py @@ -86,7 +86,6 @@ 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 811e497703..0a000d6829 100644 --- a/protostar/commands/test/cheatcodes/__init__.py +++ b/protostar/commands/test/cheatcodes/__init__.py @@ -6,7 +6,6 @@ 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 2280ab2f2a..e81ce87581 100644 --- a/protostar/commands/test/cheatcodes/deploy_cheatcode.py +++ b/protostar/commands/test/cheatcodes/deploy_cheatcode.py @@ -7,11 +7,6 @@ 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 deleted file mode 100644 index 5d41b89b46..0000000000 --- a/protostar/commands/test/cheatcodes/network_config.py +++ /dev/null @@ -1,9 +0,0 @@ -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 index 902f4a98fb..d32df54026 100644 --- a/protostar/migrator/cheatcodes/migrator_call_cheatcode.py +++ b/protostar/migrator/cheatcodes/migrator_call_cheatcode.py @@ -23,7 +23,12 @@ def name(self) -> str: def build(self) -> Callable: return self.call - def call(self, address: AddressRepresentation, function_name: str, inputs: Optional[Dict[str, Any]] = None): + def call( + self, + address: AddressRepresentation, + function_name: str, + inputs: Optional[Dict[str, Any]] = None, + ): output = asyncio.run( self._gateway_facade.call( @@ -32,4 +37,3 @@ def call(self, address: AddressRepresentation, function_name: str, inputs: Optio inputs=inputs, ) ) - diff --git a/protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py b/protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py index c1d3ec00e8..a4456f3ff0 100644 --- a/protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py +++ b/protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py @@ -24,14 +24,19 @@ 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): + 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 + wait_for_acceptance=wait_for_acceptance, ) ) - diff --git a/protostar/migrator/migrator_cheatcodes_factory.py b/protostar/migrator/migrator_cheatcodes_factory.py index 1712e9b635..ccf1d9d3d4 100644 --- a/protostar/migrator/migrator_cheatcodes_factory.py +++ b/protostar/migrator/migrator_cheatcodes_factory.py @@ -10,7 +10,9 @@ MigratorDeployContractCheatcode, ) from protostar.migrator.cheatcodes.migrator_call_cheatcode import MigratorCallCheatcode -from protostar.migrator.cheatcodes.migrator_invoke_cheatcode import MigratorInvokeCheatcode +from protostar.migrator.cheatcodes.migrator_invoke_cheatcode import ( + MigratorInvokeCheatcode, +) from protostar.starknet.cheatcode import Cheatcode from protostar.starknet.cheatcode_factory import CheatcodeFactory diff --git a/protostar/starknet_gateway/gateway_facade.py b/protostar/starknet_gateway/gateway_facade.py index 76c6fdef8f..60cdb56142 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -184,7 +184,9 @@ async def declare( transaction_hash=result.transaction_hash, ) - async def call(self, address: AddressRepresentation, function_name: str, inputs: Dict[str, Any]): + async def call( + self, address: AddressRepresentation, function_name: str, inputs: Dict[str, Any] + ): # TODO: # Add registering request # Consider returning something other than a NamedTuple @@ -197,7 +199,13 @@ async def call(self, address: AddressRepresentation, function_name: str, inputs: 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): + 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 ) @@ -205,7 +213,7 @@ async def invoke(self, address: AddressRepresentation, function_name: str, input if wait_for_acceptance: result = await result.wait_for_acceptance() - + print("INVOKE: ", result) def _register_request( From 1237a753a5c62b4b7635f1817cdbbfbed2481afe Mon Sep 17 00:00:00 2001 From: Igor Urbanik Date: Tue, 9 Aug 2022 16:05:15 +0200 Subject: [PATCH 04/49] Added protocols --- .../cheatcodes/migrator_call_cheatcode.py | 17 +++++++-- .../cheatcodes/migrator_invoke_cheatcode.py | 35 ++++++++++++++++--- protostar/starknet_gateway/gateway_facade.py | 2 ++ 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/protostar/migrator/cheatcodes/migrator_call_cheatcode.py b/protostar/migrator/cheatcodes/migrator_call_cheatcode.py index d32df54026..8599c69685 100644 --- a/protostar/migrator/cheatcodes/migrator_call_cheatcode.py +++ b/protostar/migrator/cheatcodes/migrator_call_cheatcode.py @@ -1,5 +1,6 @@ import asyncio -from typing import Callable, Dict, Any, Optional +from typing import Dict, Any, Optional +from typing_extensions import Protocol from starknet_py.net.models import AddressRepresentation @@ -7,6 +8,16 @@ from protostar.starknet_gateway import GatewayFacade +class CallCheatcodeProtocol(Protocol): + def __call__( + self, + address: AddressRepresentation, + function_name: str, + inputs: Optional[Dict[str, Any]] = None, + ) -> Any: + ... + + class MigratorCallCheatcode(Cheatcode): def __init__( self, @@ -20,7 +31,7 @@ def __init__( def name(self) -> str: return "call" - def build(self) -> Callable: + def build(self) -> CallCheatcodeProtocol: return self.call def call( @@ -37,3 +48,5 @@ def call( inputs=inputs, ) ) + + return output diff --git a/protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py b/protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py index a4456f3ff0..2054ebea65 100644 --- a/protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py +++ b/protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py @@ -1,10 +1,29 @@ import asyncio -from typing import Callable, Dict, Any, Optional +from typing import Dict, Any, Optional +from typing_extensions import Protocol from starknet_py.net.models import AddressRepresentation from protostar.starknet.cheatcode import Cheatcode from protostar.starknet_gateway import GatewayFacade +from protostar.commands.test.test_environment_exceptions import ( + KeywordOnlyArgumentCheatcodeException, +) + +from .network_config import CheatcodeNetworkConfig, ValidatedCheatcodeNetworkConfig + + +class InvokeCheatcodeProtocol(Protocol): + # pylint: disable=keyword-arg-before-vararg + def __call__( + self, + address: AddressRepresentation, + function_name: str, + inputs: Optional[Dict[str, Any]] = None, + *args, + config: Optional[Any] = None, + ) -> Any: + ... class MigratorInvokeCheatcode(Cheatcode): @@ -20,23 +39,29 @@ def __init__( def name(self) -> str: return "invoke" - def build(self) -> Callable: + def build(self) -> InvokeCheatcodeProtocol: return self.invoke - # TODO: consider CheatcodeNetworkConfig instead of wait_for_acceptance + # pylint: disable=keyword-arg-before-vararg async def invoke( self, address: AddressRepresentation, function_name: str, inputs: Optional[Dict[str, Any]] = None, - wait_for_acceptance: bool = False, + *args, + config: Optional[CheatcodeNetworkConfig] = None, ): + if len(args) > 0: + raise KeywordOnlyArgumentCheatcodeException(self.name, ["config"]) + validated_config = ValidatedCheatcodeNetworkConfig.from_dict( + config or CheatcodeNetworkConfig() + ) asyncio.run( self._gateway_facade.invoke( address=address, function_name=function_name, inputs=inputs, - wait_for_acceptance=wait_for_acceptance, + wait_for_acceptance=validated_config.wait_for_acceptance, ) ) diff --git a/protostar/starknet_gateway/gateway_facade.py b/protostar/starknet_gateway/gateway_facade.py index 60cdb56142..37c218423d 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -192,6 +192,8 @@ async def call( # Consider returning something other than a NamedTuple # Consider catching exceptions # Check whether the awaits make sense + # Consider caching contracts + # Add None checking to inputs contract = await Contract.from_address( address=address, client=self._gateway_client From 8de3f4fb353f53ff80ab48d3b14725a09b27ce0e Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 10 Aug 2022 12:48:48 +0200 Subject: [PATCH 05/49] add compiled_project fixture --- .../integration/_conftest/project_fixture.py | 53 +++++++++++++++++++ tests/integration/conftest.py | 43 +++++++++++++++ .../gateway/gateway_facade_test.py | 21 ++++++++ 3 files changed, 117 insertions(+) create mode 100644 tests/integration/_conftest/project_fixture.py create mode 100644 tests/integration/gateway/gateway_facade_test.py diff --git a/tests/integration/_conftest/project_fixture.py b/tests/integration/_conftest/project_fixture.py new file mode 100644 index 0000000000..04a5c020d6 --- /dev/null +++ b/tests/integration/_conftest/project_fixture.py @@ -0,0 +1,53 @@ +from pathlib import Path +from unittest.mock import MagicMock + +import pytest + +from protostar.commands.init.project_creator import ProjectCreator +from protostar.protostar_toml.io.protostar_toml_writer import ProtostarTOMLWriter +from protostar.utils.protostar_directory import VersionManager + + +class SimpleProjectCreator(ProjectCreator): + def __init__( + self, + project_root_path: Path, + script_root: Path, + protostar_toml_writer: ProtostarTOMLWriter, + version_manager: VersionManager, + ): + super().__init__( + script_root, + protostar_toml_writer, + version_manager, + ) + self._project_root_path = project_root_path + + def run(self): + self.copy_template("default", self._project_root_path) + self.save_protostar_toml(self._project_root_path, Path("./lib")) + + +@pytest.fixture(name="project_root_path") +def project_root_path_fixture(tmp_path: Path) -> Path: + return tmp_path + + +@pytest.fixture(name="version_manager") +def version_manager_fixture(mocker: MagicMock) -> VersionManager: + version_manager = mocker.MagicMock() + version_manager.protostar_version = mocker.MagicMock() + version_manager.protostar_version = "99.9.9" + return version_manager + + +@pytest.fixture(name="project") +def project_fixture(project_root_path: Path, version_manager: VersionManager): + protostar_toml_writer = ProtostarTOMLWriter() + project_creator = SimpleProjectCreator( + project_root_path=project_root_path, + protostar_toml_writer=protostar_toml_writer, + script_root=Path(__file__).parent / ".." / ".." / "..", + version_manager=version_manager, + ) + project_creator.run() diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 0852f9db42..0f510f8a41 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -9,8 +9,19 @@ from protostar.commands.test.test_command import TestCommand from protostar.commands.test.testing_summary import TestingSummary +from protostar.compiler.project_cairo_path_builder import ProjectCairoPathBuilder +from protostar.compiler.project_compiler import ProjectCompiler, ProjectCompilerConfig +from protostar.protostar_toml.io.protostar_toml_reader import ProtostarTOMLReader +from protostar.protostar_toml.protostar_contracts_section import ( + ProtostarContractsSection, +) +from protostar.protostar_toml.protostar_project_section import ProtostarProjectSection from tests.conftest import run_devnet +pytest_plugins = [ + "tests.integration._conftest.project_fixture", +] + @dataclass class CairoTestCases: @@ -102,3 +113,35 @@ async def run_cairo_test_runner( ).test(targets=[str(path)], seed=seed, fuzz_max_examples=fuzz_max_examples) return run_cairo_test_runner + + +@pytest.fixture(name="project_compilation_output_path") +def project_compilation_output_path_fixture(project_root_path: Path): + return project_root_path / "build" + + +@pytest.fixture(name="compiled_project") +def compiled_project_fixture( + project_root_path: Path, project_compilation_output_path: Path +): + protostar_toml_reader = ProtostarTOMLReader(protostar_toml_path=project_root_path) + project_compiler = ProjectCompiler( + project_root_path=project_root_path, + contracts_section_loader=ProtostarContractsSection.Loader( + protostar_toml_reader=protostar_toml_reader + ), + project_cairo_path_builder=ProjectCairoPathBuilder( + project_root_path, + project_section_loader=ProtostarProjectSection.Loader( + protostar_toml_reader + ), + ), + ) + project_compiler.compile_project( + output_dir=project_compilation_output_path, + config=ProjectCompilerConfig( + debugging_info_attached=True, + hint_validation_disabled=True, + relative_cairo_path=[], + ), + ) diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py new file mode 100644 index 0000000000..2cb8613ea6 --- /dev/null +++ b/tests/integration/gateway/gateway_facade_test.py @@ -0,0 +1,21 @@ +from pathlib import Path + +import pytest + +from protostar.starknet_gateway.gateway_facade import GatewayFacade +from protostar.utils.log_color_provider import LogColorProvider + + +async def test_deploy(gateway_facade: GatewayFacade, compiled_contract_path: Path): + response = await gateway_facade.deploy(compiled_contract_path) + + assert response is not None + + +@pytest.fixture(name="gateway_facade") +def gateway_facade_fixture(devnet_gateway_url: str): + log_color_provider = LogColorProvider() + log_color_provider.is_ci_mode = False + gateway_facade_builder = GatewayFacade.Builder(project_root_path=Path()) + gateway_facade_builder.set_network(devnet_gateway_url) + return gateway_facade_builder.build() From 1861fd04689f934e5a05e978704e0f6896ec9ea1 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 10 Aug 2022 13:23:35 +0200 Subject: [PATCH 06/49] fix project testing environemnet --- protostar/protostar_toml/io/protostar_toml_reader.py | 2 +- tests/integration/_conftest/project_fixture.py | 6 +++++- tests/integration/conftest.py | 11 +++++++++-- tests/integration/gateway/gateway_facade_test.py | 6 ++++++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/protostar/protostar_toml/io/protostar_toml_reader.py b/protostar/protostar_toml/io/protostar_toml_reader.py index e325af46eb..1117f5066a 100644 --- a/protostar/protostar_toml/io/protostar_toml_reader.py +++ b/protostar/protostar_toml/io/protostar_toml_reader.py @@ -73,7 +73,7 @@ def _read_if_cache_miss(self) -> Dict[str, Any]: if not self.path.is_file(): raise NoProtostarProjectFoundException( - "No protostar.toml found in the working directory" + "No protostar.toml found in the working directory\n" f"{str(self.path)}" ) with open(self.path, "rb") as protostar_toml_file: diff --git a/tests/integration/_conftest/project_fixture.py b/tests/integration/_conftest/project_fixture.py index 04a5c020d6..d8dbdb45a6 100644 --- a/tests/integration/_conftest/project_fixture.py +++ b/tests/integration/_conftest/project_fixture.py @@ -26,11 +26,15 @@ def __init__( def run(self): self.copy_template("default", self._project_root_path) self.save_protostar_toml(self._project_root_path, Path("./lib")) + self._create_libs_dir() + + def _create_libs_dir(self) -> None: + (self._project_root_path / "lib").mkdir(exist_ok=True, parents=True) @pytest.fixture(name="project_root_path") def project_root_path_fixture(tmp_path: Path) -> Path: - return tmp_path + return tmp_path / "default_project" @pytest.fixture(name="version_manager") diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 0f510f8a41..28c9b62452 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -1,5 +1,6 @@ # pylint: disable=invalid-name from dataclasses import dataclass +from os import listdir from pathlib import Path from typing import List, Optional, Set, Union @@ -117,14 +118,18 @@ async def run_cairo_test_runner( @pytest.fixture(name="project_compilation_output_path") def project_compilation_output_path_fixture(project_root_path: Path): - return project_root_path / "build" + output_path = project_root_path / "build" + output_path.mkdir(exist_ok=True) + return output_path @pytest.fixture(name="compiled_project") def compiled_project_fixture( project_root_path: Path, project_compilation_output_path: Path ): - protostar_toml_reader = ProtostarTOMLReader(protostar_toml_path=project_root_path) + protostar_toml_reader = ProtostarTOMLReader( + protostar_toml_path=project_root_path / "protostar.toml" + ) project_compiler = ProjectCompiler( project_root_path=project_root_path, contracts_section_loader=ProtostarContractsSection.Loader( @@ -145,3 +150,5 @@ def compiled_project_fixture( relative_cairo_path=[], ), ) + output_files_count = len(listdir(project_compilation_output_path)) + assert output_files_count > 0, "Project didn't compile" diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py index 2cb8613ea6..96a7dcaabf 100644 --- a/tests/integration/gateway/gateway_facade_test.py +++ b/tests/integration/gateway/gateway_facade_test.py @@ -6,6 +6,7 @@ from protostar.utils.log_color_provider import LogColorProvider +@pytest.mark.usefixtures("project", "compiled_project") async def test_deploy(gateway_facade: GatewayFacade, compiled_contract_path: Path): response = await gateway_facade.deploy(compiled_contract_path) @@ -19,3 +20,8 @@ def gateway_facade_fixture(devnet_gateway_url: str): gateway_facade_builder = GatewayFacade.Builder(project_root_path=Path()) gateway_facade_builder.set_network(devnet_gateway_url) return gateway_facade_builder.build() + + +@pytest.fixture(name="compiled_contract_path") +def compiled_contract_path_fixture(project_compilation_output_path: Path) -> Path: + return project_compilation_output_path / "main.json" From 8b7a574cacaa386497ae348ccaf7c9e9ca26e207 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 10 Aug 2022 13:31:03 +0200 Subject: [PATCH 07/49] rename fixtures --- .../{project_fixture.py => standard_project_fixture.py} | 4 ++-- tests/integration/gateway/gateway_facade_test.py | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) rename tests/integration/_conftest/{project_fixture.py => standard_project_fixture.py} (93%) diff --git a/tests/integration/_conftest/project_fixture.py b/tests/integration/_conftest/standard_project_fixture.py similarity index 93% rename from tests/integration/_conftest/project_fixture.py rename to tests/integration/_conftest/standard_project_fixture.py index d8dbdb45a6..85b644fafc 100644 --- a/tests/integration/_conftest/project_fixture.py +++ b/tests/integration/_conftest/standard_project_fixture.py @@ -45,8 +45,8 @@ def version_manager_fixture(mocker: MagicMock) -> VersionManager: return version_manager -@pytest.fixture(name="project") -def project_fixture(project_root_path: Path, version_manager: VersionManager): +@pytest.fixture(name="standard_project") +def standard_project_fixture(project_root_path: Path, version_manager: VersionManager): protostar_toml_writer = ProtostarTOMLWriter() project_creator = SimpleProjectCreator( project_root_path=project_root_path, diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py index 96a7dcaabf..c7e49c65a6 100644 --- a/tests/integration/gateway/gateway_facade_test.py +++ b/tests/integration/gateway/gateway_facade_test.py @@ -6,10 +6,9 @@ from protostar.utils.log_color_provider import LogColorProvider -@pytest.mark.usefixtures("project", "compiled_project") +@pytest.mark.usefixtures("standard_project", "compiled_project") async def test_deploy(gateway_facade: GatewayFacade, compiled_contract_path: Path): response = await gateway_facade.deploy(compiled_contract_path) - assert response is not None From fd999c2865b1beb99d04059e8316d2f1fe43aea3 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 10 Aug 2022 13:34:21 +0200 Subject: [PATCH 08/49] use constants for fixture names --- tests/integration/_conftest/standard_project_fixture.py | 5 ++++- tests/integration/conftest.py | 5 ++++- tests/integration/gateway/gateway_facade_test.py | 6 +++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/integration/_conftest/standard_project_fixture.py b/tests/integration/_conftest/standard_project_fixture.py index 85b644fafc..47a7c6c2f3 100644 --- a/tests/integration/_conftest/standard_project_fixture.py +++ b/tests/integration/_conftest/standard_project_fixture.py @@ -45,7 +45,10 @@ def version_manager_fixture(mocker: MagicMock) -> VersionManager: return version_manager -@pytest.fixture(name="standard_project") +STANDARD_PROJECT_FIXTURE = "standard_project" + + +@pytest.fixture(name=STANDARD_PROJECT_FIXTURE) def standard_project_fixture(project_root_path: Path, version_manager: VersionManager): protostar_toml_writer = ProtostarTOMLWriter() project_creator = SimpleProjectCreator( diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 28c9b62452..7ed2630564 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -123,7 +123,10 @@ def project_compilation_output_path_fixture(project_root_path: Path): return output_path -@pytest.fixture(name="compiled_project") +COMPILED_PROJECT_FIXTURE = "compiled_project" + + +@pytest.fixture(name=COMPILED_PROJECT_FIXTURE) def compiled_project_fixture( project_root_path: Path, project_compilation_output_path: Path ): diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py index c7e49c65a6..26ece85bac 100644 --- a/tests/integration/gateway/gateway_facade_test.py +++ b/tests/integration/gateway/gateway_facade_test.py @@ -4,9 +4,13 @@ from protostar.starknet_gateway.gateway_facade import GatewayFacade from protostar.utils.log_color_provider import LogColorProvider +from tests.integration._conftest.standard_project_fixture import ( + STANDARD_PROJECT_FIXTURE, +) +from tests.integration.conftest import COMPILED_PROJECT_FIXTURE -@pytest.mark.usefixtures("standard_project", "compiled_project") +@pytest.mark.usefixtures(STANDARD_PROJECT_FIXTURE, COMPILED_PROJECT_FIXTURE) async def test_deploy(gateway_facade: GatewayFacade, compiled_contract_path: Path): response = await gateway_facade.deploy(compiled_contract_path) assert response is not None From 205204f8f36238607860d1ea0e20699e54b257f2 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 10 Aug 2022 13:49:06 +0200 Subject: [PATCH 09/49] fix importing fixtures --- tests/integration/conftest.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 7ed2630564..7cf7fcf8bb 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -19,9 +19,12 @@ from protostar.protostar_toml.protostar_project_section import ProtostarProjectSection from tests.conftest import run_devnet -pytest_plugins = [ - "tests.integration._conftest.project_fixture", -] +# pylint: disable=unused-import +from tests.integration._conftest.standard_project_fixture import ( + project_root_path_fixture, + standard_project_fixture, + version_manager_fixture, +) @dataclass From 9cef01da3789875acf3fefcb04225cf3ae1de99d Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 10 Aug 2022 14:02:50 +0200 Subject: [PATCH 10/49] use module scope --- .../_conftest/standard_project_fixture.py | 15 ++++++++------- tests/integration/conftest.py | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/integration/_conftest/standard_project_fixture.py b/tests/integration/_conftest/standard_project_fixture.py index 47a7c6c2f3..8736b5eec0 100644 --- a/tests/integration/_conftest/standard_project_fixture.py +++ b/tests/integration/_conftest/standard_project_fixture.py @@ -32,15 +32,16 @@ def _create_libs_dir(self) -> None: (self._project_root_path / "lib").mkdir(exist_ok=True, parents=True) -@pytest.fixture(name="project_root_path") -def project_root_path_fixture(tmp_path: Path) -> Path: +@pytest.fixture(name="project_root_path", scope="module") +def project_root_path_fixture(tmp_path_factory) -> Path: + tmp_path = tmp_path_factory.mktemp("data") return tmp_path / "default_project" -@pytest.fixture(name="version_manager") -def version_manager_fixture(mocker: MagicMock) -> VersionManager: - version_manager = mocker.MagicMock() - version_manager.protostar_version = mocker.MagicMock() +@pytest.fixture(name="version_manager", scope="module") +def version_manager_fixture(module_mocker: MagicMock) -> VersionManager: + version_manager = module_mocker.MagicMock() + version_manager.protostar_version = module_mocker.MagicMock() version_manager.protostar_version = "99.9.9" return version_manager @@ -48,7 +49,7 @@ def version_manager_fixture(mocker: MagicMock) -> VersionManager: STANDARD_PROJECT_FIXTURE = "standard_project" -@pytest.fixture(name=STANDARD_PROJECT_FIXTURE) +@pytest.fixture(name=STANDARD_PROJECT_FIXTURE, scope="module") def standard_project_fixture(project_root_path: Path, version_manager: VersionManager): protostar_toml_writer = ProtostarTOMLWriter() project_creator = SimpleProjectCreator( diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 7cf7fcf8bb..eb89c1db17 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -119,7 +119,7 @@ async def run_cairo_test_runner( return run_cairo_test_runner -@pytest.fixture(name="project_compilation_output_path") +@pytest.fixture(name="project_compilation_output_path", scope="module") def project_compilation_output_path_fixture(project_root_path: Path): output_path = project_root_path / "build" output_path.mkdir(exist_ok=True) @@ -129,7 +129,7 @@ def project_compilation_output_path_fixture(project_root_path: Path): COMPILED_PROJECT_FIXTURE = "compiled_project" -@pytest.fixture(name=COMPILED_PROJECT_FIXTURE) +@pytest.fixture(name=COMPILED_PROJECT_FIXTURE, scope="module") def compiled_project_fixture( project_root_path: Path, project_compilation_output_path: Path ): From 2ab9625165bff5267db88952d37e4a6d476ed064 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 10 Aug 2022 14:04:27 +0200 Subject: [PATCH 11/49] add declare test --- tests/integration/gateway/gateway_facade_test.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py index 26ece85bac..e9838de7c9 100644 --- a/tests/integration/gateway/gateway_facade_test.py +++ b/tests/integration/gateway/gateway_facade_test.py @@ -16,6 +16,12 @@ async def test_deploy(gateway_facade: GatewayFacade, compiled_contract_path: Pat assert response is not None +@pytest.mark.usefixtures(STANDARD_PROJECT_FIXTURE, COMPILED_PROJECT_FIXTURE) +async def test_declare(gateway_facade: GatewayFacade, compiled_contract_path: Path): + response = await gateway_facade.declare(compiled_contract_path) + assert response is not None + + @pytest.fixture(name="gateway_facade") def gateway_facade_fixture(devnet_gateway_url: str): log_color_provider = LogColorProvider() From 226cb5d32c27c14fb2ffe8483cadf7c59d5cec54 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 10 Aug 2022 14:41:12 +0200 Subject: [PATCH 12/49] add tests --- protostar/starknet_gateway/gateway_facade.py | 25 ++++++------- .../gateway/gateway_facade_test.py | 37 ++++++++++++++++--- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/protostar/starknet_gateway/gateway_facade.py b/protostar/starknet_gateway/gateway_facade.py index 37c218423d..65036afc3a 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -1,16 +1,15 @@ +import dataclasses from logging import Logger from pathlib import Path -from typing import Callable, List, Optional, Dict, Any -import dataclasses - -from starkware.starknet.services.api.gateway.transaction import DECLARE_SENDER_ADDRESS -from starkware.starknet.definitions import constants +from typing import Any, Callable, Dict, List, Optional +from starknet_py.contract import Contract, InvokeResult from starknet_py.net.gateway_client import GatewayClient -from starknet_py.transactions.deploy import make_deploy_tx +from starknet_py.net.models import AddressRepresentation, StarknetChainId from starknet_py.transactions.declare import make_declare_tx -from starknet_py.net.models import StarknetChainId, AddressRepresentation -from starknet_py.contract import Contract +from starknet_py.transactions.deploy import make_deploy_tx +from starkware.starknet.definitions import constants +from starkware.starknet.services.api.gateway.transaction import DECLARE_SENDER_ADDRESS from protostar.protostar_exception import ProtostarException from protostar.starknet_gateway.gateway_response import ( @@ -207,16 +206,14 @@ async def invoke( function_name: str, inputs: Dict[str, Any], wait_for_acceptance: bool = False, - ): + ) -> InvokeResult: contract = await Contract.from_address( address=address, client=self._gateway_client ) - result = await contract.functions[function_name].invoke(**inputs) - + response = await contract.functions[function_name].invoke(**inputs) if wait_for_acceptance: - result = await result.wait_for_acceptance() - - print("INVOKE: ", result) + return await response.wait_for_acceptance() + return response def _register_request( self, action: StarknetRequest.Action, payload: StarknetRequest.Payload diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py index e9838de7c9..94ec326900 100644 --- a/tests/integration/gateway/gateway_facade_test.py +++ b/tests/integration/gateway/gateway_facade_test.py @@ -4,24 +4,49 @@ from protostar.starknet_gateway.gateway_facade import GatewayFacade from protostar.utils.log_color_provider import LogColorProvider -from tests.integration._conftest.standard_project_fixture import ( - STANDARD_PROJECT_FIXTURE, -) -from tests.integration.conftest import COMPILED_PROJECT_FIXTURE -@pytest.mark.usefixtures(STANDARD_PROJECT_FIXTURE, COMPILED_PROJECT_FIXTURE) +@pytest.fixture(autouse=True, scope="module") +# pylint: disable=unused-argument +def testing_environment(standard_project, compiled_project): + pass + + async def test_deploy(gateway_facade: GatewayFacade, compiled_contract_path: Path): response = await gateway_facade.deploy(compiled_contract_path) assert response is not None -@pytest.mark.usefixtures(STANDARD_PROJECT_FIXTURE, COMPILED_PROJECT_FIXTURE) async def test_declare(gateway_facade: GatewayFacade, compiled_contract_path: Path): response = await gateway_facade.declare(compiled_contract_path) assert response is not None +async def test_invoke(gateway_facade: GatewayFacade, compiled_contract_path: Path): + deployed_contract = await gateway_facade.deploy(compiled_contract_path) + + response = await gateway_facade.invoke( + deployed_contract.address, + function_name="increase_balance", + inputs={"amount": 42}, + wait_for_acceptance=True, + ) + + assert response is not None + + +async def test_call(gateway_facade: GatewayFacade, compiled_contract_path: Path): + deployed_contract = await gateway_facade.deploy(compiled_contract_path) + + response = await gateway_facade.call( + deployed_contract.address, + function_name="get_balance", + inputs={}, + ) + + assert response is not None + + @pytest.fixture(name="gateway_facade") def gateway_facade_fixture(devnet_gateway_url: str): log_color_provider = LogColorProvider() From c4df9c07855c34c5957dcc89032e4f73f18d78f3 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Thu, 11 Aug 2022 13:20:07 +0200 Subject: [PATCH 13/49] add more learning tests --- protostar/starknet_gateway/gateway_facade.py | 25 +++++---- .../gateway/gateway_facade_test.py | 55 ++++++++++++++++--- 2 files changed, 60 insertions(+), 20 deletions(-) diff --git a/protostar/starknet_gateway/gateway_facade.py b/protostar/starknet_gateway/gateway_facade.py index 65036afc3a..322b9acdd1 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -1,7 +1,7 @@ import dataclasses from logging import Logger from pathlib import Path -from typing import Any, Callable, Dict, List, Optional +from typing import Any, Callable, Dict, List, Optional, Union from starknet_py.contract import Contract, InvokeResult from starknet_py.net.gateway_client import GatewayClient @@ -184,21 +184,22 @@ async def declare( ) async def call( - self, address: AddressRepresentation, function_name: str, inputs: Dict[str, Any] + self, + address: AddressRepresentation, + function_name: str, + inputs: Optional[Union[List[int], Dict[str, Any]]] = None, ): - # TODO: - # Add registering request - # Consider returning something other than a NamedTuple - # Consider catching exceptions - # Check whether the awaits make sense - # Consider caching contracts - # Add None checking to inputs - + if inputs is None: + inputs = {} 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) + contract_function = contract.functions[function_name] + if isinstance(inputs, List): + result = await contract_function.call(*inputs) + else: + result = await contract_function.call(**inputs) + return result async def invoke( self, diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py index 94ec326900..6feb11d385 100644 --- a/tests/integration/gateway/gateway_facade_test.py +++ b/tests/integration/gateway/gateway_facade_test.py @@ -1,6 +1,7 @@ from pathlib import Path import pytest +from starknet_py.net.client_errors import ContractNotFoundError from protostar.starknet_gateway.gateway_facade import GatewayFacade from protostar.utils.log_color_provider import LogColorProvider @@ -22,17 +23,19 @@ async def test_declare(gateway_facade: GatewayFacade, compiled_contract_path: Pa assert response is not None +@pytest.mark.skip("Protostar needs to support accounts first") async def test_invoke(gateway_facade: GatewayFacade, compiled_contract_path: Path): deployed_contract = await gateway_facade.deploy(compiled_contract_path) - response = await gateway_facade.invoke( - deployed_contract.address, - function_name="increase_balance", - inputs={"amount": 42}, - wait_for_acceptance=True, - ) + with pytest.raises(ValueError, match="You need to use AccountClient for that."): + await gateway_facade.invoke( + deployed_contract.address, + function_name="increase_balance", + inputs={"amount": 42}, + wait_for_acceptance=True, + ) - assert response is not None + assert False async def test_call(gateway_facade: GatewayFacade, compiled_contract_path: Path): @@ -44,7 +47,43 @@ async def test_call(gateway_facade: GatewayFacade, compiled_contract_path: Path) inputs={}, ) - assert response is not None + initial_balance = 0 + assert response[0] == initial_balance + + +async def test_call_to_unknown_function( + gateway_facade: GatewayFacade, compiled_contract_path: Path +): + deployed_contract = await gateway_facade.deploy(compiled_contract_path) + + with pytest.raises(KeyError): + await gateway_facade.call( + deployed_contract.address, + function_name="UNKNOWN_FUNCTION", + inputs={}, + ) + + +async def test_call_to_unknown_contract(gateway_facade: GatewayFacade): + with pytest.raises(ContractNotFoundError, match="No contract found for identifier"): + await gateway_facade.call( + 123, + function_name="UNKNOWN_FUNCTION", + ) + + +@pytest.mark.skip("https://github.com/software-mansion/starknet.py/issues/302") +async def test_call_to_with_incorrect_args( + gateway_facade: GatewayFacade, compiled_contract_path: Path +): + deployed_contract = await gateway_facade.deploy(compiled_contract_path) + + with pytest.raises(Exception): + await gateway_facade.call( + deployed_contract.address, + function_name="get_balance", + inputs={"UNKNOWN_ARG": 42}, + ) @pytest.fixture(name="gateway_facade") From 5752227b96fb4c369b4a71c0893458b7741d36ed Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Thu, 11 Aug 2022 14:12:53 +0200 Subject: [PATCH 14/49] remove invoke and _add call test --- .../cheatcodes/migrator_call_cheatcode.py | 21 +++--- .../cheatcodes/migrator_invoke_cheatcode.py | 67 ------------------- .../migrator/migrator_cheatcodes_factory.py | 7 +- protostar/starknet_gateway/gateway_facade.py | 4 +- tests/integration/migrator/conftest.py | 33 ++++++++- .../migrator/migrator_call_cheatcode_test.py | 15 +++++ 6 files changed, 59 insertions(+), 88 deletions(-) delete mode 100644 protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py create mode 100644 tests/integration/migrator/migrator_call_cheatcode_test.py diff --git a/protostar/migrator/cheatcodes/migrator_call_cheatcode.py b/protostar/migrator/cheatcodes/migrator_call_cheatcode.py index 8599c69685..3b0ff2d337 100644 --- a/protostar/migrator/cheatcodes/migrator_call_cheatcode.py +++ b/protostar/migrator/cheatcodes/migrator_call_cheatcode.py @@ -1,19 +1,19 @@ import asyncio -from typing import Dict, Any, Optional -from typing_extensions import Protocol +from typing import Any, Optional -from starknet_py.net.models import AddressRepresentation +from typing_extensions import Protocol from protostar.starknet.cheatcode import Cheatcode from protostar.starknet_gateway import GatewayFacade +from protostar.utils.data_transformer import CairoOrPythonData class CallCheatcodeProtocol(Protocol): def __call__( self, - address: AddressRepresentation, + contract_address: int, function_name: str, - inputs: Optional[Dict[str, Any]] = None, + inputs: Optional[CairoOrPythonData] = None, ) -> Any: ... @@ -36,17 +36,14 @@ def build(self) -> CallCheatcodeProtocol: def call( self, - address: AddressRepresentation, + contract_address: int, function_name: str, - inputs: Optional[Dict[str, Any]] = None, + inputs: Optional[CairoOrPythonData] = None, ): - - output = asyncio.run( + return asyncio.run( self._gateway_facade.call( - address=address, + address=contract_address, function_name=function_name, inputs=inputs, ) ) - - return output diff --git a/protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py b/protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py deleted file mode 100644 index 2054ebea65..0000000000 --- a/protostar/migrator/cheatcodes/migrator_invoke_cheatcode.py +++ /dev/null @@ -1,67 +0,0 @@ -import asyncio -from typing import Dict, Any, Optional -from typing_extensions import Protocol - -from starknet_py.net.models import AddressRepresentation - -from protostar.starknet.cheatcode import Cheatcode -from protostar.starknet_gateway import GatewayFacade -from protostar.commands.test.test_environment_exceptions import ( - KeywordOnlyArgumentCheatcodeException, -) - -from .network_config import CheatcodeNetworkConfig, ValidatedCheatcodeNetworkConfig - - -class InvokeCheatcodeProtocol(Protocol): - # pylint: disable=keyword-arg-before-vararg - def __call__( - self, - address: AddressRepresentation, - function_name: str, - inputs: Optional[Dict[str, Any]] = None, - *args, - config: Optional[Any] = None, - ) -> Any: - ... - - -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) -> InvokeCheatcodeProtocol: - return self.invoke - - # pylint: disable=keyword-arg-before-vararg - async def invoke( - self, - address: AddressRepresentation, - function_name: str, - inputs: Optional[Dict[str, Any]] = None, - *args, - config: Optional[CheatcodeNetworkConfig] = None, - ): - if len(args) > 0: - raise KeywordOnlyArgumentCheatcodeException(self.name, ["config"]) - - validated_config = ValidatedCheatcodeNetworkConfig.from_dict( - config or CheatcodeNetworkConfig() - ) - asyncio.run( - self._gateway_facade.invoke( - address=address, - function_name=function_name, - inputs=inputs, - wait_for_acceptance=validated_config.wait_for_acceptance, - ) - ) diff --git a/protostar/migrator/migrator_cheatcodes_factory.py b/protostar/migrator/migrator_cheatcodes_factory.py index ccf1d9d3d4..cd58046092 100644 --- a/protostar/migrator/migrator_cheatcodes_factory.py +++ b/protostar/migrator/migrator_cheatcodes_factory.py @@ -3,17 +3,13 @@ from starkware.starknet.business_logic.execution.objects import CallInfo +from protostar.migrator.cheatcodes.migrator_call_cheatcode import MigratorCallCheatcode from protostar.migrator.cheatcodes.migrator_declare_cheatcode import ( MigratorDeclareCheatcode, ) 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 @@ -56,6 +52,5 @@ 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 322b9acdd1..818b8702a5 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -1,7 +1,7 @@ import dataclasses from logging import Logger from pathlib import Path -from typing import Any, Callable, Dict, List, Optional, Union +from typing import Any, Callable, Dict, List, NamedTuple, Optional, Union from starknet_py.contract import Contract, InvokeResult from starknet_py.net.gateway_client import GatewayClient @@ -188,7 +188,7 @@ async def call( address: AddressRepresentation, function_name: str, inputs: Optional[Union[List[int], Dict[str, Any]]] = None, - ): + ) -> NamedTuple: if inputs is None: inputs = {} contract = await Contract.from_address( diff --git a/tests/integration/migrator/conftest.py b/tests/integration/migrator/conftest.py index 812c1fc909..7a7fce17fd 100644 --- a/tests/integration/migrator/conftest.py +++ b/tests/integration/migrator/conftest.py @@ -1,10 +1,11 @@ from pathlib import Path -from typing import Union +from typing import Protocol, Union import pytest from starknet_py.net.client_models import TransactionStatus from starknet_py.net.gateway_client import GatewayClient from starknet_py.net.models import StarknetChainId +from typing_extensions import Literal from protostar.migrator import Migrator from protostar.migrator.migrator_execution_environment import ( @@ -38,3 +39,33 @@ async def assert_transaction_accepted( transaction_hash, wait_for_accept=True ) assert transaction_status == TransactionStatus.ACCEPTED_ON_L2 + + +MigrationFileName = Literal[ + "migration_declare_file_not_found.cairo", + "migration_declare.cairo", + "migration_deploy_contract.cairo", + "migration_down.cairo", +] + + +class RunMigrateFixture(Protocol): + async def __call__( + self, migration_file_name: MigrationFileName, rollback=False + ) -> Migrator.History: + ... + + +@pytest.fixture(name="run_migrate") +async def run_migrate_fixture( + migrator_builder: Migrator.Builder, project_root_path: Path +) -> RunMigrateFixture: + async def run_migrate( + migration_file_name: MigrationFileName, rollback=False + ) -> Migrator.History: + migrator = await migrator_builder.build( + migration_file_path=project_root_path / "migrations" / migration_file_name, + ) + return await migrator.run(rollback) + + return run_migrate diff --git a/tests/integration/migrator/migrator_call_cheatcode_test.py b/tests/integration/migrator/migrator_call_cheatcode_test.py new file mode 100644 index 0000000000..6065b5c47c --- /dev/null +++ b/tests/integration/migrator/migrator_call_cheatcode_test.py @@ -0,0 +1,15 @@ +from pathlib import Path +from typing import cast + +from protostar.migrator import Migrator +from tests.integration.migrator.conftest import ( + RunMigrateFixture, + assert_transaction_accepted, +) + + +async def test_call_contract(run_migrate: RunMigrateFixture): + migration_history = await run_migrate("migration_declare.cairo") + + assert_migration_history_includes_call_request(migration_history) + assert_migration_history_includes_call_response(migration_history) From 684ab2153909bf3e07f0cd0b007bbb0f00103f51 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Thu, 11 Aug 2022 16:26:11 +0200 Subject: [PATCH 15/49] _add test --- tests/integration/migrator/conftest.py | 10 +++++-- .../migrator/migrator_call_cheatcode_test.py | 29 ++++++++++++++----- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/tests/integration/migrator/conftest.py b/tests/integration/migrator/conftest.py index 7a7fce17fd..a9bdf32d9b 100644 --- a/tests/integration/migrator/conftest.py +++ b/tests/integration/migrator/conftest.py @@ -1,11 +1,12 @@ +from enum import Enum from pathlib import Path -from typing import Protocol, Union +from typing import Union import pytest from starknet_py.net.client_models import TransactionStatus from starknet_py.net.gateway_client import GatewayClient from starknet_py.net.models import StarknetChainId -from typing_extensions import Literal +from typing_extensions import Literal, Protocol from protostar.migrator import Migrator from protostar.migrator.migrator_execution_environment import ( @@ -46,6 +47,7 @@ async def assert_transaction_accepted( "migration_declare.cairo", "migration_deploy_contract.cairo", "migration_down.cairo", + "migration_deploy_and_call.cairo", ] @@ -69,3 +71,7 @@ async def run_migrate( return await migrator.run(rollback) return run_migrate + + +class ContractMainWithConstructorDefaults(Enum): + INITIAL_BALANCE = 0 diff --git a/tests/integration/migrator/migrator_call_cheatcode_test.py b/tests/integration/migrator/migrator_call_cheatcode_test.py index 6065b5c47c..198f84dbe4 100644 --- a/tests/integration/migrator/migrator_call_cheatcode_test.py +++ b/tests/integration/migrator/migrator_call_cheatcode_test.py @@ -1,15 +1,28 @@ -from pathlib import Path -from typing import cast - -from protostar.migrator import Migrator +from protostar.starknet_gateway.starknet_request import StarknetRequest from tests.integration.migrator.conftest import ( + ContractMainWithConstructorDefaults, RunMigrateFixture, - assert_transaction_accepted, ) async def test_call_contract(run_migrate: RunMigrateFixture): - migration_history = await run_migrate("migration_declare.cairo") + migration_history = await run_migrate("migration_deploy_and_call.cairo") + + contract_address = extract_contract_address_from_deploy_response( + migration_history.starknet_requests[0].response + ) + call_request = migration_history.starknet_requests[1] + assert call_request.action == "CALL" + assert call_request.payload["inputs"] == "[]" + assert call_request.payload["contract_address"] == str(contract_address) + assert ( + call_request.response["response"] + == ContractMainWithConstructorDefaults.INITIAL_BALANCE + ) + - assert_migration_history_includes_call_request(migration_history) - assert_migration_history_includes_call_response(migration_history) +def extract_contract_address_from_deploy_response( + deploy_response: StarknetRequest.Payload, +) -> int: + assert isinstance(deploy_response["contract_address"], int) + return deploy_response["contract_address"] From 3174a72c82ea97c7e6859d6294a0aef4abd5ed5d Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Thu, 11 Aug 2022 16:59:16 +0200 Subject: [PATCH 16/49] refine test --- tests/integration/migrator/conftest.py | 27 -------------- .../migrator/migrator_call_cheatcode_test.py | 37 ++++++++++++++----- 2 files changed, 27 insertions(+), 37 deletions(-) diff --git a/tests/integration/migrator/conftest.py b/tests/integration/migrator/conftest.py index a9bdf32d9b..75c5062bed 100644 --- a/tests/integration/migrator/conftest.py +++ b/tests/integration/migrator/conftest.py @@ -47,31 +47,4 @@ async def assert_transaction_accepted( "migration_declare.cairo", "migration_deploy_contract.cairo", "migration_down.cairo", - "migration_deploy_and_call.cairo", ] - - -class RunMigrateFixture(Protocol): - async def __call__( - self, migration_file_name: MigrationFileName, rollback=False - ) -> Migrator.History: - ... - - -@pytest.fixture(name="run_migrate") -async def run_migrate_fixture( - migrator_builder: Migrator.Builder, project_root_path: Path -) -> RunMigrateFixture: - async def run_migrate( - migration_file_name: MigrationFileName, rollback=False - ) -> Migrator.History: - migrator = await migrator_builder.build( - migration_file_path=project_root_path / "migrations" / migration_file_name, - ) - return await migrator.run(rollback) - - return run_migrate - - -class ContractMainWithConstructorDefaults(Enum): - INITIAL_BALANCE = 0 diff --git a/tests/integration/migrator/migrator_call_cheatcode_test.py b/tests/integration/migrator/migrator_call_cheatcode_test.py index 198f84dbe4..86e9e54db4 100644 --- a/tests/integration/migrator/migrator_call_cheatcode_test.py +++ b/tests/integration/migrator/migrator_call_cheatcode_test.py @@ -1,12 +1,32 @@ +import pytest + from protostar.starknet_gateway.starknet_request import StarknetRequest -from tests.integration.migrator.conftest import ( - ContractMainWithConstructorDefaults, - RunMigrateFixture, -) -async def test_call_contract(run_migrate: RunMigrateFixture): - migration_history = await run_migrate("migration_deploy_and_call.cairo") +@pytest.fixture(autouse=True, scope="module") +# pylint: disable=unused-argument +def testing_environment(standard_project, compile_project): + compile_project( + { + "main.json": """ + %lang starknet + + @view + func identity(arg) -> (res : felt): + return (arg) + end + """ + } + ) + + +async def test_call_contract(migrate): + migration_history = await migrate( + """ + contract_address = deploy("./build/main.json").contract_address + call(contract_address, "identity", [42]) + """ + ) contract_address = extract_contract_address_from_deploy_response( migration_history.starknet_requests[0].response @@ -15,10 +35,7 @@ async def test_call_contract(run_migrate: RunMigrateFixture): assert call_request.action == "CALL" assert call_request.payload["inputs"] == "[]" assert call_request.payload["contract_address"] == str(contract_address) - assert ( - call_request.response["response"] - == ContractMainWithConstructorDefaults.INITIAL_BALANCE - ) + assert call_request.response["response"] == "42" def extract_contract_address_from_deploy_response( From 3f859cbc322c842cd5e69d2cecf072daa7eb8367 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Thu, 11 Aug 2022 17:16:53 +0200 Subject: [PATCH 17/49] change fixture desired interface --- tests/integration/conftest.py | 27 ++++++++++++++++++- .../migrator/migrator_call_cheatcode_test.py | 8 +++--- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index eb89c1db17..0c50e35a1f 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from os import listdir from pathlib import Path -from typing import List, Optional, Set, Union +from typing import Dict, List, Optional, Set, Union import pytest from pytest_mock import MockerFixture @@ -129,6 +129,31 @@ def project_compilation_output_path_fixture(project_root_path: Path): COMPILED_PROJECT_FIXTURE = "compiled_project" +class CompileProjectFixture(Protocol): + def __call__(self, str_path_to_content: Dict[str, str]) -> None: + ... + + +@pytest.fixture(name="compile_project", scope="module") +def compile_project_fixture( + standard_project, project_root_path: Path +) -> CompileProjectFixture: + def compile_project(str_path_to_content: Dict[str, str]): + for relative_str_path, content in str_path_to_content.items(): + save_file(project_root_path / relative_str_path, content) + + return compile_project + + +def save_file(path: Path, content: str): + with open( + path, + mode="w", + encoding="utf-8", + ) as output_file: + output_file.write(content) + + @pytest.fixture(name=COMPILED_PROJECT_FIXTURE, scope="module") def compiled_project_fixture( project_root_path: Path, project_compilation_output_path: Path diff --git a/tests/integration/migrator/migrator_call_cheatcode_test.py b/tests/integration/migrator/migrator_call_cheatcode_test.py index 86e9e54db4..91d86d90aa 100644 --- a/tests/integration/migrator/migrator_call_cheatcode_test.py +++ b/tests/integration/migrator/migrator_call_cheatcode_test.py @@ -5,10 +5,11 @@ @pytest.fixture(autouse=True, scope="module") # pylint: disable=unused-argument -def testing_environment(standard_project, compile_project): - compile_project( +def setup(protostar_project): + protostar_project.init() + protostar_project.setup( { - "main.json": """ + "./src/main.json": """ %lang starknet @view @@ -18,6 +19,7 @@ def testing_environment(standard_project, compile_project): """ } ) + protostar_project.build() async def test_call_contract(migrate): From 288fc623489849a631e6032db18f6dba03655a69 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Thu, 11 Aug 2022 19:01:18 +0200 Subject: [PATCH 18/49] _add protostar fixture --- protostar/__init__.py | 2 +- protostar/commands/build/build_command.py | 19 +++- protostar/composition_root.py | 8 +- protostar/start.py | 2 +- tests/integration/protostar_fixture.py | 114 ++++++++++++++++++++++ 5 files changed, 135 insertions(+), 10 deletions(-) create mode 100644 tests/integration/protostar_fixture.py diff --git a/protostar/__init__.py b/protostar/__init__.py index ea09d146c9..9c9777cd6e 100644 --- a/protostar/__init__.py +++ b/protostar/__init__.py @@ -1,7 +1,7 @@ import sys -from starkware.crypto.signature.fast_pedersen_hash import pedersen_hash from crypto_cpp_py.cpp_bindings import cpp_hash +from starkware.crypto.signature.fast_pedersen_hash import pedersen_hash def patched_pedersen_hash(left: int, right: int) -> int: diff --git a/protostar/commands/build/build_command.py b/protostar/commands/build/build_command.py index 2827688859..44c33bd564 100644 --- a/protostar/commands/build/build_command.py +++ b/protostar/commands/build/build_command.py @@ -1,4 +1,5 @@ from logging import Logger +from pathlib import Path from typing import List, Optional from protostar.cli import ActivityIndicator, Command @@ -48,15 +49,27 @@ def arguments(self) -> List[Command.Argument]: ] async def run(self, args): + await self.build( + output_dir=args.output, + disable_hint_validation=args.disable_hint_validation, + relative_cairo_path=args.cairo_path, + ) + + async def build( + self, + output_dir: Path, + disable_hint_validation=False, + relative_cairo_path: Optional[List[Path]] = None, + ): with ActivityIndicator( log_color_provider.colorize("GRAY", "Building projects' contracts") ): try: self._project_compiler.compile_project( - output_dir=args.output, + output_dir=output_dir, config=ProjectCompilerConfig( - hint_validation_disabled=args.disable_hint_validation, - relative_cairo_path=args.cairo_path, + hint_validation_disabled=disable_hint_validation, + relative_cairo_path=relative_cairo_path or [], ), ) except BaseException as exc: diff --git a/protostar/composition_root.py b/protostar/composition_root.py index 2f8531b654..11c53c8ddc 100644 --- a/protostar/composition_root.py +++ b/protostar/composition_root.py @@ -55,13 +55,11 @@ class DIContainer: # pylint: disable=too-many-locals -def build_di_container(script_root: Path): +def build_di_container(script_root: Path, cwd: Path): logger = getLogger() - protostar_toml_path = search_upwards_protostar_toml_path( - start_path=Path().resolve() - ) + protostar_toml_path = search_upwards_protostar_toml_path(start_path=cwd.resolve()) project_root_path = ( - protostar_toml_path.parent if protostar_toml_path is not None else Path() + protostar_toml_path.parent if protostar_toml_path is not None else cwd ) protostar_toml_path = protostar_toml_path or project_root_path / "protostar.toml" protostar_directory = ProtostarDirectory(script_root) diff --git a/protostar/start.py b/protostar/start.py index 09c98c2c1a..fec1705b8d 100644 --- a/protostar/start.py +++ b/protostar/start.py @@ -17,7 +17,7 @@ def main(script_root: Path): - container = build_di_container(script_root) + container = build_di_container(script_root, cwd=Path()) arg_parser = build_parser(container.protostar_cli, container.protostar_toml_reader) args = parse_args(arg_parser) run_protostar(container.protostar_cli, args, arg_parser) diff --git a/tests/integration/protostar_fixture.py b/tests/integration/protostar_fixture.py new file mode 100644 index 0000000000..b195880bcd --- /dev/null +++ b/tests/integration/protostar_fixture.py @@ -0,0 +1,114 @@ +from pathlib import Path + +from pytest_mock import MockerFixture +from typing_extensions import Self + +from protostar.commands.init.project_creator import ProjectCreator +from protostar.compiler import ProjectCairoPathBuilder, ProjectCompiler +from protostar.compiler.project_compiler import ProjectCompilerConfig +from protostar.migrator import Migrator, MigratorExecutionEnvironment +from protostar.protostar_toml import ( + ProtostarContractsSection, + ProtostarProjectSection, + ProtostarTOMLReader, + ProtostarTOMLWriter, +) +from protostar.starknet_gateway import GatewayFacade +from protostar.utils import VersionManager + + +class ProtostarFixture: + def __init__( + self, + simple_project_creator: "SimpleProjectCreator", + project_compiler: ProjectCompiler, + migrator_builder: Migrator.Builder, + ) -> None: + self._simple_project_creator = simple_project_creator + self._project_compiler = project_compiler + self._migrator_builder = migrator_builder + + async def init(self) -> Self: + self._simple_project_creator.run() + return self + + async def build(self, output_dir: Path) -> Self: + self._project_compiler.compile_project( + output_dir=output_dir, + config=ProjectCompilerConfig( + hint_validation_disabled=False, + relative_cairo_path=[], + ), + ) + return self + + async def migrate(self, filepath: Path, rollback=False) -> Self: + migrator = await self._migrator_builder.build(filepath) + await migrator.run(rollback) + return self + + +# pylint: disable=too-many-locals +def build_protostar_fixture(project_root_path: Path, mocker: MockerFixture): + version_manager = mocker.MagicMock() + version_manager.protostar_version = mocker.MagicMock() + version_manager.protostar_version = "99.9.9" + + protostar_toml_path = project_root_path / "protostar.toml" + protostar_toml_writer = ProtostarTOMLWriter() + protostar_toml_reader = ProtostarTOMLReader(protostar_toml_path=protostar_toml_path) + + project_cairo_path_builder = ProjectCairoPathBuilder( + project_root_path=project_root_path, + project_section_loader=ProtostarProjectSection.Loader(protostar_toml_reader), + ) + + project_compiler = ProjectCompiler( + project_root_path=project_root_path, + project_cairo_path_builder=project_cairo_path_builder, + contracts_section_loader=ProtostarContractsSection.Loader( + protostar_toml_reader + ), + ) + + migrator_builder = Migrator.Builder( + migrator_execution_environment_builder=MigratorExecutionEnvironment.Builder(), + gateway_facade_builder=GatewayFacade.Builder(project_root_path), + ) + + simple_project_creator = SimpleProjectCreator( + project_root_path, + Path(__file__).parent / ".." / "..", + protostar_toml_writer, + version_manager, + ) + + ProtostarFixture( + project_compiler=project_compiler, + migrator_builder=migrator_builder, + simple_project_creator=simple_project_creator, + ) + + +class SimpleProjectCreator(ProjectCreator): + def __init__( + self, + project_root_path: Path, + script_root: Path, + protostar_toml_writer: ProtostarTOMLWriter, + version_manager: VersionManager, + ): + super().__init__( + script_root, + protostar_toml_writer, + version_manager, + ) + self._project_root_path = project_root_path + + def run(self): + self.copy_template("default", self._project_root_path) + self.save_protostar_toml(self._project_root_path, Path("./lib")) + self._create_libs_dir() + + def _create_libs_dir(self) -> None: + (self._project_root_path / "lib").mkdir(exist_ok=True, parents=True) From 3732554bc500641319ff0341c5d25ddaced62af1 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Thu, 11 Aug 2022 20:49:56 +0200 Subject: [PATCH 19/49] add protostar fixture --- .../project_creator/new_project_creator.py | 6 +- protostar/commands/migrate/migrate_command.py | 8 +- tests/integration/conftest.py | 26 ++- tests/integration/migrator/conftest.py | 3 +- .../migrator/migrator_call_cheatcode_test.py | 24 ++- tests/integration/protostar_fixture.py | 185 ++++++++++++------ 6 files changed, 179 insertions(+), 73 deletions(-) diff --git a/protostar/commands/init/project_creator/new_project_creator.py b/protostar/commands/init/project_creator/new_project_creator.py index 6ce3afaea3..45b593747c 100644 --- a/protostar/commands/init/project_creator/new_project_creator.py +++ b/protostar/commands/init/project_creator/new_project_creator.py @@ -1,5 +1,6 @@ from dataclasses import dataclass from pathlib import Path +from typing import Optional from git import InvalidGitRepositoryError from git.repo import Repo @@ -22,11 +23,13 @@ def __init__( requester: InputRequester, protostar_toml_writer: ProtostarTOMLWriter, version_manager: VersionManager, + output_dir_path: Optional[Path], ): super().__init__(script_root, protostar_toml_writer, version_manager) self._protostar_toml_writer = protostar_toml_writer self._version_manager = version_manager self._requester = requester + self._output_dir_path = output_dir_path def run(self): self._create_project(self._gather_input()) @@ -46,7 +49,8 @@ def _gather_input(self) -> "NewProjectCreator.UserInput": return NewProjectCreator.UserInput(project_dirname, lib_dirname) def _create_project(self, user_input: "NewProjectCreator.UserInput") -> None: - project_root_path = Path() / user_input.project_dirname + output_dir_path = self._output_dir_path or Path() + project_root_path = output_dir_path / user_input.project_dirname self.copy_template("default", project_root_path) libs_path = Path(project_root_path, user_input.lib_dirname) diff --git a/protostar/commands/migrate/migrate_command.py b/protostar/commands/migrate/migrate_command.py index 75e1ab982a..4503299566 100644 --- a/protostar/commands/migrate/migrate_command.py +++ b/protostar/commands/migrate/migrate_command.py @@ -3,12 +3,12 @@ from typing import List, Optional from protostar.cli import Command +from protostar.commands.deploy import DeployCommand from protostar.commands.test.test_environment_exceptions import CheatcodeException from protostar.migrator import Migrator from protostar.protostar_exception import ProtostarException from protostar.utils.input_requester import InputRequester from protostar.utils.log_color_provider import LogColorProvider -from protostar.commands.deploy import DeployCommand class MigrateCommand(Command): @@ -69,8 +69,8 @@ def arguments(self) -> List[Command.Argument]: DeployCommand.network_arg, ] - async def run(self, args): - await self.migrate( + async def run(self, args) -> Optional[Migrator.History]: + return await self.migrate( migration_file_path=args.path, rollback=args.rollback, network=args.network or args.gateway_url, @@ -117,5 +117,7 @@ async def migrate( output_dir_path=output_dir_path, ) self._logger.info("Migration completed") + + return migrator_history except CheatcodeException as ex: raise ProtostarException(str(ex)) from ex diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 0c50e35a1f..b75771de5c 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -3,6 +3,7 @@ from os import listdir from pathlib import Path from typing import Dict, List, Optional, Set, Union +from unittest.mock import MagicMock import pytest from pytest_mock import MockerFixture @@ -25,6 +26,10 @@ standard_project_fixture, version_manager_fixture, ) +from tests.integration.protostar_fixture import ( + ProtostarFixture, + build_protostar_fixture, +) @dataclass @@ -135,9 +140,7 @@ def __call__(self, str_path_to_content: Dict[str, str]) -> None: @pytest.fixture(name="compile_project", scope="module") -def compile_project_fixture( - standard_project, project_root_path: Path -) -> CompileProjectFixture: +def compile_project_fixture(project_root_path: Path) -> CompileProjectFixture: def compile_project(str_path_to_content: Dict[str, str]): for relative_str_path, content in str_path_to_content.items(): save_file(project_root_path / relative_str_path, content) @@ -183,3 +186,20 @@ def compiled_project_fixture( ) output_files_count = len(listdir(project_compilation_output_path)) assert output_files_count > 0, "Project didn't compile" + + +@pytest.fixture(name="protostar_project_root_path", scope="module") +def protostar_project_root_path_fixture(tmp_path_factory) -> Path: + tmp_path = tmp_path_factory.mktemp("data") + return tmp_path / "tmp_project" + + +@pytest.fixture(name="protostar", scope="module") +def protostar_fixture( + session_mocker: MagicMock, + protostar_project_root_path: Path, +) -> ProtostarFixture: + return build_protostar_fixture( + mocker=session_mocker, + project_root_path=protostar_project_root_path, + ) diff --git a/tests/integration/migrator/conftest.py b/tests/integration/migrator/conftest.py index 75c5062bed..ffcef5656f 100644 --- a/tests/integration/migrator/conftest.py +++ b/tests/integration/migrator/conftest.py @@ -1,4 +1,3 @@ -from enum import Enum from pathlib import Path from typing import Union @@ -6,7 +5,7 @@ from starknet_py.net.client_models import TransactionStatus from starknet_py.net.gateway_client import GatewayClient from starknet_py.net.models import StarknetChainId -from typing_extensions import Literal, Protocol +from typing_extensions import Literal from protostar.migrator import Migrator from protostar.migrator.migrator_execution_environment import ( diff --git a/tests/integration/migrator/migrator_call_cheatcode_test.py b/tests/integration/migrator/migrator_call_cheatcode_test.py index 91d86d90aa..90607b4e83 100644 --- a/tests/integration/migrator/migrator_call_cheatcode_test.py +++ b/tests/integration/migrator/migrator_call_cheatcode_test.py @@ -1,13 +1,21 @@ +import asyncio + import pytest from protostar.starknet_gateway.starknet_request import StarknetRequest +from tests.integration.protostar_fixture import ProtostarFixture + + +@pytest.fixture(scope="module") +def event_loop(): + return asyncio.get_event_loop() @pytest.fixture(autouse=True, scope="module") # pylint: disable=unused-argument -def setup(protostar_project): - protostar_project.init() - protostar_project.setup( +async def setup(protostar: ProtostarFixture): + await protostar.init() + protostar.create_files( { "./src/main.json": """ %lang starknet @@ -19,17 +27,19 @@ def setup(protostar_project): """ } ) - protostar_project.build() + await protostar.build() -async def test_call_contract(migrate): - migration_history = await migrate( +async def test_call_contract(protostar: ProtostarFixture, devnet_gateway_url: str): + file_path = protostar.create_migration( """ - contract_address = deploy("./build/main.json").contract_address + contract_address = deploy_contract("./build/main.json").contract_address call(contract_address, "identity", [42]) """ ) + migration_history = await protostar.migrate(file_path, network=devnet_gateway_url) + contract_address = extract_contract_address_from_deploy_response( migration_history.starknet_requests[0].response ) diff --git a/tests/integration/protostar_fixture.py b/tests/integration/protostar_fixture.py index b195880bcd..0c9db8cb9e 100644 --- a/tests/integration/protostar_fixture.py +++ b/tests/integration/protostar_fixture.py @@ -1,11 +1,15 @@ +from argparse import Namespace +from logging import getLogger from pathlib import Path +from typing import Dict, cast from pytest_mock import MockerFixture -from typing_extensions import Self -from protostar.commands.init.project_creator import ProjectCreator +from protostar.commands import BuildCommand, InitCommand, MigrateCommand +from protostar.commands.init.project_creator.new_project_creator import ( + NewProjectCreator, +) from protostar.compiler import ProjectCairoPathBuilder, ProjectCompiler -from protostar.compiler.project_compiler import ProjectCompilerConfig from protostar.migrator import Migrator, MigratorExecutionEnvironment from protostar.protostar_toml import ( ProtostarContractsSection, @@ -14,42 +18,84 @@ ProtostarTOMLWriter, ) from protostar.starknet_gateway import GatewayFacade -from protostar.utils import VersionManager +from protostar.utils.input_requester import InputRequester +from protostar.utils.log_color_provider import LogColorProvider class ProtostarFixture: def __init__( self, - simple_project_creator: "SimpleProjectCreator", - project_compiler: ProjectCompiler, - migrator_builder: Migrator.Builder, + project_root_path: Path, + init_command: InitCommand, + build_command: BuildCommand, + migrator_command: MigrateCommand, ) -> None: - self._simple_project_creator = simple_project_creator - self._project_compiler = project_compiler - self._migrator_builder = migrator_builder - - async def init(self) -> Self: - self._simple_project_creator.run() - return self - - async def build(self, output_dir: Path) -> Self: - self._project_compiler.compile_project( - output_dir=output_dir, - config=ProjectCompilerConfig( - hint_validation_disabled=False, - relative_cairo_path=[], - ), + self._project_root_path = project_root_path + self._init_command = init_command + self._build_command = build_command + self._migrator_command = migrator_command + + async def init(self): + args = Namespace() + args.existing = False + return await self._init_command.run(args) + + async def build(self): + args = Namespace() + args.output = Path("./build") + args.disable_hint_validation = False + args.cairo_path = None + return await self._build_command.run(args) + + async def migrate(self, path: Path, network: str, rollback=False): + args = Namespace() + args.path = path + args.output_dir = None + args.rollback = rollback + args.no_confirm = True + args.network = None + args.gateway_url = network + migration_history = await self._migrator_command.run(args) + assert migration_history is not None + return migration_history + + def create_files(self, relative_path_str_to_content: Dict[str, str]) -> None: + for relative_path_str, content in relative_path_str_to_content.items(): + self._save_file(self._project_root_path / relative_path_str, content) + + def create_migration(self, content: str) -> Path: + file_path = self._project_root_path / "migrations" / "migration_01_test.cairo" + self._save_file( + file_path, + f""" + %lang starknet + + @external + func up(): + %{{ + {content} + %}} + + return () + end + """, ) - return self + return file_path - async def migrate(self, filepath: Path, rollback=False) -> Self: - migrator = await self._migrator_builder.build(filepath) - await migrator.run(rollback) - return self + @staticmethod + def _save_file(path: Path, content: str) -> None: + path.parent.mkdir(exist_ok=True, parents=True) + with open( + path, + mode="w", + encoding="utf-8", + ) as output_file: + output_file.write(content) # pylint: disable=too-many-locals -def build_protostar_fixture(project_root_path: Path, mocker: MockerFixture): +def build_protostar_fixture(mocker: MockerFixture, project_root_path: Path): + version_manager = mocker.MagicMock() version_manager.protostar_version = mocker.MagicMock() version_manager.protostar_version = "99.9.9" @@ -76,39 +122,64 @@ def build_protostar_fixture(project_root_path: Path, mocker: MockerFixture): gateway_facade_builder=GatewayFacade.Builder(project_root_path), ) - simple_project_creator = SimpleProjectCreator( - project_root_path, - Path(__file__).parent / ".." / "..", - protostar_toml_writer, - version_manager, + input_requester = cast(InputRequester, mocker.MagicMock()) + + def request_input(message: str) -> str: + if message.startswith("project directory name"): + return project_root_path.name + if message.startswith("libraries directory name"): + return "lib" + return "" + + input_requester.request_input = request_input + + new_project_creator = NewProjectCreator( + script_root=Path(__file__).parent / ".." / "..", + requester=input_requester, + protostar_toml_writer=protostar_toml_writer, + version_manager=version_manager, + output_dir_path=project_root_path.parent, ) - ProtostarFixture( - project_compiler=project_compiler, - migrator_builder=migrator_builder, - simple_project_creator=simple_project_creator, + init_command = InitCommand( + input_requester, + new_project_creator=new_project_creator, + adapted_project_creator=mocker.MagicMock(), ) + project_compiler = ProjectCompiler( + project_root_path=project_root_path, + project_cairo_path_builder=project_cairo_path_builder, + contracts_section_loader=ProtostarContractsSection.Loader( + protostar_toml_reader + ), + ) -class SimpleProjectCreator(ProjectCreator): - def __init__( - self, - project_root_path: Path, - script_root: Path, - protostar_toml_writer: ProtostarTOMLWriter, - version_manager: VersionManager, - ): - super().__init__( - script_root, - protostar_toml_writer, - version_manager, - ) - self._project_root_path = project_root_path + logger = getLogger() + build_command = BuildCommand(logger=logger, project_compiler=project_compiler) - def run(self): - self.copy_template("default", self._project_root_path) - self.save_protostar_toml(self._project_root_path, Path("./lib")) - self._create_libs_dir() + log_color_provider = LogColorProvider() + log_color_provider.is_ci_mode = True + + gateway_facade_builder = GatewayFacade.Builder(project_root_path=project_root_path) + + migrator_builder = Migrator.Builder( + gateway_facade_builder=gateway_facade_builder, + migrator_execution_environment_builder=MigratorExecutionEnvironment.Builder(), + ) + + migrate_command = MigrateCommand( + migrator_builder=migrator_builder, + log_color_provider=log_color_provider, + logger=logger, + requester=input_requester, + ) + + protostar_fixture = ProtostarFixture( + project_root_path=project_root_path, + init_command=init_command, + build_command=build_command, + migrator_command=migrate_command, + ) - def _create_libs_dir(self) -> None: - (self._project_root_path / "lib").mkdir(exist_ok=True, parents=True) + return protostar_fixture From 3d64e05d7ad123006597dc89f1b105fa6ad23616 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Thu, 11 Aug 2022 21:03:09 +0200 Subject: [PATCH 20/49] use protostar fixture for declare cheatcode --- .../data/migrations/migration_declare.cairo | 8 --- .../migration_declare_file_not_found.cairo | 8 --- .../migrator_declare_cheatcode_test.py | 53 ++++++++++++++----- tests/integration/protostar_fixture.py | 4 +- 4 files changed, 41 insertions(+), 32 deletions(-) delete mode 100644 tests/integration/migrator/data/migrations/migration_declare.cairo delete mode 100644 tests/integration/migrator/data/migrations/migration_declare_file_not_found.cairo diff --git a/tests/integration/migrator/data/migrations/migration_declare.cairo b/tests/integration/migrator/data/migrations/migration_declare.cairo deleted file mode 100644 index b37e2eb9ce..0000000000 --- a/tests/integration/migrator/data/migrations/migration_declare.cairo +++ /dev/null @@ -1,8 +0,0 @@ -%lang starknet - -@external -func up(): - %{ declare("./build/main_with_constructor.json") %} - - return () -end diff --git a/tests/integration/migrator/data/migrations/migration_declare_file_not_found.cairo b/tests/integration/migrator/data/migrations/migration_declare_file_not_found.cairo deleted file mode 100644 index 74cd81cfd0..0000000000 --- a/tests/integration/migrator/data/migrations/migration_declare_file_not_found.cairo +++ /dev/null @@ -1,8 +0,0 @@ -%lang starknet - -@external -func up(): - %{ declare("./NOT_EXISTING_FILE.json") %} - - return () -end diff --git a/tests/integration/migrator/migrator_declare_cheatcode_test.py b/tests/integration/migrator/migrator_declare_cheatcode_test.py index d290c475cd..145fa0d0ef 100644 --- a/tests/integration/migrator/migrator_declare_cheatcode_test.py +++ b/tests/integration/migrator/migrator_declare_cheatcode_test.py @@ -1,28 +1,52 @@ +import asyncio import re from pathlib import Path from typing import cast import pytest -from protostar.commands.test.test_environment_exceptions import CheatcodeException -from protostar.migrator import Migrator +from protostar.protostar_exception import ProtostarException from tests.integration.migrator.conftest import assert_transaction_accepted +from tests.integration.protostar_fixture import ProtostarFixture -async def test_declare_contract( - migrator_builder: Migrator.Builder, devnet_gateway_url: str, project_root_path: Path -): +@pytest.fixture(scope="module") +def event_loop(): + return asyncio.get_event_loop() + + +@pytest.fixture(autouse=True, scope="module") +# pylint: disable=unused-argument +async def setup(protostar: ProtostarFixture): + await protostar.init() + protostar.create_files( + { + "./src/main.json": """ + %lang starknet - migrator = await migrator_builder.build( - project_root_path / "migrations" / "migration_declare.cairo", + @view + func identity(arg) -> (res : felt): + return (arg) + end + """ + } ) + await protostar.build() + + +async def test_declare_contract( + protostar: ProtostarFixture, + devnet_gateway_url: str, + protostar_project_root_path: Path, +): + migration_file_path = protostar.create_migration('declare("./build/main.json")') - result = await migrator.run() + result = await protostar.migrate(migration_file_path, devnet_gateway_url) assert len(result.starknet_requests) == 1 assert result.starknet_requests[0].action == "DECLARE" assert result.starknet_requests[0].payload["contract"] == str( - (project_root_path / "build" / "main_with_constructor.json").resolve() + (protostar_project_root_path / "build" / "main.json").resolve() ) assert result.starknet_requests[0].response["code"] == "TRANSACTION_RECEIVED" transaction_hash = cast( @@ -32,16 +56,17 @@ async def test_declare_contract( async def test_descriptive_error_on_file_not_found( - migrator_builder: Migrator.Builder, project_root_path: Path + protostar: ProtostarFixture, + devnet_gateway_url: str, ): - migrator = await migrator_builder.build( - project_root_path / "migrations" / "migration_declare_file_not_found.cairo", + migration_file_path = protostar.create_migration( + 'declare("./NOT_EXISTING_FILE.json")' ) with pytest.raises( - CheatcodeException, + ProtostarException, match=re.compile( "Couldn't find `.*/NOT_EXISTING_FILE.json`", ), ): - await migrator.run() + await protostar.migrate(migration_file_path, network=devnet_gateway_url) diff --git a/tests/integration/protostar_fixture.py b/tests/integration/protostar_fixture.py index 0c9db8cb9e..ffa7e54350 100644 --- a/tests/integration/protostar_fixture.py +++ b/tests/integration/protostar_fixture.py @@ -63,7 +63,7 @@ def create_files(self, relative_path_str_to_content: Dict[str, str]) -> None: for relative_path_str, content in relative_path_str_to_content.items(): self._save_file(self._project_root_path / relative_path_str, content) - def create_migration(self, content: str) -> Path: + def create_migration(self, hint_content: str) -> Path: file_path = self._project_root_path / "migrations" / "migration_01_test.cairo" self._save_file( file_path, @@ -73,7 +73,7 @@ def create_migration(self, content: str) -> Path: @external func up(): %{{ - {content} + {hint_content} %}} return () From 2a442423cf52b79edb45e320c30e75634aef9ae3 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Thu, 11 Aug 2022 21:18:02 +0200 Subject: [PATCH 21/49] use protostar fixture in gateway facade --- .../gateway/gateway_facade_test.py | 34 ++++++++++--------- tests/integration/protostar_fixture.py | 17 ++++++---- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py index 6feb11d385..470b652b54 100644 --- a/tests/integration/gateway/gateway_facade_test.py +++ b/tests/integration/gateway/gateway_facade_test.py @@ -5,12 +5,28 @@ from protostar.starknet_gateway.gateway_facade import GatewayFacade from protostar.utils.log_color_provider import LogColorProvider +from tests.integration.protostar_fixture import ProtostarFixture @pytest.fixture(autouse=True, scope="module") # pylint: disable=unused-argument -def testing_environment(standard_project, compiled_project): - pass +def setup(protostar: ProtostarFixture): + protostar.init() + protostar.build() + + +@pytest.fixture(name="compiled_contract_path") +def compiled_contract_path_fixture(protostar: ProtostarFixture) -> Path: + return protostar.project_root_path / "build" / "main.json" + + +@pytest.fixture(name="gateway_facade") +def gateway_facade_fixture(devnet_gateway_url: str): + log_color_provider = LogColorProvider() + log_color_provider.is_ci_mode = False + gateway_facade_builder = GatewayFacade.Builder(project_root_path=Path()) + gateway_facade_builder.set_network(devnet_gateway_url) + return gateway_facade_builder.build() async def test_deploy(gateway_facade: GatewayFacade, compiled_contract_path: Path): @@ -84,17 +100,3 @@ async def test_call_to_with_incorrect_args( function_name="get_balance", inputs={"UNKNOWN_ARG": 42}, ) - - -@pytest.fixture(name="gateway_facade") -def gateway_facade_fixture(devnet_gateway_url: str): - log_color_provider = LogColorProvider() - log_color_provider.is_ci_mode = False - gateway_facade_builder = GatewayFacade.Builder(project_root_path=Path()) - gateway_facade_builder.set_network(devnet_gateway_url) - return gateway_facade_builder.build() - - -@pytest.fixture(name="compiled_contract_path") -def compiled_contract_path_fixture(project_compilation_output_path: Path) -> Path: - return project_compilation_output_path / "main.json" diff --git a/tests/integration/protostar_fixture.py b/tests/integration/protostar_fixture.py index ffa7e54350..f344a9978c 100644 --- a/tests/integration/protostar_fixture.py +++ b/tests/integration/protostar_fixture.py @@ -1,3 +1,4 @@ +import asyncio from argparse import Namespace from logging import getLogger from pathlib import Path @@ -35,19 +36,23 @@ def __init__( self._build_command = build_command self._migrator_command = migrator_command - async def init(self): + @property + def project_root_path(self) -> Path: + return self._project_root_path + + def init(self): args = Namespace() args.existing = False - return await self._init_command.run(args) + return asyncio.run(self._init_command.run(args)) - async def build(self): + def build(self): args = Namespace() args.output = Path("./build") args.disable_hint_validation = False args.cairo_path = None - return await self._build_command.run(args) + return asyncio.run(self._build_command.run(args)) - async def migrate(self, path: Path, network: str, rollback=False): + def migrate(self, path: Path, network: str, rollback=False): args = Namespace() args.path = path args.output_dir = None @@ -55,7 +60,7 @@ async def migrate(self, path: Path, network: str, rollback=False): args.no_confirm = True args.network = None args.gateway_url = network - migration_history = await self._migrator_command.run(args) + migration_history = asyncio.run(self._migrator_command.run(args)) assert migration_history is not None return migration_history From 678db3ca882b6f9b63c30d8c70a8432fe49d7976 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Thu, 11 Aug 2022 21:21:15 +0200 Subject: [PATCH 22/49] remove asyncs --- .../migrator/migrator_call_cheatcode_test.py | 18 +++++------------- .../migrator_declare_cheatcode_test.py | 19 ++++++------------- 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/tests/integration/migrator/migrator_call_cheatcode_test.py b/tests/integration/migrator/migrator_call_cheatcode_test.py index 90607b4e83..a8e6b26fda 100644 --- a/tests/integration/migrator/migrator_call_cheatcode_test.py +++ b/tests/integration/migrator/migrator_call_cheatcode_test.py @@ -1,20 +1,12 @@ -import asyncio - import pytest from protostar.starknet_gateway.starknet_request import StarknetRequest from tests.integration.protostar_fixture import ProtostarFixture -@pytest.fixture(scope="module") -def event_loop(): - return asyncio.get_event_loop() - - @pytest.fixture(autouse=True, scope="module") -# pylint: disable=unused-argument -async def setup(protostar: ProtostarFixture): - await protostar.init() +def setup(protostar: ProtostarFixture): + protostar.init() protostar.create_files( { "./src/main.json": """ @@ -27,10 +19,10 @@ async def setup(protostar: ProtostarFixture): """ } ) - await protostar.build() + protostar.build() -async def test_call_contract(protostar: ProtostarFixture, devnet_gateway_url: str): +def test_call_contract(protostar: ProtostarFixture, devnet_gateway_url: str): file_path = protostar.create_migration( """ contract_address = deploy_contract("./build/main.json").contract_address @@ -38,7 +30,7 @@ async def test_call_contract(protostar: ProtostarFixture, devnet_gateway_url: st """ ) - migration_history = await protostar.migrate(file_path, network=devnet_gateway_url) + migration_history = protostar.migrate(file_path, network=devnet_gateway_url) contract_address = extract_contract_address_from_deploy_response( migration_history.starknet_requests[0].response diff --git a/tests/integration/migrator/migrator_declare_cheatcode_test.py b/tests/integration/migrator/migrator_declare_cheatcode_test.py index 145fa0d0ef..7b9058a3f9 100644 --- a/tests/integration/migrator/migrator_declare_cheatcode_test.py +++ b/tests/integration/migrator/migrator_declare_cheatcode_test.py @@ -1,4 +1,3 @@ -import asyncio import re from pathlib import Path from typing import cast @@ -10,15 +9,9 @@ from tests.integration.protostar_fixture import ProtostarFixture -@pytest.fixture(scope="module") -def event_loop(): - return asyncio.get_event_loop() - - @pytest.fixture(autouse=True, scope="module") -# pylint: disable=unused-argument -async def setup(protostar: ProtostarFixture): - await protostar.init() +def setup(protostar: ProtostarFixture): + protostar.init() protostar.create_files( { "./src/main.json": """ @@ -31,7 +24,7 @@ async def setup(protostar: ProtostarFixture): """ } ) - await protostar.build() + protostar.build() async def test_declare_contract( @@ -41,7 +34,7 @@ async def test_declare_contract( ): migration_file_path = protostar.create_migration('declare("./build/main.json")') - result = await protostar.migrate(migration_file_path, devnet_gateway_url) + result = protostar.migrate(migration_file_path, devnet_gateway_url) assert len(result.starknet_requests) == 1 assert result.starknet_requests[0].action == "DECLARE" @@ -55,7 +48,7 @@ async def test_declare_contract( await assert_transaction_accepted(devnet_gateway_url, transaction_hash) -async def test_descriptive_error_on_file_not_found( +def test_descriptive_error_on_file_not_found( protostar: ProtostarFixture, devnet_gateway_url: str, ): @@ -69,4 +62,4 @@ async def test_descriptive_error_on_file_not_found( "Couldn't find `.*/NOT_EXISTING_FILE.json`", ), ): - await protostar.migrate(migration_file_path, network=devnet_gateway_url) + protostar.migrate(migration_file_path, network=devnet_gateway_url) From 2521c0a98815f6329721afe4fe458b0fd67dfe8d Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Thu, 11 Aug 2022 21:23:59 +0200 Subject: [PATCH 23/49] remove dead code --- .../_conftest/standard_project_fixture.py | 61 -------------- tests/integration/conftest.py | 81 +------------------ 2 files changed, 1 insertion(+), 141 deletions(-) delete mode 100644 tests/integration/_conftest/standard_project_fixture.py diff --git a/tests/integration/_conftest/standard_project_fixture.py b/tests/integration/_conftest/standard_project_fixture.py deleted file mode 100644 index 8736b5eec0..0000000000 --- a/tests/integration/_conftest/standard_project_fixture.py +++ /dev/null @@ -1,61 +0,0 @@ -from pathlib import Path -from unittest.mock import MagicMock - -import pytest - -from protostar.commands.init.project_creator import ProjectCreator -from protostar.protostar_toml.io.protostar_toml_writer import ProtostarTOMLWriter -from protostar.utils.protostar_directory import VersionManager - - -class SimpleProjectCreator(ProjectCreator): - def __init__( - self, - project_root_path: Path, - script_root: Path, - protostar_toml_writer: ProtostarTOMLWriter, - version_manager: VersionManager, - ): - super().__init__( - script_root, - protostar_toml_writer, - version_manager, - ) - self._project_root_path = project_root_path - - def run(self): - self.copy_template("default", self._project_root_path) - self.save_protostar_toml(self._project_root_path, Path("./lib")) - self._create_libs_dir() - - def _create_libs_dir(self) -> None: - (self._project_root_path / "lib").mkdir(exist_ok=True, parents=True) - - -@pytest.fixture(name="project_root_path", scope="module") -def project_root_path_fixture(tmp_path_factory) -> Path: - tmp_path = tmp_path_factory.mktemp("data") - return tmp_path / "default_project" - - -@pytest.fixture(name="version_manager", scope="module") -def version_manager_fixture(module_mocker: MagicMock) -> VersionManager: - version_manager = module_mocker.MagicMock() - version_manager.protostar_version = module_mocker.MagicMock() - version_manager.protostar_version = "99.9.9" - return version_manager - - -STANDARD_PROJECT_FIXTURE = "standard_project" - - -@pytest.fixture(name=STANDARD_PROJECT_FIXTURE, scope="module") -def standard_project_fixture(project_root_path: Path, version_manager: VersionManager): - protostar_toml_writer = ProtostarTOMLWriter() - project_creator = SimpleProjectCreator( - project_root_path=project_root_path, - protostar_toml_writer=protostar_toml_writer, - script_root=Path(__file__).parent / ".." / ".." / "..", - version_manager=version_manager, - ) - project_creator.run() diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index b75771de5c..54c7a8a7e0 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -1,8 +1,7 @@ # pylint: disable=invalid-name from dataclasses import dataclass -from os import listdir from pathlib import Path -from typing import Dict, List, Optional, Set, Union +from typing import List, Optional, Set, Union from unittest.mock import MagicMock import pytest @@ -11,21 +10,7 @@ from protostar.commands.test.test_command import TestCommand from protostar.commands.test.testing_summary import TestingSummary -from protostar.compiler.project_cairo_path_builder import ProjectCairoPathBuilder -from protostar.compiler.project_compiler import ProjectCompiler, ProjectCompilerConfig -from protostar.protostar_toml.io.protostar_toml_reader import ProtostarTOMLReader -from protostar.protostar_toml.protostar_contracts_section import ( - ProtostarContractsSection, -) -from protostar.protostar_toml.protostar_project_section import ProtostarProjectSection from tests.conftest import run_devnet - -# pylint: disable=unused-import -from tests.integration._conftest.standard_project_fixture import ( - project_root_path_fixture, - standard_project_fixture, - version_manager_fixture, -) from tests.integration.protostar_fixture import ( ProtostarFixture, build_protostar_fixture, @@ -124,70 +109,6 @@ async def run_cairo_test_runner( return run_cairo_test_runner -@pytest.fixture(name="project_compilation_output_path", scope="module") -def project_compilation_output_path_fixture(project_root_path: Path): - output_path = project_root_path / "build" - output_path.mkdir(exist_ok=True) - return output_path - - -COMPILED_PROJECT_FIXTURE = "compiled_project" - - -class CompileProjectFixture(Protocol): - def __call__(self, str_path_to_content: Dict[str, str]) -> None: - ... - - -@pytest.fixture(name="compile_project", scope="module") -def compile_project_fixture(project_root_path: Path) -> CompileProjectFixture: - def compile_project(str_path_to_content: Dict[str, str]): - for relative_str_path, content in str_path_to_content.items(): - save_file(project_root_path / relative_str_path, content) - - return compile_project - - -def save_file(path: Path, content: str): - with open( - path, - mode="w", - encoding="utf-8", - ) as output_file: - output_file.write(content) - - -@pytest.fixture(name=COMPILED_PROJECT_FIXTURE, scope="module") -def compiled_project_fixture( - project_root_path: Path, project_compilation_output_path: Path -): - protostar_toml_reader = ProtostarTOMLReader( - protostar_toml_path=project_root_path / "protostar.toml" - ) - project_compiler = ProjectCompiler( - project_root_path=project_root_path, - contracts_section_loader=ProtostarContractsSection.Loader( - protostar_toml_reader=protostar_toml_reader - ), - project_cairo_path_builder=ProjectCairoPathBuilder( - project_root_path, - project_section_loader=ProtostarProjectSection.Loader( - protostar_toml_reader - ), - ), - ) - project_compiler.compile_project( - output_dir=project_compilation_output_path, - config=ProjectCompilerConfig( - debugging_info_attached=True, - hint_validation_disabled=True, - relative_cairo_path=[], - ), - ) - output_files_count = len(listdir(project_compilation_output_path)) - assert output_files_count > 0, "Project didn't compile" - - @pytest.fixture(name="protostar_project_root_path", scope="module") def protostar_project_root_path_fixture(tmp_path_factory) -> Path: tmp_path = tmp_path_factory.mktemp("data") From 42ddd280c8c117e5db15bb5cf0cda3f9ec2ea368 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Thu, 11 Aug 2022 22:00:21 +0200 Subject: [PATCH 24/49] use protostar fixture --- tests/integration/migrator/conftest.py | 8 ------- .../migrator/migrator_call_cheatcode_test.py | 6 ++--- .../migrator_declare_cheatcode_test.py | 24 ++++++------------- tests/integration/protostar_fixture.py | 6 ++--- 4 files changed, 13 insertions(+), 31 deletions(-) diff --git a/tests/integration/migrator/conftest.py b/tests/integration/migrator/conftest.py index ffcef5656f..0f2ed9e619 100644 --- a/tests/integration/migrator/conftest.py +++ b/tests/integration/migrator/conftest.py @@ -39,11 +39,3 @@ async def assert_transaction_accepted( transaction_hash, wait_for_accept=True ) assert transaction_status == TransactionStatus.ACCEPTED_ON_L2 - - -MigrationFileName = Literal[ - "migration_declare_file_not_found.cairo", - "migration_declare.cairo", - "migration_deploy_contract.cairo", - "migration_down.cairo", -] diff --git a/tests/integration/migrator/migrator_call_cheatcode_test.py b/tests/integration/migrator/migrator_call_cheatcode_test.py index a8e6b26fda..8433fb927c 100644 --- a/tests/integration/migrator/migrator_call_cheatcode_test.py +++ b/tests/integration/migrator/migrator_call_cheatcode_test.py @@ -22,15 +22,15 @@ def setup(protostar: ProtostarFixture): protostar.build() -def test_call_contract(protostar: ProtostarFixture, devnet_gateway_url: str): - file_path = protostar.create_migration( +async def test_call_contract(protostar: ProtostarFixture, devnet_gateway_url: str): + file_path = protostar.create_migration_file( """ contract_address = deploy_contract("./build/main.json").contract_address call(contract_address, "identity", [42]) """ ) - migration_history = protostar.migrate(file_path, network=devnet_gateway_url) + migration_history = await protostar.migrate(file_path, network=devnet_gateway_url) contract_address = extract_contract_address_from_deploy_response( migration_history.starknet_requests[0].response diff --git a/tests/integration/migrator/migrator_declare_cheatcode_test.py b/tests/integration/migrator/migrator_declare_cheatcode_test.py index 7b9058a3f9..0af7114354 100644 --- a/tests/integration/migrator/migrator_declare_cheatcode_test.py +++ b/tests/integration/migrator/migrator_declare_cheatcode_test.py @@ -12,18 +12,6 @@ @pytest.fixture(autouse=True, scope="module") def setup(protostar: ProtostarFixture): protostar.init() - protostar.create_files( - { - "./src/main.json": """ - %lang starknet - - @view - func identity(arg) -> (res : felt): - return (arg) - end - """ - } - ) protostar.build() @@ -32,9 +20,11 @@ async def test_declare_contract( devnet_gateway_url: str, protostar_project_root_path: Path, ): - migration_file_path = protostar.create_migration('declare("./build/main.json")') + migration_file_path = protostar.create_migration_file( + 'declare("./build/main.json")' + ) - result = protostar.migrate(migration_file_path, devnet_gateway_url) + result = await protostar.migrate(migration_file_path, devnet_gateway_url) assert len(result.starknet_requests) == 1 assert result.starknet_requests[0].action == "DECLARE" @@ -48,11 +38,11 @@ async def test_declare_contract( await assert_transaction_accepted(devnet_gateway_url, transaction_hash) -def test_descriptive_error_on_file_not_found( +async def test_descriptive_error_on_file_not_found( protostar: ProtostarFixture, devnet_gateway_url: str, ): - migration_file_path = protostar.create_migration( + migration_file_path = protostar.create_migration_file( 'declare("./NOT_EXISTING_FILE.json")' ) @@ -62,4 +52,4 @@ def test_descriptive_error_on_file_not_found( "Couldn't find `.*/NOT_EXISTING_FILE.json`", ), ): - protostar.migrate(migration_file_path, network=devnet_gateway_url) + await protostar.migrate(migration_file_path, network=devnet_gateway_url) diff --git a/tests/integration/protostar_fixture.py b/tests/integration/protostar_fixture.py index f344a9978c..9016ab14db 100644 --- a/tests/integration/protostar_fixture.py +++ b/tests/integration/protostar_fixture.py @@ -52,7 +52,7 @@ def build(self): args.cairo_path = None return asyncio.run(self._build_command.run(args)) - def migrate(self, path: Path, network: str, rollback=False): + async def migrate(self, path: Path, network: str, rollback=False): args = Namespace() args.path = path args.output_dir = None @@ -60,7 +60,7 @@ def migrate(self, path: Path, network: str, rollback=False): args.no_confirm = True args.network = None args.gateway_url = network - migration_history = asyncio.run(self._migrator_command.run(args)) + migration_history = await self._migrator_command.run(args) assert migration_history is not None return migration_history @@ -68,7 +68,7 @@ def create_files(self, relative_path_str_to_content: Dict[str, str]) -> None: for relative_path_str, content in relative_path_str_to_content.items(): self._save_file(self._project_root_path / relative_path_str, content) - def create_migration(self, hint_content: str) -> Path: + def create_migration_file(self, hint_content: str) -> Path: file_path = self._project_root_path / "migrations" / "migration_01_test.cairo" self._save_file( file_path, From cf6d536b3d5f653177dee7a4009925e2efe11f15 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Thu, 11 Aug 2022 22:09:23 +0200 Subject: [PATCH 25/49] make call pass --- protostar/starknet_gateway/gateway_facade.py | 9 +++++++++ protostar/starknet_gateway/starknet_request.py | 2 +- .../integration/migrator/migrator_call_cheatcode_test.py | 8 ++++---- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/protostar/starknet_gateway/gateway_facade.py b/protostar/starknet_gateway/gateway_facade.py index 818b8702a5..17bb738916 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -189,6 +189,14 @@ async def call( function_name: str, inputs: Optional[Union[List[int], Dict[str, Any]]] = None, ) -> NamedTuple: + register_response = self._register_request( + action="CALL", + payload={ + "contract_address": address, + "function_name": function_name, + "inputs": str(inputs), + }, + ) if inputs is None: inputs = {} contract = await Contract.from_address( @@ -199,6 +207,7 @@ async def call( result = await contract_function.call(*inputs) else: result = await contract_function.call(**inputs) + register_response({"response": str(result._asdict())}) return result async def invoke( diff --git a/protostar/starknet_gateway/starknet_request.py b/protostar/starknet_gateway/starknet_request.py index 37ad489e17..537acec196 100644 --- a/protostar/starknet_gateway/starknet_request.py +++ b/protostar/starknet_gateway/starknet_request.py @@ -8,7 +8,7 @@ @dataclass class StarknetRequest: - Action = Literal["DEPLOY", "DECLARE"] + Action = Literal["DEPLOY", "DECLARE", "CALL"] Payload = Dict[str, Union[None, str, int, List[int], List[str]]] action: Action diff --git a/tests/integration/migrator/migrator_call_cheatcode_test.py b/tests/integration/migrator/migrator_call_cheatcode_test.py index 8433fb927c..595bc32e33 100644 --- a/tests/integration/migrator/migrator_call_cheatcode_test.py +++ b/tests/integration/migrator/migrator_call_cheatcode_test.py @@ -9,7 +9,7 @@ def setup(protostar: ProtostarFixture): protostar.init() protostar.create_files( { - "./src/main.json": """ + "./src/main.cairo": """ %lang starknet @view @@ -37,9 +37,9 @@ async def test_call_contract(protostar: ProtostarFixture, devnet_gateway_url: st ) call_request = migration_history.starknet_requests[1] assert call_request.action == "CALL" - assert call_request.payload["inputs"] == "[]" - assert call_request.payload["contract_address"] == str(contract_address) - assert call_request.response["response"] == "42" + assert call_request.payload["inputs"] == "[42]" + assert call_request.payload["contract_address"] == contract_address + assert call_request.response["response"] == "{'res': 42}" def extract_contract_address_from_deploy_response( From 4dcebf27161c24f5c3f810df2fc8f1cf082c4ee4 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Fri, 12 Aug 2022 10:05:16 +0200 Subject: [PATCH 26/49] move contract to tests.data --- tests/data/contracts.py | 8 ++++++++ .../integration/gateway/gateway_facade_test.py | 4 ++-- .../migrator/migrator_call_cheatcode_test.py | 18 ++++-------------- .../migrator_declare_cheatcode_test.py | 4 ++-- tests/integration/protostar_fixture.py | 4 ++-- 5 files changed, 18 insertions(+), 20 deletions(-) create mode 100644 tests/data/contracts.py diff --git a/tests/data/contracts.py b/tests/data/contracts.py new file mode 100644 index 0000000000..429c7f53f4 --- /dev/null +++ b/tests/data/contracts.py @@ -0,0 +1,8 @@ +IDENTITY_CONTRACT = """ + %lang starknet + + @view + func identity(arg) -> (res : felt): + return (arg) + end + """ diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py index 470b652b54..fdb70b0697 100644 --- a/tests/integration/gateway/gateway_facade_test.py +++ b/tests/integration/gateway/gateway_facade_test.py @@ -11,8 +11,8 @@ @pytest.fixture(autouse=True, scope="module") # pylint: disable=unused-argument def setup(protostar: ProtostarFixture): - protostar.init() - protostar.build() + protostar.init_sync() + protostar.build_sync() @pytest.fixture(name="compiled_contract_path") diff --git a/tests/integration/migrator/migrator_call_cheatcode_test.py b/tests/integration/migrator/migrator_call_cheatcode_test.py index 595bc32e33..5ed93d503d 100644 --- a/tests/integration/migrator/migrator_call_cheatcode_test.py +++ b/tests/integration/migrator/migrator_call_cheatcode_test.py @@ -1,25 +1,15 @@ import pytest from protostar.starknet_gateway.starknet_request import StarknetRequest +from tests.data.contracts import IDENTITY_CONTRACT from tests.integration.protostar_fixture import ProtostarFixture @pytest.fixture(autouse=True, scope="module") def setup(protostar: ProtostarFixture): - protostar.init() - protostar.create_files( - { - "./src/main.cairo": """ - %lang starknet - - @view - func identity(arg) -> (res : felt): - return (arg) - end - """ - } - ) - protostar.build() + protostar.init_sync() + protostar.create_files({"./src/main.cairo": IDENTITY_CONTRACT}) + protostar.build_sync() async def test_call_contract(protostar: ProtostarFixture, devnet_gateway_url: str): diff --git a/tests/integration/migrator/migrator_declare_cheatcode_test.py b/tests/integration/migrator/migrator_declare_cheatcode_test.py index 0af7114354..fbc8843979 100644 --- a/tests/integration/migrator/migrator_declare_cheatcode_test.py +++ b/tests/integration/migrator/migrator_declare_cheatcode_test.py @@ -11,8 +11,8 @@ @pytest.fixture(autouse=True, scope="module") def setup(protostar: ProtostarFixture): - protostar.init() - protostar.build() + protostar.init_sync() + protostar.build_sync() async def test_declare_contract( diff --git a/tests/integration/protostar_fixture.py b/tests/integration/protostar_fixture.py index 9016ab14db..58b6cb099f 100644 --- a/tests/integration/protostar_fixture.py +++ b/tests/integration/protostar_fixture.py @@ -40,12 +40,12 @@ def __init__( def project_root_path(self) -> Path: return self._project_root_path - def init(self): + def init_sync(self): args = Namespace() args.existing = False return asyncio.run(self._init_command.run(args)) - def build(self): + def build_sync(self): args = Namespace() args.output = Path("./build") args.disable_hint_validation = False From eb8629431ba2e9527e926c2d1221d6901ca0eedd Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Fri, 12 Aug 2022 12:14:06 +0200 Subject: [PATCH 27/49] fix creating migration output file --- .../project_creator/new_project_creator.py | 6 +-- protostar/commands/migrate/migrate_command.py | 2 +- protostar/composition_root.py | 1 + protostar/migrator/migrator.py | 18 +++++--- protostar/migrator/migrator_test.py | 2 +- .../migrator/migrator_call_cheatcode_test.py | 42 +++++++++++++++---- tests/integration/protostar_fixture.py | 18 ++++---- 7 files changed, 64 insertions(+), 25 deletions(-) diff --git a/protostar/commands/init/project_creator/new_project_creator.py b/protostar/commands/init/project_creator/new_project_creator.py index 45b593747c..bd6f79c882 100644 --- a/protostar/commands/init/project_creator/new_project_creator.py +++ b/protostar/commands/init/project_creator/new_project_creator.py @@ -23,13 +23,13 @@ def __init__( requester: InputRequester, protostar_toml_writer: ProtostarTOMLWriter, version_manager: VersionManager, - output_dir_path: Optional[Path], + output_dir_path: Optional[Path] = None, ): super().__init__(script_root, protostar_toml_writer, version_manager) self._protostar_toml_writer = protostar_toml_writer self._version_manager = version_manager self._requester = requester - self._output_dir_path = output_dir_path + self._output_dir_path = output_dir_path or Path() def run(self): self._create_project(self._gather_input()) @@ -49,7 +49,7 @@ def _gather_input(self) -> "NewProjectCreator.UserInput": return NewProjectCreator.UserInput(project_dirname, lib_dirname) def _create_project(self, user_input: "NewProjectCreator.UserInput") -> None: - output_dir_path = self._output_dir_path or Path() + output_dir_path = self._output_dir_path project_root_path = output_dir_path / user_input.project_dirname self.copy_template("default", project_root_path) diff --git a/protostar/commands/migrate/migrate_command.py b/protostar/commands/migrate/migrate_command.py index 4503299566..22e0377ac6 100644 --- a/protostar/commands/migrate/migrate_command.py +++ b/protostar/commands/migrate/migrate_command.py @@ -114,7 +114,7 @@ async def migrate( migrator.save_history( migrator_history, migration_file_basename=Path(migration_file_path).stem, - output_dir_path=output_dir_path, + output_dir_relative_path=output_dir_path, ) self._logger.info("Migration completed") diff --git a/protostar/composition_root.py b/protostar/composition_root.py index 11c53c8ddc..505b2ce280 100644 --- a/protostar/composition_root.py +++ b/protostar/composition_root.py @@ -150,6 +150,7 @@ def build_di_container(script_root: Path, cwd: Path): migrator_builder=Migrator.Builder( migrator_execution_environment_builder=MigratorExecutionEnvironment.Builder(), gateway_facade_builder=GatewayFacade.Builder(project_root_path), + cwd=project_root_path, ), requester=requester, logger=logger, diff --git a/protostar/migrator/migrator.py b/protostar/migrator/migrator.py index d10b267a45..dc421aa6a7 100644 --- a/protostar/migrator/migrator.py +++ b/protostar/migrator/migrator.py @@ -9,7 +9,6 @@ from protostar.migrator.migrator_execution_environment import ( MigratorExecutionEnvironment, ) - from protostar.starknet_gateway.gateway_facade import GatewayFacade from protostar.starknet_gateway.starknet_request import StarknetRequest from protostar.utils.log_color_provider import LogColorProvider @@ -29,6 +28,7 @@ def __init__( self, migrator_execution_environment_builder: MigratorExecutionEnvironment.Builder, gateway_facade_builder: GatewayFacade.Builder, + cwd: Optional[Path] = None, ) -> None: self._migrator_execution_environment_builder = ( migrator_execution_environment_builder @@ -39,6 +39,7 @@ def __init__( self._migrator_execution_environment_config = ( MigratorExecutionEnvironment.Config() ) + self._cwd = cwd def set_logger( self, logger: Logger, log_color_provider: LogColorProvider @@ -72,12 +73,16 @@ async def build(self, migration_file_path: Path): ) ) - return Migrator(migrator_execution_environment=migrator_execution_env) + return Migrator( + migrator_execution_environment=migrator_execution_env, cwd=self._cwd + ) def __init__( self, migrator_execution_environment: MigratorExecutionEnvironment, + cwd: Optional[Path] = None, ) -> None: + self._cwd = cwd or Path() self._migrator_execution_environment = migrator_execution_environment async def run(self, rollback=False) -> History: @@ -90,16 +95,19 @@ async def run(self, rollback=False) -> History: starknet_requests=self._migrator_execution_environment.cheatcode_factory.gateway_facade.get_starknet_requests() ) - @staticmethod def save_history( + self, history: History, migration_file_basename: str, - output_dir_path: Path, + output_dir_relative_path: Path, ): + output_dir_path = self._cwd / output_dir_relative_path prefix = datetime.strftime(datetime.now(), "%Y%m%d%H%M%S") output_file_path = output_dir_path / f"{prefix}_{migration_file_basename}.json" if not output_dir_path.exists(): - output_dir_path.mkdir(parents=True) + output_dir_path.mkdir( + parents=True, + ) history.save_as_json(output_file_path) diff --git a/protostar/migrator/migrator_test.py b/protostar/migrator/migrator_test.py index 79e4b0e6ff..ceb1cc483d 100644 --- a/protostar/migrator/migrator_test.py +++ b/protostar/migrator/migrator_test.py @@ -18,7 +18,7 @@ def test_migrator_saves_result_successfully_with_proper_name(tmp_path: Path): ] ), migration_file_basename="01_init", - output_dir_path=tmp_path, + output_dir_relative_path=tmp_path, ) assert "20220402213742_01_init.json" in listdir(tmp_path) diff --git a/tests/integration/migrator/migrator_call_cheatcode_test.py b/tests/integration/migrator/migrator_call_cheatcode_test.py index 5ed93d503d..4e92805fd8 100644 --- a/tests/integration/migrator/migrator_call_cheatcode_test.py +++ b/tests/integration/migrator/migrator_call_cheatcode_test.py @@ -1,3 +1,8 @@ +import json +from os import listdir +from pathlib import Path +from typing import Dict + import pytest from protostar.starknet_gateway.starknet_request import StarknetRequest @@ -13,23 +18,46 @@ def setup(protostar: ProtostarFixture): async def test_call_contract(protostar: ProtostarFixture, devnet_gateway_url: str): - file_path = protostar.create_migration_file( + migration_file_path = protostar.create_migration_file( """ contract_address = deploy_contract("./build/main.json").contract_address call(contract_address, "identity", [42]) """ ) + migration_output_relative_path = Path("./migrations/output") + + migration_history = await protostar.migrate( + migration_file_path, + network=devnet_gateway_url, + output_dir=migration_output_relative_path, + ) - migration_history = await protostar.migrate(file_path, network=devnet_gateway_url) + loaded_migration_output = load_migration_history( + migration_output_path=protostar.project_root_path + / migration_output_relative_path + ) + assert loaded_migration_output is not None + output_file_content = str(loaded_migration_output) + assert "CALL" in output_file_content + assert "[42]" in output_file_content + assert "{'res': 42}" in output_file_content contract_address = extract_contract_address_from_deploy_response( migration_history.starknet_requests[0].response ) - call_request = migration_history.starknet_requests[1] - assert call_request.action == "CALL" - assert call_request.payload["inputs"] == "[42]" - assert call_request.payload["contract_address"] == contract_address - assert call_request.response["response"] == "{'res': 42}" + assert str(contract_address) in output_file_content + + +def load_migration_history(migration_output_path: Path) -> Dict: + migration_output_file_names = listdir(migration_output_path) + assert len(migration_output_file_names) == 1 + migration_output_file_path = migration_output_path / migration_output_file_names[0] + return load_json(migration_output_file_path) + + +def load_json(path: Path): + with open(path, "r", encoding="utf-8") as file: + return json.loads(file.read()) def extract_contract_address_from_deploy_response( diff --git a/tests/integration/protostar_fixture.py b/tests/integration/protostar_fixture.py index 58b6cb099f..da88b017c9 100644 --- a/tests/integration/protostar_fixture.py +++ b/tests/integration/protostar_fixture.py @@ -2,7 +2,7 @@ from argparse import Namespace from logging import getLogger from pathlib import Path -from typing import Dict, cast +from typing import Dict, Optional, cast from pytest_mock import MockerFixture @@ -52,10 +52,16 @@ def build_sync(self): args.cairo_path = None return asyncio.run(self._build_command.run(args)) - async def migrate(self, path: Path, network: str, rollback=False): + async def migrate( + self, + path: Path, + network: str, + rollback=False, + output_dir: Optional[Path] = None, + ): args = Namespace() args.path = path - args.output_dir = None + args.output_dir = output_dir args.rollback = rollback args.no_confirm = True args.network = None @@ -122,11 +128,6 @@ def build_protostar_fixture(mocker: MockerFixture, project_root_path: Path): ), ) - migrator_builder = Migrator.Builder( - migrator_execution_environment_builder=MigratorExecutionEnvironment.Builder(), - gateway_facade_builder=GatewayFacade.Builder(project_root_path), - ) - input_requester = cast(InputRequester, mocker.MagicMock()) def request_input(message: str) -> str: @@ -171,6 +172,7 @@ def request_input(message: str) -> str: migrator_builder = Migrator.Builder( gateway_facade_builder=gateway_facade_builder, migrator_execution_environment_builder=MigratorExecutionEnvironment.Builder(), + cwd=project_root_path, ) migrate_command = MigrateCommand( From 90dd036962f27fdcea149addde67cf008a31c129 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Fri, 12 Aug 2022 13:49:58 +0200 Subject: [PATCH 28/49] add more tests --- .../cheatcodes/migrator_call_cheatcode.py | 22 ++++--- protostar/starknet_gateway/__init__.py | 5 +- protostar/starknet_gateway/gateway_facade.py | 18 ++++-- .../gateway/gateway_facade_test.py | 13 ++++ .../migrator/migrator_call_cheatcode_test.py | 62 +++++++++++++++++-- 5 files changed, 103 insertions(+), 17 deletions(-) diff --git a/protostar/migrator/cheatcodes/migrator_call_cheatcode.py b/protostar/migrator/cheatcodes/migrator_call_cheatcode.py index 3b0ff2d337..0a2da53193 100644 --- a/protostar/migrator/cheatcodes/migrator_call_cheatcode.py +++ b/protostar/migrator/cheatcodes/migrator_call_cheatcode.py @@ -3,8 +3,10 @@ from typing_extensions import Protocol +from protostar.commands.test.test_environment_exceptions import \ + CheatcodeException from protostar.starknet.cheatcode import Cheatcode -from protostar.starknet_gateway import GatewayFacade +from protostar.starknet_gateway import GatewayFacade, UnknownFunctionException from protostar.utils.data_transformer import CairoOrPythonData @@ -40,10 +42,16 @@ def call( function_name: str, inputs: Optional[CairoOrPythonData] = None, ): - return asyncio.run( - self._gateway_facade.call( - address=contract_address, - function_name=function_name, - inputs=inputs, + try: + return asyncio.run( + self._gateway_facade.call( + address=contract_address, + function_name=function_name, + inputs=inputs, + ) ) - ) + except UnknownFunctionException as err: + raise CheatcodeException( + self.name, + message=err.message, + ) from err diff --git a/protostar/starknet_gateway/__init__.py b/protostar/starknet_gateway/__init__.py index cce9370368..20d6b0b1cd 100644 --- a/protostar/starknet_gateway/__init__.py +++ b/protostar/starknet_gateway/__init__.py @@ -1,4 +1,7 @@ -from protostar.starknet_gateway.gateway_facade import GatewayFacade +from protostar.starknet_gateway.gateway_facade import ( + GatewayFacade, + UnknownFunctionException, +) from protostar.starknet_gateway.gateway_response import SuccessfulDeclareResponse from protostar.starknet_gateway.network_config import ( InvalidNetworkConfigurationException, diff --git a/protostar/starknet_gateway/gateway_facade.py b/protostar/starknet_gateway/gateway_facade.py index 17bb738916..57a4a77bcd 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -9,13 +9,12 @@ from starknet_py.transactions.declare import make_declare_tx from starknet_py.transactions.deploy import make_deploy_tx from starkware.starknet.definitions import constants -from starkware.starknet.services.api.gateway.transaction import DECLARE_SENDER_ADDRESS +from starkware.starknet.services.api.gateway.transaction import \ + DECLARE_SENDER_ADDRESS from protostar.protostar_exception import ProtostarException from protostar.starknet_gateway.gateway_response import ( - SuccessfulDeclareResponse, - SuccessfulDeployResponse, -) + SuccessfulDeclareResponse, SuccessfulDeployResponse) from protostar.starknet_gateway.starknet_request import StarknetRequest from protostar.utils.log_color_provider import LogColorProvider @@ -202,7 +201,11 @@ async def call( contract = await Contract.from_address( address=address, client=self._gateway_client ) - contract_function = contract.functions[function_name] + try: + contract_function = contract.functions[function_name] + except KeyError: + raise UnknownFunctionException(function_name) + if isinstance(inputs, List): result = await contract_function.call(*inputs) else: @@ -284,3 +287,8 @@ def map_from_starknet_py_naming(name: str) -> str: if name == "mainnet": return "alpha-mainnet" return name + + +class UnknownFunctionException(ProtostarException): + def __init__(self, function_name: str): + super().__init__(f"Tried to call unknown function: '{function_name}'") diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py index fdb70b0697..72af91e195 100644 --- a/tests/integration/gateway/gateway_facade_test.py +++ b/tests/integration/gateway/gateway_facade_test.py @@ -100,3 +100,16 @@ async def test_call_to_with_incorrect_args( function_name="get_balance", inputs={"UNKNOWN_ARG": 42}, ) + + +async def test_call_to_with_positional_incorrect_args( + gateway_facade: GatewayFacade, compiled_contract_path: Path +): + deployed_contract = await gateway_facade.deploy(compiled_contract_path) + + with pytest.raises(Exception): + await gateway_facade.call( + deployed_contract.address, + function_name="get_balance", + inputs=[42], + ) diff --git a/tests/integration/migrator/migrator_call_cheatcode_test.py b/tests/integration/migrator/migrator_call_cheatcode_test.py index 4e92805fd8..910ecc5724 100644 --- a/tests/integration/migrator/migrator_call_cheatcode_test.py +++ b/tests/integration/migrator/migrator_call_cheatcode_test.py @@ -4,7 +4,10 @@ from typing import Dict import pytest +from typing_extensions import Protocol +from protostar.commands.test.test_environment_exceptions import ReportedException +from protostar.protostar_exception import ProtostarException from protostar.starknet_gateway.starknet_request import StarknetRequest from tests.data.contracts import IDENTITY_CONTRACT from tests.integration.protostar_fixture import ProtostarFixture @@ -17,7 +20,59 @@ def setup(protostar: ProtostarFixture): protostar.build_sync() -async def test_call_contract(protostar: ProtostarFixture, devnet_gateway_url: str): +class MigrateFixture(Protocol): + async def __call__(self, migration_hint_content: str) -> None: + ... + + +@pytest.fixture(name="migrate") +async def migrate_fixture(protostar: ProtostarFixture, devnet_gateway_url: str): + async def migrate(migration_hint_content: str): + migration_file_path = protostar.create_migration_file(migration_hint_content) + await protostar.migrate(migration_file_path, network=devnet_gateway_url) + + return migrate + + +async def test_using_dict_to_pass_args(migrate: MigrateFixture): + await migrate( + """ + contract_address = deploy_contract("./build/main.json").contract_address + + result = call(contract_address, "identity", {"arg": 42}) + + assert result.res == 42 + """ + ) + + +async def test_failure_on_wrong_args(migrate: MigrateFixture): + with pytest.raises(ReportedException, match="Input arg not provided"): + await migrate( + """ + contract_address = deploy_contract("./build/main.json").contract_address + + result = call(contract_address, "identity", []) + """ + ) + + +async def test_failure_when_calling_not_existing_function(migrate: MigrateFixture): + with pytest.raises( + ProtostarException, match="unknown function: 'UNKNOWN_FUNCTION'" + ): + await migrate( + """ + contract_address = deploy_contract("./build/main.json").contract_address + + result = call(contract_address, "UNKNOWN_FUNCTION", []) + """ + ) + + +async def test_migration_using_call_creates_output( + protostar: ProtostarFixture, devnet_gateway_url: str +): migration_file_path = protostar.create_migration_file( """ contract_address = deploy_contract("./build/main.json").contract_address @@ -32,12 +87,11 @@ async def test_call_contract(protostar: ProtostarFixture, devnet_gateway_url: st output_dir=migration_output_relative_path, ) - loaded_migration_output = load_migration_history( + loaded_migration_output = load_migration_history_from_output( migration_output_path=protostar.project_root_path / migration_output_relative_path ) assert loaded_migration_output is not None - output_file_content = str(loaded_migration_output) assert "CALL" in output_file_content assert "[42]" in output_file_content @@ -48,7 +102,7 @@ async def test_call_contract(protostar: ProtostarFixture, devnet_gateway_url: st assert str(contract_address) in output_file_content -def load_migration_history(migration_output_path: Path) -> Dict: +def load_migration_history_from_output(migration_output_path: Path) -> Dict: migration_output_file_names = listdir(migration_output_path) assert len(migration_output_file_names) == 1 migration_output_file_path = migration_output_path / migration_output_file_names[0] From 956250c2ae580a77ce7327e5c422dc5430dcc5ec Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Fri, 12 Aug 2022 13:51:43 +0200 Subject: [PATCH 29/49] format --- scripts/generate_reference_docs_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generate_reference_docs_test.py b/scripts/generate_reference_docs_test.py index 6fba061f76..65a1b446e2 100644 --- a/scripts/generate_reference_docs_test.py +++ b/scripts/generate_reference_docs_test.py @@ -5,7 +5,7 @@ def test_instance_matches_cli_reference_docs(): - di_container = build_di_container(Path()) + di_container = build_di_container(script_root=Path(), cwd=Path()) new_snapshot = ReferenceDocsGenerator( di_container.protostar_cli ).generate_cli_reference_markdown() From 33b40ea071946526ca1671e2a071e197d1b01f06 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Fri, 12 Aug 2022 16:08:45 +0200 Subject: [PATCH 30/49] handle errors --- .../cheatcodes/migrator_call_cheatcode.py | 11 ++-- protostar/starknet_gateway/__init__.py | 1 + protostar/starknet_gateway/gateway_facade.py | 56 +++++++++++++------ tests/integration/migrator/conftest.py | 17 +++++- .../migrator/migrator_call_cheatcode_test.py | 25 +++------ 5 files changed, 71 insertions(+), 39 deletions(-) diff --git a/protostar/migrator/cheatcodes/migrator_call_cheatcode.py b/protostar/migrator/cheatcodes/migrator_call_cheatcode.py index 0a2da53193..511b802865 100644 --- a/protostar/migrator/cheatcodes/migrator_call_cheatcode.py +++ b/protostar/migrator/cheatcodes/migrator_call_cheatcode.py @@ -3,10 +3,13 @@ from typing_extensions import Protocol -from protostar.commands.test.test_environment_exceptions import \ - CheatcodeException +from protostar.commands.test.test_environment_exceptions import CheatcodeException from protostar.starknet.cheatcode import Cheatcode -from protostar.starknet_gateway import GatewayFacade, UnknownFunctionException +from protostar.starknet_gateway import ( + ContractNotFoundException, + GatewayFacade, + UnknownFunctionException, +) from protostar.utils.data_transformer import CairoOrPythonData @@ -50,7 +53,7 @@ def call( inputs=inputs, ) ) - except UnknownFunctionException as err: + except (UnknownFunctionException, ContractNotFoundException) as err: raise CheatcodeException( self.name, message=err.message, diff --git a/protostar/starknet_gateway/__init__.py b/protostar/starknet_gateway/__init__.py index 20d6b0b1cd..135716901e 100644 --- a/protostar/starknet_gateway/__init__.py +++ b/protostar/starknet_gateway/__init__.py @@ -1,4 +1,5 @@ from protostar.starknet_gateway.gateway_facade import ( + ContractNotFoundException, GatewayFacade, UnknownFunctionException, ) diff --git a/protostar/starknet_gateway/gateway_facade.py b/protostar/starknet_gateway/gateway_facade.py index 57a4a77bcd..c16e2bc1e1 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -3,21 +3,25 @@ from pathlib import Path from typing import Any, Callable, Dict, List, NamedTuple, Optional, Union -from starknet_py.contract import Contract, InvokeResult +from starknet_py.contract import Contract, ContractFunction, InvokeResult +from starknet_py.net.client_errors import ContractNotFoundError from starknet_py.net.gateway_client import GatewayClient from starknet_py.net.models import AddressRepresentation, StarknetChainId from starknet_py.transactions.declare import make_declare_tx from starknet_py.transactions.deploy import make_deploy_tx from starkware.starknet.definitions import constants -from starkware.starknet.services.api.gateway.transaction import \ - DECLARE_SENDER_ADDRESS +from starkware.starknet.services.api.gateway.transaction import DECLARE_SENDER_ADDRESS from protostar.protostar_exception import ProtostarException from protostar.starknet_gateway.gateway_response import ( - SuccessfulDeclareResponse, SuccessfulDeployResponse) + SuccessfulDeclareResponse, + SuccessfulDeployResponse, +) from protostar.starknet_gateway.starknet_request import StarknetRequest from protostar.utils.log_color_provider import LogColorProvider +GatewayFacadeSupportedInputType = Union[List[int], Dict[str, Any]] + class TransactionException(ProtostarException): pass @@ -186,7 +190,7 @@ async def call( self, address: AddressRepresentation, function_name: str, - inputs: Optional[Union[List[int], Dict[str, Any]]] = None, + inputs: Optional[GatewayFacadeSupportedInputType] = None, ) -> NamedTuple: register_response = self._register_request( action="CALL", @@ -196,22 +200,35 @@ async def call( "inputs": str(inputs), }, ) - if inputs is None: - inputs = {} - contract = await Contract.from_address( - address=address, client=self._gateway_client - ) + contract_function = await self._create_contract_function(address, function_name) + result = await self._call_function(contract_function, inputs) + register_response({"result": str(result._asdict())}) + return result + + async def _create_contract_function( + self, contract_address: AddressRepresentation, function_name: str + ): try: - contract_function = contract.functions[function_name] + contract = await Contract.from_address( + address=contract_address, client=self._gateway_client + ) + except ContractNotFoundError as err: + raise ContractNotFoundException(contract_address) from err + try: + return contract.functions[function_name] except KeyError: - raise UnknownFunctionException(function_name) + raise UnknownFunctionException(function_name) from KeyError + @staticmethod + async def _call_function( + contract_function: ContractFunction, + inputs: Optional[GatewayFacadeSupportedInputType] = None, + ): + if inputs is None: + inputs = {} if isinstance(inputs, List): - result = await contract_function.call(*inputs) - else: - result = await contract_function.call(**inputs) - register_response({"response": str(result._asdict())}) - return result + return await contract_function.call(*inputs) + return await contract_function.call(**inputs) async def invoke( self, @@ -292,3 +309,8 @@ def map_from_starknet_py_naming(name: str) -> str: class UnknownFunctionException(ProtostarException): def __init__(self, function_name: str): super().__init__(f"Tried to call unknown function: '{function_name}'") + + +class ContractNotFoundException(ProtostarException): + def __init__(self, contract_address: AddressRepresentation): + super().__init__(f"Tried to call unknown contract:\n{contract_address}") diff --git a/tests/integration/migrator/conftest.py b/tests/integration/migrator/conftest.py index 0f2ed9e619..ac7087cc4a 100644 --- a/tests/integration/migrator/conftest.py +++ b/tests/integration/migrator/conftest.py @@ -5,13 +5,14 @@ from starknet_py.net.client_models import TransactionStatus from starknet_py.net.gateway_client import GatewayClient from starknet_py.net.models import StarknetChainId -from typing_extensions import Literal +from typing_extensions import Protocol from protostar.migrator import Migrator from protostar.migrator.migrator_execution_environment import ( MigratorExecutionEnvironment, ) from protostar.starknet_gateway.gateway_facade import GatewayFacade +from tests.integration.protostar_fixture import ProtostarFixture @pytest.fixture(name="project_root_path") @@ -39,3 +40,17 @@ async def assert_transaction_accepted( transaction_hash, wait_for_accept=True ) assert transaction_status == TransactionStatus.ACCEPTED_ON_L2 + + +class MigrateFixture(Protocol): + async def __call__(self, migration_hint_content: str) -> None: + ... + + +@pytest.fixture(name="migrate") +async def migrate_fixture(protostar: ProtostarFixture, devnet_gateway_url: str): + async def migrate(migration_hint_content: str): + migration_file_path = protostar.create_migration_file(migration_hint_content) + await protostar.migrate(migration_file_path, network=devnet_gateway_url) + + return migrate diff --git a/tests/integration/migrator/migrator_call_cheatcode_test.py b/tests/integration/migrator/migrator_call_cheatcode_test.py index 910ecc5724..6710355001 100644 --- a/tests/integration/migrator/migrator_call_cheatcode_test.py +++ b/tests/integration/migrator/migrator_call_cheatcode_test.py @@ -4,12 +4,12 @@ from typing import Dict import pytest -from typing_extensions import Protocol from protostar.commands.test.test_environment_exceptions import ReportedException from protostar.protostar_exception import ProtostarException from protostar.starknet_gateway.starknet_request import StarknetRequest from tests.data.contracts import IDENTITY_CONTRACT +from tests.integration.migrator.conftest import MigrateFixture from tests.integration.protostar_fixture import ProtostarFixture @@ -20,20 +20,6 @@ def setup(protostar: ProtostarFixture): protostar.build_sync() -class MigrateFixture(Protocol): - async def __call__(self, migration_hint_content: str) -> None: - ... - - -@pytest.fixture(name="migrate") -async def migrate_fixture(protostar: ProtostarFixture, devnet_gateway_url: str): - async def migrate(migration_hint_content: str): - migration_file_path = protostar.create_migration_file(migration_hint_content) - await protostar.migrate(migration_file_path, network=devnet_gateway_url) - - return migrate - - async def test_using_dict_to_pass_args(migrate: MigrateFixture): await migrate( """ @@ -52,7 +38,7 @@ async def test_failure_on_wrong_args(migrate: MigrateFixture): """ contract_address = deploy_contract("./build/main.json").contract_address - result = call(contract_address, "identity", []) + call(contract_address, "identity", []) """ ) @@ -65,11 +51,16 @@ async def test_failure_when_calling_not_existing_function(migrate: MigrateFixtur """ contract_address = deploy_contract("./build/main.json").contract_address - result = call(contract_address, "UNKNOWN_FUNCTION", []) + call(contract_address, "UNKNOWN_FUNCTION") """ ) +async def test_failure_when_calling_not_existing_contract(migrate: MigrateFixture): + with pytest.raises(ProtostarException, match="unknown contract"): + await migrate('call(123, "_")') + + async def test_migration_using_call_creates_output( protostar: ProtostarFixture, devnet_gateway_url: str ): From 8a13d88c99537f8032aca9b5aa05015c5629ca2d Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Fri, 12 Aug 2022 16:16:01 +0200 Subject: [PATCH 31/49] fix gateway facade tests --- tests/integration/gateway/gateway_facade_test.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py index 72af91e195..6350c50ce3 100644 --- a/tests/integration/gateway/gateway_facade_test.py +++ b/tests/integration/gateway/gateway_facade_test.py @@ -1,9 +1,12 @@ from pathlib import Path import pytest -from starknet_py.net.client_errors import ContractNotFoundError -from protostar.starknet_gateway.gateway_facade import GatewayFacade +from protostar.starknet_gateway.gateway_facade import ( + ContractNotFoundException, + GatewayFacade, + UnknownFunctionException, +) from protostar.utils.log_color_provider import LogColorProvider from tests.integration.protostar_fixture import ProtostarFixture @@ -72,7 +75,7 @@ async def test_call_to_unknown_function( ): deployed_contract = await gateway_facade.deploy(compiled_contract_path) - with pytest.raises(KeyError): + with pytest.raises(UnknownFunctionException): await gateway_facade.call( deployed_contract.address, function_name="UNKNOWN_FUNCTION", @@ -81,7 +84,7 @@ async def test_call_to_unknown_function( async def test_call_to_unknown_contract(gateway_facade: GatewayFacade): - with pytest.raises(ContractNotFoundError, match="No contract found for identifier"): + with pytest.raises(ContractNotFoundException): await gateway_facade.call( 123, function_name="UNKNOWN_FUNCTION", From 6e9e88b0c98fab365fe1472961c0cd2bf266e834 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Fri, 12 Aug 2022 16:28:25 +0200 Subject: [PATCH 32/49] fix types and format --- protostar/composition_root.py | 5 +++-- protostar/migrator/migrator_test.py | 9 +++++++-- scripts/generate_reference_docs.py | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/protostar/composition_root.py b/protostar/composition_root.py index 505b2ce280..6ced0fe6b4 100644 --- a/protostar/composition_root.py +++ b/protostar/composition_root.py @@ -1,7 +1,7 @@ from dataclasses import dataclass from logging import getLogger from pathlib import Path -from typing import List +from typing import List, Optional from protostar.cli import Command from protostar.commands import ( @@ -55,7 +55,8 @@ class DIContainer: # pylint: disable=too-many-locals -def build_di_container(script_root: Path, cwd: Path): +def build_di_container(script_root: Path, cwd: Optional[Path] = None): + cwd = cwd or Path() logger = getLogger() protostar_toml_path = search_upwards_protostar_toml_path(start_path=cwd.resolve()) project_root_path = ( diff --git a/protostar/migrator/migrator_test.py b/protostar/migrator/migrator_test.py index ceb1cc483d..458ceacff4 100644 --- a/protostar/migrator/migrator_test.py +++ b/protostar/migrator/migrator_test.py @@ -2,14 +2,19 @@ from pathlib import Path from freezegun import freeze_time +from pytest_mock import MockerFixture from protostar.migrator.migrator import Migrator from protostar.starknet_gateway.starknet_request import StarknetRequest @freeze_time("2022-04-02 21:37:42") -def test_migrator_saves_result_successfully_with_proper_name(tmp_path: Path): - Migrator.save_history( +def test_migrator_saves_result_successfully_with_proper_name( + mocker: MockerFixture, tmp_path: Path +): + migrator = Migrator(migrator_execution_environment=mocker.MagicMock()) + + migrator.save_history( history=Migrator.History( starknet_requests=[ StarknetRequest( diff --git a/scripts/generate_reference_docs.py b/scripts/generate_reference_docs.py index f2da4d0da4..5a5fd588cc 100644 --- a/scripts/generate_reference_docs.py +++ b/scripts/generate_reference_docs.py @@ -4,7 +4,7 @@ from protostar.composition_root import build_di_container CLI_REFERENCE_MARKDOWN_CONTENT = ReferenceDocsGenerator( - build_di_container(Path()).protostar_cli + build_di_container(script_root=Path()).protostar_cli ).generate_cli_reference_markdown() ReferenceDocsGenerator.save_to_markdown_file( From a4d3fa071e9f038846996b651b661cfb8b789660 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Fri, 12 Aug 2022 17:06:28 +0200 Subject: [PATCH 33/49] refine --- tests/integration/conftest.py | 6 +++--- tests/integration/gateway/gateway_facade_test.py | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 54c7a8a7e0..f7d5b2c05a 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -2,9 +2,9 @@ from dataclasses import dataclass from pathlib import Path from typing import List, Optional, Set, Union -from unittest.mock import MagicMock import pytest +from pytest import TempPathFactory from pytest_mock import MockerFixture from typing_extensions import Protocol @@ -110,14 +110,14 @@ async def run_cairo_test_runner( @pytest.fixture(name="protostar_project_root_path", scope="module") -def protostar_project_root_path_fixture(tmp_path_factory) -> Path: +def protostar_project_root_path_fixture(tmp_path_factory: TempPathFactory) -> Path: tmp_path = tmp_path_factory.mktemp("data") return tmp_path / "tmp_project" @pytest.fixture(name="protostar", scope="module") def protostar_fixture( - session_mocker: MagicMock, + session_mocker: MockerFixture, protostar_project_root_path: Path, ) -> ProtostarFixture: return build_protostar_fixture( diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py index 6350c50ce3..a0771b2391 100644 --- a/tests/integration/gateway/gateway_facade_test.py +++ b/tests/integration/gateway/gateway_facade_test.py @@ -12,7 +12,6 @@ @pytest.fixture(autouse=True, scope="module") -# pylint: disable=unused-argument def setup(protostar: ProtostarFixture): protostar.init_sync() protostar.build_sync() From 1ae29475a0a935e2ac4f71a2b3c08b36199a6bac Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Fri, 12 Aug 2022 17:48:54 +0200 Subject: [PATCH 34/49] fix protostar toml --- protostar/commands/init/init_command.py | 17 ++++++++++++----- protostar/composition_root.py | 1 + tests/integration/protostar_fixture.py | 1 + 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/protostar/commands/init/init_command.py b/protostar/commands/init/init_command.py index b0af30b9da..28fc73e3ea 100644 --- a/protostar/commands/init/init_command.py +++ b/protostar/commands/init/init_command.py @@ -1,4 +1,5 @@ -import glob +from glob import glob +from pathlib import Path from typing import List, Optional from protostar.cli import Command @@ -17,11 +18,13 @@ def __init__( requester: InputRequester, new_project_creator: NewProjectCreator, adapted_project_creator: AdaptedProjectCreator, + cwd: Path, ) -> None: super().__init__() self._adapted_project_creator = adapted_project_creator self._new_project_creator = new_project_creator self._requester = requester + self._cwd = cwd @property def name(self) -> str: @@ -65,9 +68,13 @@ def init(self, force_adapting_existing_project: bool): else: self._new_project_creator.run() - @staticmethod - def _can_be_protostar_project() -> bool: - files_depth_3 = glob.glob("*") + glob.glob("*/*") + glob.glob("*/*/*") + def _can_be_protostar_project(self) -> bool: + + files_depth_3 = ( + glob(str(self._cwd / "*")) + + glob(str(self._cwd / "*" / "*")) + + glob(str(self._cwd / "*" / "*" / "*")) + ) return any( map(lambda f: f.endswith(".cairo") or f == ".git", files_depth_3) - ) and "protostar.toml" not in glob.glob("*") + ) and "protostar.toml" not in glob(str(self._cwd / "*")) diff --git a/protostar/composition_root.py b/protostar/composition_root.py index 6ced0fe6b4..0b1650ca1d 100644 --- a/protostar/composition_root.py +++ b/protostar/composition_root.py @@ -111,6 +111,7 @@ def build_di_container(script_root: Path, cwd: Optional[Path] = None): protostar_toml_writer, version_manager, ), + cwd=cwd, ), BuildCommand(project_compiler, logger), InstallCommand( diff --git a/tests/integration/protostar_fixture.py b/tests/integration/protostar_fixture.py index da88b017c9..13dfc45c9c 100644 --- a/tests/integration/protostar_fixture.py +++ b/tests/integration/protostar_fixture.py @@ -151,6 +151,7 @@ def request_input(message: str) -> str: input_requester, new_project_creator=new_project_creator, adapted_project_creator=mocker.MagicMock(), + cwd=project_root_path.parent, ) project_compiler = ProjectCompiler( From 436c5f414b2c6748bb0bd05f53b0a01595836cfd Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Fri, 12 Aug 2022 18:19:03 +0200 Subject: [PATCH 35/49] fix lint --- protostar/commands/init/project_creator/new_project_creator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/protostar/commands/init/project_creator/new_project_creator.py b/protostar/commands/init/project_creator/new_project_creator.py index bd6f79c882..090fb6713c 100644 --- a/protostar/commands/init/project_creator/new_project_creator.py +++ b/protostar/commands/init/project_creator/new_project_creator.py @@ -17,6 +17,7 @@ class UserInput: project_dirname: str lib_dirname: str + # pylint: disable=too-many-arguments def __init__( self, script_root: Path, From b237c839d330ad13c852b5e54e5251511effd171 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Tue, 16 Aug 2022 17:06:40 +0200 Subject: [PATCH 36/49] remove invoke --- protostar/starknet_gateway/gateway_facade.py | 17 +---------------- .../integration/gateway/gateway_facade_test.py | 15 --------------- 2 files changed, 1 insertion(+), 31 deletions(-) diff --git a/protostar/starknet_gateway/gateway_facade.py b/protostar/starknet_gateway/gateway_facade.py index c16e2bc1e1..2b52af9c63 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -3,7 +3,7 @@ from pathlib import Path from typing import Any, Callable, Dict, List, NamedTuple, Optional, Union -from starknet_py.contract import Contract, ContractFunction, InvokeResult +from starknet_py.contract import Contract, ContractFunction from starknet_py.net.client_errors import ContractNotFoundError from starknet_py.net.gateway_client import GatewayClient from starknet_py.net.models import AddressRepresentation, StarknetChainId @@ -230,21 +230,6 @@ async def _call_function( return await contract_function.call(*inputs) return await contract_function.call(**inputs) - async def invoke( - self, - address: AddressRepresentation, - function_name: str, - inputs: Dict[str, Any], - wait_for_acceptance: bool = False, - ) -> InvokeResult: - contract = await Contract.from_address( - address=address, client=self._gateway_client - ) - response = await contract.functions[function_name].invoke(**inputs) - if wait_for_acceptance: - return await response.wait_for_acceptance() - return response - def _register_request( self, action: StarknetRequest.Action, payload: StarknetRequest.Payload ) -> Callable[[StarknetRequest.Payload], None]: diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py index a0771b2391..010b065780 100644 --- a/tests/integration/gateway/gateway_facade_test.py +++ b/tests/integration/gateway/gateway_facade_test.py @@ -41,21 +41,6 @@ async def test_declare(gateway_facade: GatewayFacade, compiled_contract_path: Pa assert response is not None -@pytest.mark.skip("Protostar needs to support accounts first") -async def test_invoke(gateway_facade: GatewayFacade, compiled_contract_path: Path): - deployed_contract = await gateway_facade.deploy(compiled_contract_path) - - with pytest.raises(ValueError, match="You need to use AccountClient for that."): - await gateway_facade.invoke( - deployed_contract.address, - function_name="increase_balance", - inputs={"amount": 42}, - wait_for_acceptance=True, - ) - - assert False - - async def test_call(gateway_facade: GatewayFacade, compiled_contract_path: Path): deployed_contract = await gateway_facade.deploy(compiled_contract_path) From e2871d2fbcbc10f3bd15f9681d331b0077db73d2 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Tue, 16 Aug 2022 17:19:36 +0200 Subject: [PATCH 37/49] remove call cheatcode --- .../cheatcodes/migrator_call_cheatcode.py | 60 ---------- .../migrator/migrator_cheatcodes_factory.py | 2 - protostar/starknet_gateway/__init__.py | 6 +- protostar/starknet_gateway/gateway_facade.py | 60 +--------- .../gateway/gateway_facade_test.py | 67 +---------- tests/integration/migrator/conftest.py | 16 --- .../migrator/migrator_call_cheatcode_test.py | 112 ------------------ 7 files changed, 4 insertions(+), 319 deletions(-) delete mode 100644 protostar/migrator/cheatcodes/migrator_call_cheatcode.py delete mode 100644 tests/integration/migrator/migrator_call_cheatcode_test.py diff --git a/protostar/migrator/cheatcodes/migrator_call_cheatcode.py b/protostar/migrator/cheatcodes/migrator_call_cheatcode.py deleted file mode 100644 index 511b802865..0000000000 --- a/protostar/migrator/cheatcodes/migrator_call_cheatcode.py +++ /dev/null @@ -1,60 +0,0 @@ -import asyncio -from typing import Any, Optional - -from typing_extensions import Protocol - -from protostar.commands.test.test_environment_exceptions import CheatcodeException -from protostar.starknet.cheatcode import Cheatcode -from protostar.starknet_gateway import ( - ContractNotFoundException, - GatewayFacade, - UnknownFunctionException, -) -from protostar.utils.data_transformer import CairoOrPythonData - - -class CallCheatcodeProtocol(Protocol): - def __call__( - self, - contract_address: int, - function_name: str, - inputs: Optional[CairoOrPythonData] = None, - ) -> Any: - ... - - -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) -> CallCheatcodeProtocol: - return self.call - - def call( - self, - contract_address: int, - function_name: str, - inputs: Optional[CairoOrPythonData] = None, - ): - try: - return asyncio.run( - self._gateway_facade.call( - address=contract_address, - function_name=function_name, - inputs=inputs, - ) - ) - except (UnknownFunctionException, ContractNotFoundException) as err: - raise CheatcodeException( - self.name, - message=err.message, - ) from err diff --git a/protostar/migrator/migrator_cheatcodes_factory.py b/protostar/migrator/migrator_cheatcodes_factory.py index cd58046092..60f54304a5 100644 --- a/protostar/migrator/migrator_cheatcodes_factory.py +++ b/protostar/migrator/migrator_cheatcodes_factory.py @@ -3,7 +3,6 @@ from starkware.starknet.business_logic.execution.objects import CallInfo -from protostar.migrator.cheatcodes.migrator_call_cheatcode import MigratorCallCheatcode from protostar.migrator.cheatcodes.migrator_declare_cheatcode import ( MigratorDeclareCheatcode, ) @@ -52,5 +51,4 @@ def build( self.gateway_facade, config=MigratorDeployContractCheatcode.Config(token=self._config.token), ), - MigratorCallCheatcode(syscall_dependencies, self.gateway_facade), ] diff --git a/protostar/starknet_gateway/__init__.py b/protostar/starknet_gateway/__init__.py index 135716901e..cce9370368 100644 --- a/protostar/starknet_gateway/__init__.py +++ b/protostar/starknet_gateway/__init__.py @@ -1,8 +1,4 @@ -from protostar.starknet_gateway.gateway_facade import ( - ContractNotFoundException, - GatewayFacade, - UnknownFunctionException, -) +from protostar.starknet_gateway.gateway_facade import GatewayFacade from protostar.starknet_gateway.gateway_response import SuccessfulDeclareResponse from protostar.starknet_gateway.network_config import ( InvalidNetworkConfigurationException, diff --git a/protostar/starknet_gateway/gateway_facade.py b/protostar/starknet_gateway/gateway_facade.py index 2b52af9c63..59e4d4c515 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -1,12 +1,10 @@ import dataclasses from logging import Logger from pathlib import Path -from typing import Any, Callable, Dict, List, NamedTuple, Optional, Union +from typing import Any, Callable, Dict, List, Optional, Union -from starknet_py.contract import Contract, ContractFunction -from starknet_py.net.client_errors import ContractNotFoundError from starknet_py.net.gateway_client import GatewayClient -from starknet_py.net.models import AddressRepresentation, StarknetChainId +from starknet_py.net.models import StarknetChainId from starknet_py.transactions.declare import make_declare_tx from starknet_py.transactions.deploy import make_deploy_tx from starkware.starknet.definitions import constants @@ -186,50 +184,6 @@ async def declare( transaction_hash=result.transaction_hash, ) - async def call( - self, - address: AddressRepresentation, - function_name: str, - inputs: Optional[GatewayFacadeSupportedInputType] = None, - ) -> NamedTuple: - register_response = self._register_request( - action="CALL", - payload={ - "contract_address": address, - "function_name": function_name, - "inputs": str(inputs), - }, - ) - contract_function = await self._create_contract_function(address, function_name) - result = await self._call_function(contract_function, inputs) - register_response({"result": str(result._asdict())}) - return result - - async def _create_contract_function( - self, contract_address: AddressRepresentation, function_name: str - ): - try: - contract = await Contract.from_address( - address=contract_address, client=self._gateway_client - ) - except ContractNotFoundError as err: - raise ContractNotFoundException(contract_address) from err - try: - return contract.functions[function_name] - except KeyError: - raise UnknownFunctionException(function_name) from KeyError - - @staticmethod - async def _call_function( - contract_function: ContractFunction, - inputs: Optional[GatewayFacadeSupportedInputType] = None, - ): - if inputs is None: - inputs = {} - if isinstance(inputs, List): - return await contract_function.call(*inputs) - return await contract_function.call(**inputs) - def _register_request( self, action: StarknetRequest.Action, payload: StarknetRequest.Payload ) -> Callable[[StarknetRequest.Payload], None]: @@ -289,13 +243,3 @@ def map_from_starknet_py_naming(name: str) -> str: if name == "mainnet": return "alpha-mainnet" return name - - -class UnknownFunctionException(ProtostarException): - def __init__(self, function_name: str): - super().__init__(f"Tried to call unknown function: '{function_name}'") - - -class ContractNotFoundException(ProtostarException): - def __init__(self, contract_address: AddressRepresentation): - super().__init__(f"Tried to call unknown contract:\n{contract_address}") diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py index 010b065780..487c7acb24 100644 --- a/tests/integration/gateway/gateway_facade_test.py +++ b/tests/integration/gateway/gateway_facade_test.py @@ -2,11 +2,7 @@ import pytest -from protostar.starknet_gateway.gateway_facade import ( - ContractNotFoundException, - GatewayFacade, - UnknownFunctionException, -) +from protostar.starknet_gateway.gateway_facade import GatewayFacade from protostar.utils.log_color_provider import LogColorProvider from tests.integration.protostar_fixture import ProtostarFixture @@ -39,64 +35,3 @@ async def test_deploy(gateway_facade: GatewayFacade, compiled_contract_path: Pat async def test_declare(gateway_facade: GatewayFacade, compiled_contract_path: Path): response = await gateway_facade.declare(compiled_contract_path) assert response is not None - - -async def test_call(gateway_facade: GatewayFacade, compiled_contract_path: Path): - deployed_contract = await gateway_facade.deploy(compiled_contract_path) - - response = await gateway_facade.call( - deployed_contract.address, - function_name="get_balance", - inputs={}, - ) - - initial_balance = 0 - assert response[0] == initial_balance - - -async def test_call_to_unknown_function( - gateway_facade: GatewayFacade, compiled_contract_path: Path -): - deployed_contract = await gateway_facade.deploy(compiled_contract_path) - - with pytest.raises(UnknownFunctionException): - await gateway_facade.call( - deployed_contract.address, - function_name="UNKNOWN_FUNCTION", - inputs={}, - ) - - -async def test_call_to_unknown_contract(gateway_facade: GatewayFacade): - with pytest.raises(ContractNotFoundException): - await gateway_facade.call( - 123, - function_name="UNKNOWN_FUNCTION", - ) - - -@pytest.mark.skip("https://github.com/software-mansion/starknet.py/issues/302") -async def test_call_to_with_incorrect_args( - gateway_facade: GatewayFacade, compiled_contract_path: Path -): - deployed_contract = await gateway_facade.deploy(compiled_contract_path) - - with pytest.raises(Exception): - await gateway_facade.call( - deployed_contract.address, - function_name="get_balance", - inputs={"UNKNOWN_ARG": 42}, - ) - - -async def test_call_to_with_positional_incorrect_args( - gateway_facade: GatewayFacade, compiled_contract_path: Path -): - deployed_contract = await gateway_facade.deploy(compiled_contract_path) - - with pytest.raises(Exception): - await gateway_facade.call( - deployed_contract.address, - function_name="get_balance", - inputs=[42], - ) diff --git a/tests/integration/migrator/conftest.py b/tests/integration/migrator/conftest.py index ac7087cc4a..812c1fc909 100644 --- a/tests/integration/migrator/conftest.py +++ b/tests/integration/migrator/conftest.py @@ -5,14 +5,12 @@ from starknet_py.net.client_models import TransactionStatus from starknet_py.net.gateway_client import GatewayClient from starknet_py.net.models import StarknetChainId -from typing_extensions import Protocol from protostar.migrator import Migrator from protostar.migrator.migrator_execution_environment import ( MigratorExecutionEnvironment, ) from protostar.starknet_gateway.gateway_facade import GatewayFacade -from tests.integration.protostar_fixture import ProtostarFixture @pytest.fixture(name="project_root_path") @@ -40,17 +38,3 @@ async def assert_transaction_accepted( transaction_hash, wait_for_accept=True ) assert transaction_status == TransactionStatus.ACCEPTED_ON_L2 - - -class MigrateFixture(Protocol): - async def __call__(self, migration_hint_content: str) -> None: - ... - - -@pytest.fixture(name="migrate") -async def migrate_fixture(protostar: ProtostarFixture, devnet_gateway_url: str): - async def migrate(migration_hint_content: str): - migration_file_path = protostar.create_migration_file(migration_hint_content) - await protostar.migrate(migration_file_path, network=devnet_gateway_url) - - return migrate diff --git a/tests/integration/migrator/migrator_call_cheatcode_test.py b/tests/integration/migrator/migrator_call_cheatcode_test.py deleted file mode 100644 index 6710355001..0000000000 --- a/tests/integration/migrator/migrator_call_cheatcode_test.py +++ /dev/null @@ -1,112 +0,0 @@ -import json -from os import listdir -from pathlib import Path -from typing import Dict - -import pytest - -from protostar.commands.test.test_environment_exceptions import ReportedException -from protostar.protostar_exception import ProtostarException -from protostar.starknet_gateway.starknet_request import StarknetRequest -from tests.data.contracts import IDENTITY_CONTRACT -from tests.integration.migrator.conftest import MigrateFixture -from tests.integration.protostar_fixture import ProtostarFixture - - -@pytest.fixture(autouse=True, scope="module") -def setup(protostar: ProtostarFixture): - protostar.init_sync() - protostar.create_files({"./src/main.cairo": IDENTITY_CONTRACT}) - protostar.build_sync() - - -async def test_using_dict_to_pass_args(migrate: MigrateFixture): - await migrate( - """ - contract_address = deploy_contract("./build/main.json").contract_address - - result = call(contract_address, "identity", {"arg": 42}) - - assert result.res == 42 - """ - ) - - -async def test_failure_on_wrong_args(migrate: MigrateFixture): - with pytest.raises(ReportedException, match="Input arg not provided"): - await migrate( - """ - contract_address = deploy_contract("./build/main.json").contract_address - - call(contract_address, "identity", []) - """ - ) - - -async def test_failure_when_calling_not_existing_function(migrate: MigrateFixture): - with pytest.raises( - ProtostarException, match="unknown function: 'UNKNOWN_FUNCTION'" - ): - await migrate( - """ - contract_address = deploy_contract("./build/main.json").contract_address - - call(contract_address, "UNKNOWN_FUNCTION") - """ - ) - - -async def test_failure_when_calling_not_existing_contract(migrate: MigrateFixture): - with pytest.raises(ProtostarException, match="unknown contract"): - await migrate('call(123, "_")') - - -async def test_migration_using_call_creates_output( - protostar: ProtostarFixture, devnet_gateway_url: str -): - migration_file_path = protostar.create_migration_file( - """ - contract_address = deploy_contract("./build/main.json").contract_address - call(contract_address, "identity", [42]) - """ - ) - migration_output_relative_path = Path("./migrations/output") - - migration_history = await protostar.migrate( - migration_file_path, - network=devnet_gateway_url, - output_dir=migration_output_relative_path, - ) - - loaded_migration_output = load_migration_history_from_output( - migration_output_path=protostar.project_root_path - / migration_output_relative_path - ) - assert loaded_migration_output is not None - output_file_content = str(loaded_migration_output) - assert "CALL" in output_file_content - assert "[42]" in output_file_content - assert "{'res': 42}" in output_file_content - contract_address = extract_contract_address_from_deploy_response( - migration_history.starknet_requests[0].response - ) - assert str(contract_address) in output_file_content - - -def load_migration_history_from_output(migration_output_path: Path) -> Dict: - migration_output_file_names = listdir(migration_output_path) - assert len(migration_output_file_names) == 1 - migration_output_file_path = migration_output_path / migration_output_file_names[0] - return load_json(migration_output_file_path) - - -def load_json(path: Path): - with open(path, "r", encoding="utf-8") as file: - return json.loads(file.read()) - - -def extract_contract_address_from_deploy_response( - deploy_response: StarknetRequest.Payload, -) -> int: - assert isinstance(deploy_response["contract_address"], int) - return deploy_response["contract_address"] From ac66be72b864578d47f2adaf5a5a622ca1b1e1e9 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Tue, 16 Aug 2022 17:31:17 +0200 Subject: [PATCH 38/49] Revert "remove call cheatcode" This reverts commit e2871d2fbcbc10f3bd15f9681d331b0077db73d2. --- .../cheatcodes/migrator_call_cheatcode.py | 60 ++++++++++ .../migrator/migrator_cheatcodes_factory.py | 2 + protostar/starknet_gateway/__init__.py | 6 +- protostar/starknet_gateway/gateway_facade.py | 60 +++++++++- .../gateway/gateway_facade_test.py | 67 ++++++++++- tests/integration/migrator/conftest.py | 16 +++ .../migrator/migrator_call_cheatcode_test.py | 112 ++++++++++++++++++ 7 files changed, 319 insertions(+), 4 deletions(-) create mode 100644 protostar/migrator/cheatcodes/migrator_call_cheatcode.py create mode 100644 tests/integration/migrator/migrator_call_cheatcode_test.py diff --git a/protostar/migrator/cheatcodes/migrator_call_cheatcode.py b/protostar/migrator/cheatcodes/migrator_call_cheatcode.py new file mode 100644 index 0000000000..511b802865 --- /dev/null +++ b/protostar/migrator/cheatcodes/migrator_call_cheatcode.py @@ -0,0 +1,60 @@ +import asyncio +from typing import Any, Optional + +from typing_extensions import Protocol + +from protostar.commands.test.test_environment_exceptions import CheatcodeException +from protostar.starknet.cheatcode import Cheatcode +from protostar.starknet_gateway import ( + ContractNotFoundException, + GatewayFacade, + UnknownFunctionException, +) +from protostar.utils.data_transformer import CairoOrPythonData + + +class CallCheatcodeProtocol(Protocol): + def __call__( + self, + contract_address: int, + function_name: str, + inputs: Optional[CairoOrPythonData] = None, + ) -> Any: + ... + + +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) -> CallCheatcodeProtocol: + return self.call + + def call( + self, + contract_address: int, + function_name: str, + inputs: Optional[CairoOrPythonData] = None, + ): + try: + return asyncio.run( + self._gateway_facade.call( + address=contract_address, + function_name=function_name, + inputs=inputs, + ) + ) + except (UnknownFunctionException, ContractNotFoundException) as err: + raise CheatcodeException( + self.name, + message=err.message, + ) from err diff --git a/protostar/migrator/migrator_cheatcodes_factory.py b/protostar/migrator/migrator_cheatcodes_factory.py index 60f54304a5..cd58046092 100644 --- a/protostar/migrator/migrator_cheatcodes_factory.py +++ b/protostar/migrator/migrator_cheatcodes_factory.py @@ -3,6 +3,7 @@ from starkware.starknet.business_logic.execution.objects import CallInfo +from protostar.migrator.cheatcodes.migrator_call_cheatcode import MigratorCallCheatcode from protostar.migrator.cheatcodes.migrator_declare_cheatcode import ( MigratorDeclareCheatcode, ) @@ -51,4 +52,5 @@ def build( self.gateway_facade, config=MigratorDeployContractCheatcode.Config(token=self._config.token), ), + MigratorCallCheatcode(syscall_dependencies, self.gateway_facade), ] diff --git a/protostar/starknet_gateway/__init__.py b/protostar/starknet_gateway/__init__.py index cce9370368..135716901e 100644 --- a/protostar/starknet_gateway/__init__.py +++ b/protostar/starknet_gateway/__init__.py @@ -1,4 +1,8 @@ -from protostar.starknet_gateway.gateway_facade import GatewayFacade +from protostar.starknet_gateway.gateway_facade import ( + ContractNotFoundException, + GatewayFacade, + UnknownFunctionException, +) from protostar.starknet_gateway.gateway_response import SuccessfulDeclareResponse from protostar.starknet_gateway.network_config import ( InvalidNetworkConfigurationException, diff --git a/protostar/starknet_gateway/gateway_facade.py b/protostar/starknet_gateway/gateway_facade.py index 59e4d4c515..2b52af9c63 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -1,10 +1,12 @@ import dataclasses from logging import Logger from pathlib import Path -from typing import Any, Callable, Dict, List, Optional, Union +from typing import Any, Callable, Dict, List, NamedTuple, Optional, Union +from starknet_py.contract import Contract, ContractFunction +from starknet_py.net.client_errors import ContractNotFoundError from starknet_py.net.gateway_client import GatewayClient -from starknet_py.net.models import StarknetChainId +from starknet_py.net.models import AddressRepresentation, StarknetChainId from starknet_py.transactions.declare import make_declare_tx from starknet_py.transactions.deploy import make_deploy_tx from starkware.starknet.definitions import constants @@ -184,6 +186,50 @@ async def declare( transaction_hash=result.transaction_hash, ) + async def call( + self, + address: AddressRepresentation, + function_name: str, + inputs: Optional[GatewayFacadeSupportedInputType] = None, + ) -> NamedTuple: + register_response = self._register_request( + action="CALL", + payload={ + "contract_address": address, + "function_name": function_name, + "inputs": str(inputs), + }, + ) + contract_function = await self._create_contract_function(address, function_name) + result = await self._call_function(contract_function, inputs) + register_response({"result": str(result._asdict())}) + return result + + async def _create_contract_function( + self, contract_address: AddressRepresentation, function_name: str + ): + try: + contract = await Contract.from_address( + address=contract_address, client=self._gateway_client + ) + except ContractNotFoundError as err: + raise ContractNotFoundException(contract_address) from err + try: + return contract.functions[function_name] + except KeyError: + raise UnknownFunctionException(function_name) from KeyError + + @staticmethod + async def _call_function( + contract_function: ContractFunction, + inputs: Optional[GatewayFacadeSupportedInputType] = None, + ): + if inputs is None: + inputs = {} + if isinstance(inputs, List): + return await contract_function.call(*inputs) + return await contract_function.call(**inputs) + def _register_request( self, action: StarknetRequest.Action, payload: StarknetRequest.Payload ) -> Callable[[StarknetRequest.Payload], None]: @@ -243,3 +289,13 @@ def map_from_starknet_py_naming(name: str) -> str: if name == "mainnet": return "alpha-mainnet" return name + + +class UnknownFunctionException(ProtostarException): + def __init__(self, function_name: str): + super().__init__(f"Tried to call unknown function: '{function_name}'") + + +class ContractNotFoundException(ProtostarException): + def __init__(self, contract_address: AddressRepresentation): + super().__init__(f"Tried to call unknown contract:\n{contract_address}") diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py index 487c7acb24..010b065780 100644 --- a/tests/integration/gateway/gateway_facade_test.py +++ b/tests/integration/gateway/gateway_facade_test.py @@ -2,7 +2,11 @@ import pytest -from protostar.starknet_gateway.gateway_facade import GatewayFacade +from protostar.starknet_gateway.gateway_facade import ( + ContractNotFoundException, + GatewayFacade, + UnknownFunctionException, +) from protostar.utils.log_color_provider import LogColorProvider from tests.integration.protostar_fixture import ProtostarFixture @@ -35,3 +39,64 @@ async def test_deploy(gateway_facade: GatewayFacade, compiled_contract_path: Pat async def test_declare(gateway_facade: GatewayFacade, compiled_contract_path: Path): response = await gateway_facade.declare(compiled_contract_path) assert response is not None + + +async def test_call(gateway_facade: GatewayFacade, compiled_contract_path: Path): + deployed_contract = await gateway_facade.deploy(compiled_contract_path) + + response = await gateway_facade.call( + deployed_contract.address, + function_name="get_balance", + inputs={}, + ) + + initial_balance = 0 + assert response[0] == initial_balance + + +async def test_call_to_unknown_function( + gateway_facade: GatewayFacade, compiled_contract_path: Path +): + deployed_contract = await gateway_facade.deploy(compiled_contract_path) + + with pytest.raises(UnknownFunctionException): + await gateway_facade.call( + deployed_contract.address, + function_name="UNKNOWN_FUNCTION", + inputs={}, + ) + + +async def test_call_to_unknown_contract(gateway_facade: GatewayFacade): + with pytest.raises(ContractNotFoundException): + await gateway_facade.call( + 123, + function_name="UNKNOWN_FUNCTION", + ) + + +@pytest.mark.skip("https://github.com/software-mansion/starknet.py/issues/302") +async def test_call_to_with_incorrect_args( + gateway_facade: GatewayFacade, compiled_contract_path: Path +): + deployed_contract = await gateway_facade.deploy(compiled_contract_path) + + with pytest.raises(Exception): + await gateway_facade.call( + deployed_contract.address, + function_name="get_balance", + inputs={"UNKNOWN_ARG": 42}, + ) + + +async def test_call_to_with_positional_incorrect_args( + gateway_facade: GatewayFacade, compiled_contract_path: Path +): + deployed_contract = await gateway_facade.deploy(compiled_contract_path) + + with pytest.raises(Exception): + await gateway_facade.call( + deployed_contract.address, + function_name="get_balance", + inputs=[42], + ) diff --git a/tests/integration/migrator/conftest.py b/tests/integration/migrator/conftest.py index 812c1fc909..ac7087cc4a 100644 --- a/tests/integration/migrator/conftest.py +++ b/tests/integration/migrator/conftest.py @@ -5,12 +5,14 @@ from starknet_py.net.client_models import TransactionStatus from starknet_py.net.gateway_client import GatewayClient from starknet_py.net.models import StarknetChainId +from typing_extensions import Protocol from protostar.migrator import Migrator from protostar.migrator.migrator_execution_environment import ( MigratorExecutionEnvironment, ) from protostar.starknet_gateway.gateway_facade import GatewayFacade +from tests.integration.protostar_fixture import ProtostarFixture @pytest.fixture(name="project_root_path") @@ -38,3 +40,17 @@ async def assert_transaction_accepted( transaction_hash, wait_for_accept=True ) assert transaction_status == TransactionStatus.ACCEPTED_ON_L2 + + +class MigrateFixture(Protocol): + async def __call__(self, migration_hint_content: str) -> None: + ... + + +@pytest.fixture(name="migrate") +async def migrate_fixture(protostar: ProtostarFixture, devnet_gateway_url: str): + async def migrate(migration_hint_content: str): + migration_file_path = protostar.create_migration_file(migration_hint_content) + await protostar.migrate(migration_file_path, network=devnet_gateway_url) + + return migrate diff --git a/tests/integration/migrator/migrator_call_cheatcode_test.py b/tests/integration/migrator/migrator_call_cheatcode_test.py new file mode 100644 index 0000000000..6710355001 --- /dev/null +++ b/tests/integration/migrator/migrator_call_cheatcode_test.py @@ -0,0 +1,112 @@ +import json +from os import listdir +from pathlib import Path +from typing import Dict + +import pytest + +from protostar.commands.test.test_environment_exceptions import ReportedException +from protostar.protostar_exception import ProtostarException +from protostar.starknet_gateway.starknet_request import StarknetRequest +from tests.data.contracts import IDENTITY_CONTRACT +from tests.integration.migrator.conftest import MigrateFixture +from tests.integration.protostar_fixture import ProtostarFixture + + +@pytest.fixture(autouse=True, scope="module") +def setup(protostar: ProtostarFixture): + protostar.init_sync() + protostar.create_files({"./src/main.cairo": IDENTITY_CONTRACT}) + protostar.build_sync() + + +async def test_using_dict_to_pass_args(migrate: MigrateFixture): + await migrate( + """ + contract_address = deploy_contract("./build/main.json").contract_address + + result = call(contract_address, "identity", {"arg": 42}) + + assert result.res == 42 + """ + ) + + +async def test_failure_on_wrong_args(migrate: MigrateFixture): + with pytest.raises(ReportedException, match="Input arg not provided"): + await migrate( + """ + contract_address = deploy_contract("./build/main.json").contract_address + + call(contract_address, "identity", []) + """ + ) + + +async def test_failure_when_calling_not_existing_function(migrate: MigrateFixture): + with pytest.raises( + ProtostarException, match="unknown function: 'UNKNOWN_FUNCTION'" + ): + await migrate( + """ + contract_address = deploy_contract("./build/main.json").contract_address + + call(contract_address, "UNKNOWN_FUNCTION") + """ + ) + + +async def test_failure_when_calling_not_existing_contract(migrate: MigrateFixture): + with pytest.raises(ProtostarException, match="unknown contract"): + await migrate('call(123, "_")') + + +async def test_migration_using_call_creates_output( + protostar: ProtostarFixture, devnet_gateway_url: str +): + migration_file_path = protostar.create_migration_file( + """ + contract_address = deploy_contract("./build/main.json").contract_address + call(contract_address, "identity", [42]) + """ + ) + migration_output_relative_path = Path("./migrations/output") + + migration_history = await protostar.migrate( + migration_file_path, + network=devnet_gateway_url, + output_dir=migration_output_relative_path, + ) + + loaded_migration_output = load_migration_history_from_output( + migration_output_path=protostar.project_root_path + / migration_output_relative_path + ) + assert loaded_migration_output is not None + output_file_content = str(loaded_migration_output) + assert "CALL" in output_file_content + assert "[42]" in output_file_content + assert "{'res': 42}" in output_file_content + contract_address = extract_contract_address_from_deploy_response( + migration_history.starknet_requests[0].response + ) + assert str(contract_address) in output_file_content + + +def load_migration_history_from_output(migration_output_path: Path) -> Dict: + migration_output_file_names = listdir(migration_output_path) + assert len(migration_output_file_names) == 1 + migration_output_file_path = migration_output_path / migration_output_file_names[0] + return load_json(migration_output_file_path) + + +def load_json(path: Path): + with open(path, "r", encoding="utf-8") as file: + return json.loads(file.read()) + + +def extract_contract_address_from_deploy_response( + deploy_response: StarknetRequest.Payload, +) -> int: + assert isinstance(deploy_response["contract_address"], int) + return deploy_response["contract_address"] From 34a1b6cbe08fcc8861a98108c7375a465489668b Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Tue, 16 Aug 2022 17:38:41 +0200 Subject: [PATCH 39/49] refine no protostar toml exception --- protostar/protostar_toml/io/protostar_toml_reader.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/protostar/protostar_toml/io/protostar_toml_reader.py b/protostar/protostar_toml/io/protostar_toml_reader.py index 1117f5066a..262a5c3aaa 100644 --- a/protostar/protostar_toml/io/protostar_toml_reader.py +++ b/protostar/protostar_toml/io/protostar_toml_reader.py @@ -72,9 +72,7 @@ def _read_if_cache_miss(self) -> Dict[str, Any]: return self._cache if not self.path.is_file(): - raise NoProtostarProjectFoundException( - "No protostar.toml found in the working directory\n" f"{str(self.path)}" - ) + raise NoProtostarProjectFoundException("`protostar.toml` not found") with open(self.path, "rb") as protostar_toml_file: protostar_toml_dict = tomli.load(protostar_toml_file) From 5a557fe3eb49c3cb134486db4c71093906dc759c Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 17 Aug 2022 11:38:51 +0200 Subject: [PATCH 40/49] remove "call" literal type --- protostar/starknet_gateway/starknet_request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protostar/starknet_gateway/starknet_request.py b/protostar/starknet_gateway/starknet_request.py index 537acec196..37ad489e17 100644 --- a/protostar/starknet_gateway/starknet_request.py +++ b/protostar/starknet_gateway/starknet_request.py @@ -8,7 +8,7 @@ @dataclass class StarknetRequest: - Action = Literal["DEPLOY", "DECLARE", "CALL"] + Action = Literal["DEPLOY", "DECLARE"] Payload = Dict[str, Union[None, str, int, List[int], List[str]]] action: Action From 001f17633b70255459601ed08ba995f1afd371ec Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 17 Aug 2022 11:51:06 +0200 Subject: [PATCH 41/49] Merge branch 'feature/call_and_invoke' of https://github.com/software-mansion/protostar into feature/migrator-call-cheat --- protostar/protostar_toml/io/protostar_toml_reader.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/protostar/protostar_toml/io/protostar_toml_reader.py b/protostar/protostar_toml/io/protostar_toml_reader.py index 1117f5066a..262a5c3aaa 100644 --- a/protostar/protostar_toml/io/protostar_toml_reader.py +++ b/protostar/protostar_toml/io/protostar_toml_reader.py @@ -72,9 +72,7 @@ def _read_if_cache_miss(self) -> Dict[str, Any]: return self._cache if not self.path.is_file(): - raise NoProtostarProjectFoundException( - "No protostar.toml found in the working directory\n" f"{str(self.path)}" - ) + raise NoProtostarProjectFoundException("`protostar.toml` not found") with open(self.path, "rb") as protostar_toml_file: protostar_toml_dict = tomli.load(protostar_toml_file) From f8bd58c750138c9ec8dd35398d26155127c7f5cd Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 17 Aug 2022 11:58:10 +0200 Subject: [PATCH 42/49] rename type --- protostar/starknet_gateway/gateway_facade.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protostar/starknet_gateway/gateway_facade.py b/protostar/starknet_gateway/gateway_facade.py index 59e4d4c515..debead6876 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -18,7 +18,7 @@ from protostar.starknet_gateway.starknet_request import StarknetRequest from protostar.utils.log_color_provider import LogColorProvider -GatewayFacadeSupportedInputType = Union[List[int], Dict[str, Any]] +ContractFunctionInputType = Union[List[int], Dict[str, Any]] class TransactionException(ProtostarException): From f2b6c5cf572e8f73e650106dbd8c6a66c55f83c7 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 17 Aug 2022 11:59:52 +0200 Subject: [PATCH 43/49] remove unnecessary log color provider --- tests/integration/gateway/gateway_facade_test.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/integration/gateway/gateway_facade_test.py b/tests/integration/gateway/gateway_facade_test.py index 487c7acb24..9e97619be5 100644 --- a/tests/integration/gateway/gateway_facade_test.py +++ b/tests/integration/gateway/gateway_facade_test.py @@ -3,7 +3,6 @@ import pytest from protostar.starknet_gateway.gateway_facade import GatewayFacade -from protostar.utils.log_color_provider import LogColorProvider from tests.integration.protostar_fixture import ProtostarFixture @@ -20,8 +19,6 @@ def compiled_contract_path_fixture(protostar: ProtostarFixture) -> Path: @pytest.fixture(name="gateway_facade") def gateway_facade_fixture(devnet_gateway_url: str): - log_color_provider = LogColorProvider() - log_color_provider.is_ci_mode = False gateway_facade_builder = GatewayFacade.Builder(project_root_path=Path()) gateway_facade_builder.set_network(devnet_gateway_url) return gateway_facade_builder.build() From 265ac19533428e30386364e611bb32a470267b76 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 17 Aug 2022 12:12:45 +0200 Subject: [PATCH 44/49] remove cwd --- protostar/commands/init/init_command.py | 15 ++++----------- protostar/composition_root.py | 9 ++++----- protostar/start.py | 2 +- tests/integration/protostar_fixture.py | 8 ++++++-- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/protostar/commands/init/init_command.py b/protostar/commands/init/init_command.py index 28fc73e3ea..787b2eb817 100644 --- a/protostar/commands/init/init_command.py +++ b/protostar/commands/init/init_command.py @@ -1,5 +1,4 @@ from glob import glob -from pathlib import Path from typing import List, Optional from protostar.cli import Command @@ -18,13 +17,11 @@ def __init__( requester: InputRequester, new_project_creator: NewProjectCreator, adapted_project_creator: AdaptedProjectCreator, - cwd: Path, ) -> None: super().__init__() self._adapted_project_creator = adapted_project_creator self._new_project_creator = new_project_creator self._requester = requester - self._cwd = cwd @property def name(self) -> str: @@ -68,13 +65,9 @@ def init(self, force_adapting_existing_project: bool): else: self._new_project_creator.run() - def _can_be_protostar_project(self) -> bool: - - files_depth_3 = ( - glob(str(self._cwd / "*")) - + glob(str(self._cwd / "*" / "*")) - + glob(str(self._cwd / "*" / "*" / "*")) - ) + @staticmethod + def _can_be_protostar_project() -> bool: + files_depth_3 = glob("*") + glob("*/*") + glob("*/*/*") return any( map(lambda f: f.endswith(".cairo") or f == ".git", files_depth_3) - ) and "protostar.toml" not in glob(str(self._cwd / "*")) + ) and "protostar.toml" not in glob("*") diff --git a/protostar/composition_root.py b/protostar/composition_root.py index 0b1650ca1d..2bcbae8cde 100644 --- a/protostar/composition_root.py +++ b/protostar/composition_root.py @@ -1,7 +1,7 @@ from dataclasses import dataclass from logging import getLogger from pathlib import Path -from typing import List, Optional +from typing import List from protostar.cli import Command from protostar.commands import ( @@ -55,10 +55,10 @@ class DIContainer: # pylint: disable=too-many-locals -def build_di_container(script_root: Path, cwd: Optional[Path] = None): - cwd = cwd or Path() +def build_di_container(script_root: Path): logger = getLogger() - protostar_toml_path = search_upwards_protostar_toml_path(start_path=cwd.resolve()) + cwd = Path() + protostar_toml_path = search_upwards_protostar_toml_path(start_path=cwd) project_root_path = ( protostar_toml_path.parent if protostar_toml_path is not None else cwd ) @@ -111,7 +111,6 @@ def build_di_container(script_root: Path, cwd: Optional[Path] = None): protostar_toml_writer, version_manager, ), - cwd=cwd, ), BuildCommand(project_compiler, logger), InstallCommand( diff --git a/protostar/start.py b/protostar/start.py index fec1705b8d..09c98c2c1a 100644 --- a/protostar/start.py +++ b/protostar/start.py @@ -17,7 +17,7 @@ def main(script_root: Path): - container = build_di_container(script_root, cwd=Path()) + container = build_di_container(script_root) arg_parser = build_parser(container.protostar_cli, container.protostar_toml_reader) args = parse_args(arg_parser) run_protostar(container.protostar_cli, args, arg_parser) diff --git a/tests/integration/protostar_fixture.py b/tests/integration/protostar_fixture.py index 13dfc45c9c..c4d306bbf1 100644 --- a/tests/integration/protostar_fixture.py +++ b/tests/integration/protostar_fixture.py @@ -1,4 +1,5 @@ import asyncio +import os from argparse import Namespace from logging import getLogger from pathlib import Path @@ -43,7 +44,11 @@ def project_root_path(self) -> Path: def init_sync(self): args = Namespace() args.existing = False - return asyncio.run(self._init_command.run(args)) + cwd = Path().resolve() + os.chdir(self._project_root_path.parent) + result = asyncio.run(self._init_command.run(args)) + os.chdir(cwd) + return result def build_sync(self): args = Namespace() @@ -151,7 +156,6 @@ def request_input(message: str) -> str: input_requester, new_project_creator=new_project_creator, adapted_project_creator=mocker.MagicMock(), - cwd=project_root_path.parent, ) project_compiler = ProjectCompiler( From e5cf92a294093bd98c4defed515d5839410729be Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 17 Aug 2022 12:13:16 +0200 Subject: [PATCH 45/49] remove cwd --- scripts/generate_reference_docs_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generate_reference_docs_test.py b/scripts/generate_reference_docs_test.py index 65a1b446e2..24fd1d0a61 100644 --- a/scripts/generate_reference_docs_test.py +++ b/scripts/generate_reference_docs_test.py @@ -5,7 +5,7 @@ def test_instance_matches_cli_reference_docs(): - di_container = build_di_container(script_root=Path(), cwd=Path()) + di_container = build_di_container(script_root=Path()) new_snapshot = ReferenceDocsGenerator( di_container.protostar_cli ).generate_cli_reference_markdown() From 4eec693c97a9e57ecb0b470bafefb1c3c0199b7d Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 17 Aug 2022 12:25:46 +0200 Subject: [PATCH 46/49] fix types --- protostar/starknet_gateway/gateway_facade.py | 4 ++-- protostar/starknet_gateway/starknet_request.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/protostar/starknet_gateway/gateway_facade.py b/protostar/starknet_gateway/gateway_facade.py index a344131e26..26f946f65e 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -190,7 +190,7 @@ async def call( self, address: AddressRepresentation, function_name: str, - inputs: Optional[GatewayFacadeSupportedInputType] = None, + inputs: Optional[ContractFunctionInputType] = None, ) -> NamedTuple: register_response = self._register_request( action="CALL", @@ -222,7 +222,7 @@ async def _create_contract_function( @staticmethod async def _call_function( contract_function: ContractFunction, - inputs: Optional[GatewayFacadeSupportedInputType] = None, + inputs: Optional[ContractFunctionInputType] = None, ): if inputs is None: inputs = {} diff --git a/protostar/starknet_gateway/starknet_request.py b/protostar/starknet_gateway/starknet_request.py index 37ad489e17..537acec196 100644 --- a/protostar/starknet_gateway/starknet_request.py +++ b/protostar/starknet_gateway/starknet_request.py @@ -8,7 +8,7 @@ @dataclass class StarknetRequest: - Action = Literal["DEPLOY", "DECLARE"] + Action = Literal["DEPLOY", "DECLARE", "CALL"] Payload = Dict[str, Union[None, str, int, List[int], List[str]]] action: Action From a548c0099fce3993ab99cca534ef4a5abc8b70fd Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 17 Aug 2022 12:41:32 +0200 Subject: [PATCH 47/49] remove type --- protostar/starknet_gateway/gateway_facade.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/protostar/starknet_gateway/gateway_facade.py b/protostar/starknet_gateway/gateway_facade.py index debead6876..c720e7d68c 100644 --- a/protostar/starknet_gateway/gateway_facade.py +++ b/protostar/starknet_gateway/gateway_facade.py @@ -1,7 +1,7 @@ import dataclasses from logging import Logger from pathlib import Path -from typing import Any, Callable, Dict, List, Optional, Union +from typing import Callable, List, Optional from starknet_py.net.gateway_client import GatewayClient from starknet_py.net.models import StarknetChainId @@ -18,8 +18,6 @@ from protostar.starknet_gateway.starknet_request import StarknetRequest from protostar.utils.log_color_provider import LogColorProvider -ContractFunctionInputType = Union[List[int], Dict[str, Any]] - class TransactionException(ProtostarException): pass From 556b624b5fb55813bf9d96daf74ce31d103c7831 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 17 Aug 2022 12:49:08 +0200 Subject: [PATCH 48/49] renamed cwd to project root path --- protostar/composition_root.py | 2 +- protostar/migrator/migrator.py | 13 +++++++------ tests/integration/protostar_fixture.py | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/protostar/composition_root.py b/protostar/composition_root.py index 2bcbae8cde..760bfa509f 100644 --- a/protostar/composition_root.py +++ b/protostar/composition_root.py @@ -151,7 +151,7 @@ def build_di_container(script_root: Path): migrator_builder=Migrator.Builder( migrator_execution_environment_builder=MigratorExecutionEnvironment.Builder(), gateway_facade_builder=GatewayFacade.Builder(project_root_path), - cwd=project_root_path, + project_root_path=project_root_path, ), requester=requester, logger=logger, diff --git a/protostar/migrator/migrator.py b/protostar/migrator/migrator.py index dc421aa6a7..888837438c 100644 --- a/protostar/migrator/migrator.py +++ b/protostar/migrator/migrator.py @@ -28,7 +28,7 @@ def __init__( self, migrator_execution_environment_builder: MigratorExecutionEnvironment.Builder, gateway_facade_builder: GatewayFacade.Builder, - cwd: Optional[Path] = None, + project_root_path: Optional[Path] = None, ) -> None: self._migrator_execution_environment_builder = ( migrator_execution_environment_builder @@ -39,7 +39,7 @@ def __init__( self._migrator_execution_environment_config = ( MigratorExecutionEnvironment.Config() ) - self._cwd = cwd + self._project_root_path = project_root_path def set_logger( self, logger: Logger, log_color_provider: LogColorProvider @@ -74,15 +74,16 @@ async def build(self, migration_file_path: Path): ) return Migrator( - migrator_execution_environment=migrator_execution_env, cwd=self._cwd + migrator_execution_environment=migrator_execution_env, + project_root_path=self._project_root_path, ) def __init__( self, migrator_execution_environment: MigratorExecutionEnvironment, - cwd: Optional[Path] = None, + project_root_path: Optional[Path] = None, ) -> None: - self._cwd = cwd or Path() + self._project_root_path = project_root_path or Path() self._migrator_execution_environment = migrator_execution_environment async def run(self, rollback=False) -> History: @@ -101,7 +102,7 @@ def save_history( migration_file_basename: str, output_dir_relative_path: Path, ): - output_dir_path = self._cwd / output_dir_relative_path + output_dir_path = self._project_root_path / output_dir_relative_path prefix = datetime.strftime(datetime.now(), "%Y%m%d%H%M%S") output_file_path = output_dir_path / f"{prefix}_{migration_file_basename}.json" diff --git a/tests/integration/protostar_fixture.py b/tests/integration/protostar_fixture.py index c4d306bbf1..896ee25bc8 100644 --- a/tests/integration/protostar_fixture.py +++ b/tests/integration/protostar_fixture.py @@ -177,7 +177,7 @@ def request_input(message: str) -> str: migrator_builder = Migrator.Builder( gateway_facade_builder=gateway_facade_builder, migrator_execution_environment_builder=MigratorExecutionEnvironment.Builder(), - cwd=project_root_path, + project_root_path=project_root_path, ) migrate_command = MigrateCommand( From 3434ca1ce2fd98d27413eebc6cfb5cc544c3f951 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kasprzyk Date: Wed, 17 Aug 2022 13:22:28 +0200 Subject: [PATCH 49/49] fix e2e tests --- protostar/composition_root.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protostar/composition_root.py b/protostar/composition_root.py index 760bfa509f..5a381b66b0 100644 --- a/protostar/composition_root.py +++ b/protostar/composition_root.py @@ -57,7 +57,7 @@ class DIContainer: # pylint: disable=too-many-locals def build_di_container(script_root: Path): logger = getLogger() - cwd = Path() + cwd = Path().resolve() protostar_toml_path = search_upwards_protostar_toml_path(start_path=cwd) project_root_path = ( protostar_toml_path.parent if protostar_toml_path is not None else cwd