Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Reworked deploy and declare #573

Merged
merged 24 commits into from
Aug 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions protostar/commands/declare/declare_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
class DeclareCommand(Command):
def __init__(
self,
gateway_facade: GatewayFacade,
gateway_facade_builder: GatewayFacade.Builder,
logger: Logger,
):
self._gateway_facade = gateway_facade
self._gateway_facade_builder = gateway_facade_builder
self._logger = logger

@property
Expand Down Expand Up @@ -46,30 +46,32 @@ def arguments(self) -> List[Command.Argument]:
Command.Argument(
name="signature",
description=("Signature information for the declaration."),
type="str",
type="int",
is_array=True,
),
Command.Argument(
name="token",
description="Used for declaring contracts in Alpha MainNet.",
type="str",
),
DeployCommand.wait_for_acceptance_arg,
DeployCommand.gateway_url_arg,
DeployCommand.network_arg,
]

async def run(self, args) -> SuccessfulDeclareResponse:
assert isinstance(args.contract, Path)
assert args.network is None or isinstance(args.network, str)
assert args.gateway_url is None or isinstance(args.gateway_url, str)
assert args.network is None or isinstance(args.network, str)
assert args.token is None or isinstance(args.token, str)
assert isinstance(args.wait_for_acceptance, bool)
assert args.signature is None or isinstance(args.signature, list)

return await self.declare(
compiled_contract_path=args.contract,
network=args.network,
gateway_url=args.gateway_url,
network=args.network or args.gateway_url,
token=args.token,
wait_for_acceptance=args.wait_for_acceptance,
signature=args.signature,
)

Expand All @@ -78,21 +80,24 @@ async def declare(
self,
compiled_contract_path: Path,
network: Optional[str] = None,
gateway_url: Optional[str] = None,
token: Optional[str] = None,
signature: Optional[List[str]] = None,
wait_for_acceptance: bool = False,
signature: Optional[List[int]] = None,
) -> SuccessfulDeclareResponse:
if network is None and gateway_url is None:
if network is None:
raise ProtostarException(
f"Argument `{DeployCommand.gateway_url_arg.name}` or `{DeployCommand.network_arg.name}` is required"
)

network_config = NetworkConfig.build(network=network, gateway_url=gateway_url)
self._gateway_facade_builder.set_network(network)
gateway_facade = self._gateway_facade_builder.build()

network_config = NetworkConfig(network)

response = await self._gateway_facade.declare(
response = await gateway_facade.declare(
compiled_contract_path=compiled_contract_path,
gateway_url=network_config.gateway_url,
token=token,
wait_for_acceptance=wait_for_acceptance,
signature=signature,
)

Expand Down
32 changes: 21 additions & 11 deletions protostar/commands/deploy/deploy_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,19 @@ class DeployCommand(Command):
type="str",
)

wait_for_acceptance_arg = Command.Argument(
name="wait-for-acceptance",
description="Waits for transaction to be accepted on chain.",
type="bool",
default=False,
)

def __init__(
self,
gateway_facade: GatewayFacade,
gateway_facade_builder: GatewayFacade.Builder,
logger: Logger,
) -> None:
self._gateway_facade = gateway_facade
self._gateway_facade_builder = gateway_facade_builder
self._logger = logger

@property
Expand Down Expand Up @@ -75,12 +82,12 @@ def arguments(self) -> List[Command.Argument]:
# pylint: disable=line-too-long
"[Read more about representing Cairo data types in the CLI.](https://www.cairo-lang.org/docs/hello_starknet/more_features.html#array-arguments-in-calldata)"
),
type="str",
type="int",
is_array=True,
),
Command.Argument(
name="token",
description="Used for deploying contracts in Alpha MainNet.",
description="Used by whitelisted users for deploying contracts in Alpha MainNet.",
type="str",
),
Command.Argument(
Expand All @@ -91,28 +98,31 @@ def arguments(self) -> List[Command.Argument]:
"of contract, salt and caller. "
"If the salt is not supplied, the contract will be deployed with a random salt."
),
type="str",
type="int",
),
DeployCommand.wait_for_acceptance_arg,
DeployCommand.gateway_url_arg,
DeployCommand.network_arg,
]

async def run(self, args):
if args.network is None and args.gateway_url is None:
network = args.network or args.gateway_url
if network is None:
raise ProtostarException(
f"Argument `{DeployCommand.gateway_url_arg.name}` or `{DeployCommand.network_arg.name}` is required"
)

network_config = NetworkConfig.build(
network=args.network, gateway_url=args.gateway_url
)
network_config = NetworkConfig(network)

self._gateway_facade_builder.set_network(network)
gateway_facade = self._gateway_facade_builder.build()

response = await self._gateway_facade.deploy(
response = await gateway_facade.deploy(
compiled_contract_path=args.contract,
gateway_url=network_config.gateway_url,
inputs=args.inputs,
token=args.token,
salt=args.salt,
wait_for_acceptance=args.wait_for_acceptance,
)

explorer_url = network_config.get_contract_explorer_url(response.address)
Expand Down
40 changes: 8 additions & 32 deletions protostar/commands/migrate/migrate_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
from protostar.commands.test.test_environment_exceptions import CheatcodeException
from protostar.migrator import Migrator
from protostar.protostar_exception import ProtostarException
from protostar.starknet_gateway import NetworkConfig
from protostar.utils.input_requester import InputRequester
from protostar.utils.log_color_provider import LogColorProvider
from protostar.commands.deploy import DeployCommand


class MigrateCommand(Command):
Expand Down Expand Up @@ -65,35 +65,15 @@ def arguments(self) -> List[Command.Argument]:
description="Skip confirming building the project.",
type="bool",
),
Command.Argument(
name=MigrateCommand.GATEWAY_URL_ARG_NAME,
description="The URL of a StarkNet gateway. It is required unless `--network` is provided.",
type="str",
),
Command.Argument(
name=MigrateCommand.NETWORK_ARG_NAME,
short_name="n",
description=(
"\n".join(
[
"The name of the StarkNet network.",
"It is required unless `--gateway-url` is provided.",
"",
"Supported StarkNet networks:",
]
+ [f"- `{n}`" for n in NetworkConfig.get_starknet_networks()]
)
),
type="str",
),
DeployCommand.gateway_url_arg,
DeployCommand.network_arg,
]

async def run(self, args):
await self.migrate(
migration_file_path=args.path,
rollback=args.rollback,
gateway_url=args.gateway_url,
network=args.network,
network=args.network or args.gateway_url,
output_dir_path=args.output_dir,
no_confirm=args.no_confirm,
)
Expand All @@ -103,18 +83,15 @@ async def migrate(
self,
migration_file_path: Path,
rollback: bool,
gateway_url: Optional[str],
network: Optional[str],
output_dir_path: Optional[Path],
no_confirm: bool,
):
if network is None and gateway_url is None:
if network is None:
raise ProtostarException(
f"Argument `{MigrateCommand.GATEWAY_URL_ARG_NAME}` or `{MigrateCommand.NETWORK_ARG_NAME}` is required"
)

network_config = NetworkConfig.build(gateway_url, network)

# mitigates the risk of running migrate on an outdated project
should_confirm = not no_confirm
if should_confirm and not self._requester.confirm(
Expand All @@ -126,10 +103,9 @@ async def migrate(

self._migrator_builder.set_logger(self._logger, self._log_color_provider)

migrator = await self._migrator_builder.build(
migration_file_path,
config=Migrator.Config(gateway_url=network_config.gateway_url),
)
self._migrator_builder.set_network(network)

migrator = await self._migrator_builder.build(migration_file_path)

try:
migrator_history = await migrator.run(rollback)
Expand Down
6 changes: 2 additions & 4 deletions protostar/commands/migrate/migrate_command_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ def setup_migrate(mocker: MockerFixture):

async def migrate(no_confirm: bool):
await migrate_command.migrate(
gateway_url="http://localhost:3000/",
network=None,
network="http://localhost:3000/",
migration_file_path=Path(),
rollback=False,
output_dir_path=None,
Expand All @@ -67,8 +66,7 @@ async def test_cheatcode_exceptions_are_pretty_printed(mocker: MockerFixture):

with pytest.raises(ProtostarException, match="CHEATCODE_EX_MSG"):
await migrate_command.migrate(
gateway_url="http://localhost:3000/",
network=None,
network="http://localhost:3000/",
migration_file_path=Path(),
rollback=False,
output_dir_path=None,
Expand Down
30 changes: 18 additions & 12 deletions protostar/commands/test/cheatcodes/declare_cheatcode.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
import asyncio
from dataclasses import dataclass
from pathlib import Path
from typing import Optional, Dict

from starkware.python.utils import from_bytes
from starkware.starknet.business_logic.internal_transaction import InternalDeclare
from starkware.starknet.public.abi import AbiType
from starkware.starknet.testing.contract import DeclaredClass
from starkware.starknet.testing.contract_utils import EventManager, get_abi
from typing_extensions import Protocol

from protostar.starknet.cheatcode import Cheatcode
from protostar.utils.starknet_compilation import StarknetCompiler
from protostar.commands.test.test_environment_exceptions import (
KeywordOnlyArgumentCheatcodeException,
)


@dataclass
class DeclaredContract:
class_hash: int


class DeclareCheatcodeProtocol(Protocol):
def __call__(self, contract_path_str: str) -> DeclaredContract:
...
from protostar.migrator.cheatcodes.migrator_declare_cheatcode import (
DeclareCheatcodeProtocol,
DeclaredContract,
)


class DeclareCheatcode(Cheatcode):
Expand All @@ -39,7 +36,16 @@ def name(self) -> str:
def build(self) -> DeclareCheatcodeProtocol:
return self.declare

def declare(self, contract_path_str: str) -> DeclaredContract:
def declare(
self,
contract_path_str: str,
*args,
# pylint: disable=unused-argument
config: Optional[Dict] = None,
) -> DeclaredContract:
if len(args) > 0:
raise KeywordOnlyArgumentCheatcodeException(self.name, ["config"])

declared_class = asyncio.run(self._declare_contract(Path(contract_path_str)))
assert declared_class
class_hash = declared_class.class_hash
Expand Down
13 changes: 7 additions & 6 deletions protostar/commands/test/cheatcodes/deploy_cheatcode.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import asyncio
from dataclasses import dataclass
from typing import Any, Callable, List

from starkware.python.utils import to_bytes
Expand All @@ -9,10 +8,9 @@
from protostar.commands.test.cheatcodes.prepare_cheatcode import PreparedContract
from protostar.starknet.cheatcode import Cheatcode


@dataclass(frozen=True)
class DeployedContract:
contract_address: int
from protostar.migrator.cheatcodes.migrator_deploy_contract_cheatcode import (
DeployedContract,
)


class DeployCheatcode(Cheatcode):
Expand All @@ -32,7 +30,10 @@ def name(self) -> str:
def build(self) -> Callable[[Any], Any]:
return self.deploy_prepared

def deploy_prepared(self, prepared: PreparedContract):
def deploy_prepared(
self,
prepared: PreparedContract,
):
class_hash_bytes = to_bytes(prepared.class_hash)
future = asyncio.run_coroutine_threadsafe(
coro=initialize_contract_state(
Expand Down
31 changes: 16 additions & 15 deletions protostar/commands/test/cheatcodes/deploy_contract_cheatcode.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
from typing import Optional

from typing_extensions import Protocol
from typing import Optional, Dict

from protostar.commands.test.cheatcodes.declare_cheatcode import DeclareCheatcode
from protostar.commands.test.cheatcodes.deploy_cheatcode import (
DeployCheatcode,
DeployedContract,
)
from protostar.commands.test.cheatcodes.deploy_cheatcode import DeployCheatcode
from protostar.commands.test.cheatcodes.prepare_cheatcode import PrepareCheatcode
from protostar.starknet.cheatcode import Cheatcode
from protostar.utils.data_transformer import CairoOrPythonData
from protostar.commands.test.test_environment_exceptions import (
KeywordOnlyArgumentCheatcodeException,
)


class DeployContractCheatcodeProtocol(Protocol):
def __call__(
self,
contract_path: str,
constructor_args: Optional[CairoOrPythonData] = None,
) -> DeployedContract:
...
from protostar.migrator.cheatcodes.migrator_deploy_contract_cheatcode import (
DeployContractCheatcodeProtocol,
DeployedContract,
)


class DeployContractCheatcode(Cheatcode):
Expand All @@ -41,11 +35,18 @@ def name(self) -> str:
def build(self) -> DeployContractCheatcodeProtocol:
return self.deploy_contract

# pylint bug ?
# pylint: disable=keyword-arg-before-vararg
def deploy_contract(
self,
contract_path: str,
constructor_args: Optional[CairoOrPythonData] = None,
*args,
# pylint: disable=unused-argument
config: Optional[Dict] = None,
) -> DeployedContract:
if len(args) > 0:
raise KeywordOnlyArgumentCheatcodeException(self.name, ["config"])
declared_contract = self._declare_cheatcode.declare(contract_path)
prepared_contract = self._prepare_cheatcode.prepare(
declared_contract, constructor_args
Expand Down
Loading