diff --git a/README.md b/README.md index 5db31dd95..8c57390a4 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ Example usage: ```python from starknet_py.contract import Contract -from starknet_py.net.client_models import ResourceBounds +from starknet_py.net.client_models import ResourceBounds, ResourceBoundsMapping l1_resource_bounds = ResourceBounds( max_amount=int(1e5), max_price_per_unit=int(1e13) ) @@ -111,12 +111,12 @@ declare_result = await Contract.declare_v3( account, compiled_contract=compiled_contract, compiled_class_hash=class_hash, - l1_resource_bounds=l1_resource_bounds, + resource_bounds=resource_bounds, ) await declare_result.wait_for_acceptance() deploy_result = await declare_result.deploy_v3( - l1_resource_bounds=l1_resource_bounds, + resource_bounds=resource_bounds, ) # Wait until deployment transaction is accepted await deploy_result.wait_for_acceptance() @@ -126,13 +126,15 @@ map_contract = deploy_result.deployed_contract k, v = 13, 4324 # Adds a transaction to mutate the state of k-v store. The call goes through account proxy, because we've used # Account to create the contract object +resource_bounds = ResourceBoundsMapping( + l1_gas = ResourceBounds(max_amount=int(1e5), max_price_per_unit=int(1e13)), + l2_gas = ResourceBounds.init_with_zeros() +) await ( await map_contract.functions["put"].invoke_v3( k, v, - l1_resource_bounds=ResourceBounds( - max_amount=int(1e5), max_price_per_unit=int(1e13) - ), + resource_bounds=resource_bounds, ) ).wait_for_acceptance() @@ -150,7 +152,7 @@ calls = [ # Executes only one transaction with prepared calls transaction_response = await account.execute_v3( calls=calls, - l1_resource_bounds=l1_resource_bounds, + resource_bounds=resource_bounds, ) await account.client.wait_for_tx(transaction_response.transaction_hash) ``` diff --git a/docs/account_creation.rst b/docs/account_creation.rst index 148325376..8d4241796 100644 --- a/docs/account_creation.rst +++ b/docs/account_creation.rst @@ -33,5 +33,5 @@ Here is step by step example: If you are experiencing transaction failures with ``FEE_TRANSFER_FAILURE`` make sure that the address you are trying to deploy is prefunded with enough tokens, and verify that ``max_fee`` argument in :meth:`~starknet_py.net.account.account.Account.sign_deploy_account_v1` - or ``l1_resource_bounds`` argument in :meth:`~starknet_py.net.account.account.Account.sign_deploy_account_v3` is set + or ``resource_bounds`` argument in :meth:`~starknet_py.net.account.account.Account.sign_deploy_account_v3` is set to a high enough value. diff --git a/docs/guide/account_and_client.rst b/docs/guide/account_and_client.rst index fa111b5f1..4e966b71e 100644 --- a/docs/guide/account_and_client.rst +++ b/docs/guide/account_and_client.rst @@ -16,7 +16,7 @@ Transaction Fee All methods within the :ref:`Account` that involve on-chain modifications require either specifying a maximum transaction fee or using auto estimation. In the case of V1 and V2 transactions, the transaction fee, denoted in Wei, is configured by the ``max_fee`` parameter. -For V3 transactions, however, the fee is expressed in Fri and is determined by the ``l1_resource_bounds`` parameter. +For V3 transactions, however, the fee is expressed in Fri and is determined by the ``resource_bounds`` parameter. To enable auto estimation, set the ``auto_estimate`` parameter to ``True``. .. code-block:: python diff --git a/docs/guide/using_existing_contracts.rst b/docs/guide/using_existing_contracts.rst index 749f2aa87..69156b0c9 100644 --- a/docs/guide/using_existing_contracts.rst +++ b/docs/guide/using_existing_contracts.rst @@ -48,7 +48,7 @@ Alternatively, you can estimate fee automatically, as described in the :ref:`aut await contract.functions["put"].invoke_v1(k, v, max_fee=5000) The ``max_fee`` argument can be also defined in :meth:`~ContractFunction.prepare_invoke_v1`. Subsequently, the :meth:`~PreparedFunctionInvokeV1.invoke` method on a prepared call can be used either with ``max_fee`` omitted or with its value overridden. -The same behavior applies to :meth:`~ContractFunction.prepare_invoke_v3` and ``l1_resource_bounds``. +The same behavior applies to :meth:`~ContractFunction.prepare_invoke_v3` and ``resource_bounds``. .. code-block:: python @@ -60,7 +60,7 @@ The same behavior applies to :meth:`~ContractFunction.prepare_invoke_v3` and ``l .. warning:: For V1 transactions if ``max_fee`` is not specified at any step it will default to ``None``, - and will raise an exception when invoking a transaction, unless `auto_estimate` is specified and is set to `True`. The same applies to ``l1_resource_bounds`` and V3 transactions. + and will raise an exception when invoking a transaction, unless `auto_estimate` is specified and is set to `True`. The same applies to ``resource_bounds`` and V3 transactions. Please note you will need to have enough Wei (for V1 transaction) or Fri (for V3 transaction) in your Starknet account otherwise transaction will be rejected. diff --git a/docs/migration_guide.rst b/docs/migration_guide.rst index d6429fef5..e528d56c6 100644 --- a/docs/migration_guide.rst +++ b/docs/migration_guide.rst @@ -1,6 +1,20 @@ Migration guide =============== +****************************** +0.25.0 Migration guide +****************************** + +Version 0.25.0 of **starknet.py** comes with support for RPC 0.8.0! + +0.25.0 Targeted versions +------------------------ + +- Starknet - `0.13.3 `_ +- RPC - `0.8.0 `_ + +TODO (#1498): List changes + ****************************** 0.24.2 Migration guide ****************************** @@ -186,7 +200,7 @@ Changes in the :class:`~starknet_py.net.account.account.Account`: - :meth:`sign_declare_transaction`, :meth:`sign_declare_v2_transaction`, :meth:`sign_deploy_account_transaction` and :meth:`sign_invoke_transaction` have been renamed to :meth:`~Account.sign_declare_v1`, :meth:`~Account.sign_declare_v2`, :meth:`~Account.sign_deploy_account_v1` and :meth:`~Account.sign_invoke_v1` respectively All new functions with ``v3`` in their name operate similarly to their ``v1`` and ``v2`` counterparts. -Unlike their ``v1`` counterparts however, ``v3`` transaction fees are paid in Fri (10^-18 STRK). Therefore, ``max_fee`` parameter, which is typically set in Wei, is not applicable for ``v3`` functions. Instead, ``l1_resource_bounds`` parameter is utilized to limit the Fri amount used. +Unlike their ``v1`` counterparts however, ``v3`` transaction fees are paid in Fri (10^-18 STRK). Therefore, ``max_fee`` parameter, which is typically set in Wei, is not applicable for ``v3`` functions. Instead, ``resource_bounds`` parameter is utilized to limit the Fri amount used. The same applies to the new ``v3`` methods in the :class:`~starknet_py.contract.Contract` class. Changes in the :class:`~starknet_py.net.full_node_client.FullNodeClient`: diff --git a/starknet_py/contract.py b/starknet_py/contract.py index abab55b56..ea7ca1396 100644 --- a/starknet_py/contract.py +++ b/starknet_py/contract.py @@ -26,7 +26,13 @@ from starknet_py.hash.selector import get_selector_from_name from starknet_py.net.account.base_account import BaseAccount from starknet_py.net.client import Client -from starknet_py.net.client_models import Call, EstimatedFee, Hash, ResourceBounds, Tag +from starknet_py.net.client_models import ( + Call, + EstimatedFee, + Hash, + ResourceBoundsMapping, + Tag, +) from starknet_py.net.models import AddressRepresentation, parse_address from starknet_py.net.models.transaction import Declare, Invoke from starknet_py.net.udc_deployer.deployer import Deployer @@ -231,7 +237,7 @@ async def deploy_v3( unique: bool = True, constructor_args: Optional[Union[List, Dict]] = None, nonce: Optional[int] = None, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, auto_estimate: bool = False, ) -> "DeployResult": """ @@ -244,7 +250,7 @@ async def deploy_v3( :param unique: Determines if the contract should be salted with the account address. :param constructor_args: a ``list`` or ``dict`` of arguments for the constructor. :param nonce: Nonce of the transaction with call to deployer. - :param l1_resource_bounds: Max amount and max price per unit of L1 gas (in Fri) used when executing + :param resource_bounds: Max amount and max price per unit of L1 and L2 gas (in Fri) used when executing this transaction. :param auto_estimate: Use automatic fee estimation (not recommended, as it may lead to high costs). :return: DeployResult instance. @@ -260,7 +266,7 @@ async def deploy_v3( deployer_address=deployer_address, cairo_version=self._cairo_version, nonce=nonce, - l1_resource_bounds=l1_resource_bounds, + resource_bounds=resource_bounds, auto_estimate=auto_estimate, salt=salt, unique=unique, @@ -462,11 +468,11 @@ class PreparedFunctionInvokeV3(PreparedFunctionInvoke): Prepared date to send an InvokeV3 transaction. """ - l1_resource_bounds: Optional[ResourceBounds] + resource_bounds: Optional[ResourceBoundsMapping] async def invoke( self, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, auto_estimate: bool = False, *, nonce: Optional[int] = None, @@ -474,7 +480,7 @@ async def invoke( """ Send an Invoke transaction version 3 for the prepared data. - :param l1_resource_bounds: Max amount and max price per unit of L1 gas (in Fri) used when executing + :param resource_bounds: Max amount and max price per unit of L1 and L2 gas (in Fri) used when executing this transaction. :param auto_estimate: Use automatic fee estimation (not recommended, as it may lead to high costs). :param nonce: Nonce of the transaction. @@ -484,7 +490,7 @@ async def invoke( transaction = await self.get_account.sign_invoke_v3( calls=self, nonce=nonce, - l1_resource_bounds=l1_resource_bounds or self.l1_resource_bounds, + resource_bounds=resource_bounds or self.resource_bounds, auto_estimate=auto_estimate, ) @@ -498,7 +504,9 @@ async def estimate_fee( nonce: Optional[int] = None, ) -> EstimatedFee: tx = await self.get_account.sign_invoke_v3( - calls=self, nonce=nonce, l1_resource_bounds=ResourceBounds.init_with_zeros() + calls=self, + nonce=nonce, + resource_bounds=ResourceBoundsMapping.init_with_zeros(), ) estimate_tx = await self.get_account.sign_for_fee_estimate(transaction=tx) @@ -652,7 +660,7 @@ async def invoke_v1( def prepare_invoke_v3( self, *args, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, **kwargs, ) -> PreparedFunctionInvokeV3: """ @@ -660,7 +668,7 @@ def prepare_invoke_v3( Creates a ``PreparedFunctionInvokeV3`` instance which exposes calldata for every argument and adds more arguments when calling methods. - :param l1_resource_bounds: Max amount and max price per unit of L1 gas (in Fri) used when executing + :param resource_bounds: Max amount and max price per unit of L1 and L2 gas (in Fri) used when executing this transaction. :return: PreparedFunctionInvokeV3. """ @@ -670,7 +678,7 @@ def prepare_invoke_v3( to_addr=self.contract_data.address, calldata=calldata, selector=self.get_selector(self.name), - l1_resource_bounds=l1_resource_bounds, + resource_bounds=resource_bounds, _contract_data=self.contract_data, _client=self.client, _account=self.account, @@ -680,7 +688,7 @@ def prepare_invoke_v3( async def invoke_v3( self, *args, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, auto_estimate: bool = False, nonce: Optional[int] = None, **kwargs, @@ -689,7 +697,7 @@ async def invoke_v3( Invoke contract's function. ``*args`` and ``**kwargs`` are translated into Cairo calldata. Equivalent of ``.prepare_invoke_v3(*args, **kwargs).invoke()``. - :param l1_resource_bounds: Max amount and max price per unit of L1 gas (in Fri) used when executing + :param resource_bounds: Max amount and max price per unit of L1 and L2 gas (in Fri) used when executing this transaction. :param auto_estimate: Use automatic fee estimation (not recommended, as it may lead to high costs). :param nonce: Nonce of the transaction. @@ -697,7 +705,7 @@ async def invoke_v3( """ prepared_invoke = self.prepare_invoke_v3(*args, **kwargs) return await prepared_invoke.invoke( - l1_resource_bounds=l1_resource_bounds, + resource_bounds=resource_bounds, nonce=nonce, auto_estimate=auto_estimate, ) @@ -896,7 +904,7 @@ async def declare_v3( compiled_contract_casm: Optional[str] = None, compiled_class_hash: Optional[int] = None, nonce: Optional[int] = None, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, auto_estimate: bool = False, ) -> DeclareResult: # pylint: disable=too-many-arguments @@ -909,7 +917,7 @@ async def declare_v3( :param compiled_contract_casm: String containing the content of the starknet-sierra-compile (.casm file). :param compiled_class_hash: Hash of the compiled_contract_casm. :param nonce: Nonce of the transaction. - :param l1_resource_bounds: Max amount and max price per unit of L1 gas (in Fri) used when executing + :param resource_bounds: Max amount and max price per unit of L1 and L2 gas (in Fri) used when executing this transaction. :param auto_estimate: Use automatic fee estimation (not recommended, as it may lead to high costs). :return: DeclareResult instance. @@ -923,7 +931,7 @@ async def declare_v3( compiled_contract=compiled_contract, compiled_class_hash=compiled_class_hash, nonce=nonce, - l1_resource_bounds=l1_resource_bounds, + resource_bounds=resource_bounds, auto_estimate=auto_estimate, ) @@ -1006,7 +1014,7 @@ async def deploy_contract_v3( deployer_address: AddressRepresentation = DEFAULT_DEPLOYER_ADDRESS, cairo_version: int = 1, nonce: Optional[int] = None, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, auto_estimate: bool = False, salt: Optional[int] = None, unique: bool = True, @@ -1024,7 +1032,7 @@ async def deploy_contract_v3( :param cairo_version: Version of the Cairo in which contract is written. By default, it is set to 1. :param nonce: Nonce of the transaction. - :param l1_resource_bounds: Max amount and max price per unit of L1 gas (in Fri) used when executing + :param resource_bounds: Max amount and max price per unit of L1 and L2 gas (in Fri) used when executing this transaction. :param auto_estimate: Use automatic fee estimation (not recommended, as it may lead to high costs). :param salt: Optional salt. Random value is selected if it is not provided. @@ -1047,7 +1055,7 @@ async def deploy_contract_v3( res = await account.execute_v3( calls=deploy_call, nonce=nonce, - l1_resource_bounds=l1_resource_bounds, + resource_bounds=resource_bounds, auto_estimate=auto_estimate, ) diff --git a/starknet_py/net/account/account.py b/starknet_py/net/account/account.py index d5b7e1213..3a6a877bd 100644 --- a/starknet_py/net/account/account.py +++ b/starknet_py/net/account/account.py @@ -16,7 +16,6 @@ Calls, EstimatedFee, Hash, - ResourceBounds, ResourceBoundsMapping, SentTransactionResponse, SierraContractClass, @@ -158,12 +157,12 @@ async def _get_max_fee( async def _get_resource_bounds( self, transaction: AccountTransaction, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, auto_estimate: bool = False, ) -> ResourceBoundsMapping: - if auto_estimate and l1_resource_bounds is not None: + if auto_estimate and resource_bounds is not None: raise ValueError( - "Arguments auto_estimate and l1_resource_bounds are mutually exclusive." + "Arguments auto_estimate and resource_bounds are mutually exclusive." ) if auto_estimate: @@ -175,14 +174,12 @@ async def _get_resource_bounds( Account.ESTIMATED_UNIT_PRICE_MULTIPLIER, ) - if l1_resource_bounds is None: + if resource_bounds is None: raise ValueError( - "One of arguments: l1_resource_bounds or auto_estimate must be specified when invoking a transaction." + "One of arguments: resource_bounds or auto_estimate must be specified when invoking a transaction." ) - return ResourceBoundsMapping( - l1_gas=l1_resource_bounds, l2_gas=ResourceBounds.init_with_zeros() - ) + return resource_bounds async def _prepare_invoke( self, @@ -222,7 +219,7 @@ async def _prepare_invoke_v3( self, calls: Calls, *, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, nonce: Optional[int] = None, auto_estimate: bool = False, ) -> InvokeV3: @@ -249,7 +246,7 @@ async def _prepare_invoke_v3( ) resource_bounds = await self._get_resource_bounds( - transaction, l1_resource_bounds, auto_estimate + transaction, resource_bounds, auto_estimate ) return _add_resource_bounds_to_transaction(transaction, resource_bounds) @@ -349,12 +346,12 @@ async def sign_invoke_v3( calls: Calls, *, nonce: Optional[int] = None, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, auto_estimate: bool = False, ) -> InvokeV3: invoke_tx = await self._prepare_invoke_v3( calls, - l1_resource_bounds=l1_resource_bounds, + resource_bounds=resource_bounds, nonce=nonce, auto_estimate=auto_estimate, ) @@ -420,7 +417,7 @@ async def sign_declare_v3( compiled_class_hash: int, *, nonce: Optional[int] = None, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, auto_estimate: bool = False, ) -> DeclareV3: declare_tx = await self._make_declare_v3_transaction( @@ -429,7 +426,7 @@ async def sign_declare_v3( nonce=nonce, ) resource_bounds = await self._get_resource_bounds( - declare_tx, l1_resource_bounds, auto_estimate + declare_tx, resource_bounds, auto_estimate ) declare_tx = _add_resource_bounds_to_transaction(declare_tx, resource_bounds) @@ -539,7 +536,7 @@ async def sign_deploy_account_v3( *, constructor_calldata: Optional[List[int]] = None, nonce: int = 0, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, auto_estimate: bool = False, ) -> DeployAccountV3: # pylint: disable=too-many-arguments @@ -553,7 +550,7 @@ async def sign_deploy_account_v3( nonce=nonce, ) resource_bounds = await self._get_resource_bounds( - deploy_account_tx, l1_resource_bounds, auto_estimate + deploy_account_tx, resource_bounds, auto_estimate ) deploy_account_tx = _add_resource_bounds_to_transaction( deploy_account_tx, resource_bounds @@ -582,13 +579,13 @@ async def execute_v3( self, calls: Calls, *, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, nonce: Optional[int] = None, auto_estimate: bool = False, ) -> SentTransactionResponse: execute_transaction = await self.sign_invoke_v3( calls, - l1_resource_bounds=l1_resource_bounds, + resource_bounds=resource_bounds, nonce=nonce, auto_estimate=auto_estimate, ) @@ -693,7 +690,7 @@ async def deploy_account_v3( client: Client, constructor_calldata: Optional[List[int]] = None, nonce: int = 0, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, auto_estimate: bool = False, ) -> AccountDeploymentResult: # pylint: disable=too-many-arguments @@ -712,7 +709,7 @@ async def deploy_account_v3( :param constructor_calldata: Optional calldata to account contract constructor. If ``None`` is passed, ``[key_pair.public_key]`` will be used as calldata. :param nonce: Nonce of the transaction. - :param l1_resource_bounds: Max amount and max price per unit of L1 gas (in Fri) used when executing + :param resource_bounds: Max amount and max price per unit of L1 and L2 gas (in Fri) used when executing this transaction. :param auto_estimate: Use automatic fee estimation, not recommend as it may lead to high costs. """ @@ -739,7 +736,7 @@ async def deploy_account_v3( contract_address_salt=salt, constructor_calldata=calldata, nonce=nonce, - l1_resource_bounds=l1_resource_bounds, + resource_bounds=resource_bounds, auto_estimate=auto_estimate, ) diff --git a/starknet_py/net/account/base_account.py b/starknet_py/net/account/base_account.py index 5542a9dad..b718cf44f 100644 --- a/starknet_py/net/account/base_account.py +++ b/starknet_py/net/account/base_account.py @@ -6,7 +6,7 @@ Calls, EstimatedFee, Hash, - ResourceBounds, + ResourceBoundsMapping, SentTransactionResponse, Tag, ) @@ -145,7 +145,7 @@ async def sign_invoke_v3( calls: Calls, *, nonce: Optional[int] = None, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, auto_estimate: bool = False, ) -> InvokeV3: """ @@ -153,7 +153,7 @@ async def sign_invoke_v3( :param calls: Single call or list of calls. :param nonce: Nonce of the transaction. - :param l1_resource_bounds: Max amount and max price per unit of L1 gas used in this transaction. + :param resource_bounds: Max amount and max price per unit of L1 gas used in this transaction. :param auto_estimate: Use automatic fee estimation, not recommend as it may lead to high costs. :return: Invoke created from the calls. """ @@ -213,7 +213,7 @@ async def sign_declare_v3( compiled_class_hash: int, *, nonce: Optional[int] = None, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, auto_estimate: bool = False, ) -> DeclareV3: """ @@ -224,7 +224,7 @@ async def sign_declare_v3( :param compiled_class_hash: a class hash of the sierra compiled contract used in the declare transaction. Computed from casm compiled contract. :param nonce: Nonce of the transaction. - :param l1_resource_bounds: Max amount and max price per unit of L1 gas used in this transaction. + :param resource_bounds: Max amount and max price per unit of L1 gas used in this transaction. :param auto_estimate: Use automatic fee estimation, not recommend as it may lead to high costs. :return: Signed DeclareV3 transaction. """ @@ -263,7 +263,7 @@ async def sign_deploy_account_v3( *, constructor_calldata: Optional[List[int]] = None, nonce: int = 0, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, auto_estimate: bool = False, ) -> DeployAccountV3: # pylint: disable=too-many-arguments @@ -275,7 +275,7 @@ async def sign_deploy_account_v3( :param constructor_calldata: Calldata to be ed to contract constructor and used to calculate deployed contract address. :param nonce: Nonce of the transaction. - :param l1_resource_bounds: Max amount and max price per unit of L1 gas used in this transaction. + :param resource_bounds: Max amount and max price per unit of L1 gas used in this transaction. Enough tokens must be prefunded before sending the transaction for it to succeed. :param auto_estimate: Use automatic fee estimation, not recommend as it may lead to high costs. :return: Signed DeployAccountV3 transaction. @@ -305,7 +305,7 @@ async def execute_v3( self, calls: Calls, *, - l1_resource_bounds: Optional[ResourceBounds] = None, + resource_bounds: Optional[ResourceBoundsMapping] = None, nonce: Optional[int] = None, auto_estimate: bool = False, ) -> SentTransactionResponse: @@ -313,7 +313,7 @@ async def execute_v3( Takes calls and executes transaction. :param calls: Single call or list of calls. - :param l1_resource_bounds: Max amount and max price per unit of L1 gas used in this transaction. + :param resource_bounds: Max amount and max price per unit of L1 gas used in this transaction. :param nonce: Nonce of the transaction. :param auto_estimate: Use automatic fee estimation, not recommend as it may lead to high costs. :return: SentTransactionResponse. diff --git a/starknet_py/net/client.py b/starknet_py/net/client.py index 7ebc7eaac..d6fc20460 100644 --- a/starknet_py/net/client.py +++ b/starknet_py/net/client.py @@ -9,16 +9,19 @@ BlockStateUpdate, BlockTransactionTrace, Call, + ContractStorageKeys, DeclareTransactionResponse, DeployAccountTransactionResponse, DeprecatedContractClass, EstimatedFee, Hash, + MessageStatus, PendingBlockStateUpdate, PendingStarknetBlock, SentTransactionResponse, SierraContractClass, StarknetBlock, + StorageProofResponse, Tag, Transaction, TransactionExecutionStatus, @@ -100,6 +103,25 @@ async def get_storage_at( :return: Storage value of given contract """ + @abstractmethod + async def get_storage_proof( + self, + block_id: Union[int, Hash, Tag], + class_hashes: Optional[List[int]] = None, + contract_addresses: Optional[List[int]] = None, + contract_storage_keys: Optional[List[ContractStorageKeys]] = None, + ) -> StorageProofResponse: + """ + Get merkle paths in one of the state tries: global state, classes, individual contract. + + :param block_id: Hash of the requested block, or number (height) of the requested block, or a block tag. + :param class_hashes: List of the class hashes for which we want to prove membership in the classes trie. + :param contract_addresses: List of the contract addresses for which we want to prove membership in the + contracts trie. + :param contract_storage_keys: List of the contract address and storage keys pairs. + :return: StorageProofResponse object. + """ + @abstractmethod async def get_transaction( self, @@ -307,3 +329,14 @@ async def get_contract_nonce( @abstractmethod async def get_chain_id(self) -> str: """Return the currently configured Starknet chain id""" + + @abstractmethod + async def get_messages_status( + self, l1_transaction_hash: int + ) -> List[MessageStatus]: + """ + Get L1 handler transaction data for all L1 to L2 messages sent by the given L1 transaction. + + :param l1_transaction_hash: Hash of the L1 transaction + :return: Status of the messages + """ diff --git a/starknet_py/net/client_models.py b/starknet_py/net/client_models.py index c198d3c97..5ad74bfe0 100644 --- a/starknet_py/net/client_models.py +++ b/starknet_py/net/client_models.py @@ -381,9 +381,9 @@ class TransactionFinalityStatus(Enum): @dataclass -class DataResources: +class InnerCallExecutionResources: """ - Dataclass representing the data-availability resources of the transaction + Dataclass representing resources consumed by the internal call """ l1_gas: int @@ -391,32 +391,12 @@ class DataResources: @dataclass -class ComputationResources: - """ - Dataclass representing the resources consumed by the VM. - """ - - # pylint: disable=too-many-instance-attributes - - steps: int - memory_holes: Optional[int] - range_check_builtin_applications: Optional[int] - pedersen_builtin_applications: Optional[int] - poseidon_builtin_applications: Optional[int] - ec_op_builtin_applications: Optional[int] - ecdsa_builtin_applications: Optional[int] - bitwise_builtin_applications: Optional[int] - keccak_builtin_applications: Optional[int] - segment_arena_builtin: Optional[int] - - -@dataclass -class ExecutionResources(ComputationResources): +class ExecutionResources(InnerCallExecutionResources): """ Dataclass representing the resources consumed by the transaction, includes both computation and data. """ - data_availability: DataResources + l2_gas: int # TODO (#1219): split into PendingTransactionReceipt and TransactionReceipt @@ -618,27 +598,32 @@ class StorageDiffItem: @dataclass class EstimatedFee: + # pylint: disable=too-many-instance-attributes """ Dataclass representing estimated fee. """ - gas_consumed: int - gas_price: int - data_gas_consumed: int - data_gas_price: int + l1_gas_consumed: int + l1_gas_price: int + l2_gas_consumed: int + l2_gas_price: int + l1_data_gas_consumed: int + l1_data_gas_price: int overall_fee: int unit: PriceUnit + # TODO (#1498): Decrease multipliers def to_resource_bounds( self, amount_multiplier=1.5, unit_price_multiplier=1.5 ) -> ResourceBoundsMapping: """ Converts estimated fee to resource bounds with applied multipliers. - Calculates max amount as `max_amount` = `overall_fee` / `gas_price`, unless `gas_price` is 0, - then `max_amount` is 0. Calculates max price per unit as `max_price_per_unit` = `gas_price`. + Calculates L1 max amount as `l1_gas_consumed` * `amount_multiplier`. + Calculates L1 max price per unit as `l1_gas_price` * `unit_price_multiplier`. - Then multiplies `max_amount` by `amount_multiplier` and `max_price_per_unit` by `unit_price_multiplier`. + Calculates L2 max amount as `l2_gas_consumed` * `amount_multiplier`. + Calculates L2 max price per unit as `l2_gas_price` * `unit_price_multiplier`. :param amount_multiplier: Multiplier for max amount, defaults to 1.5. :param unit_price_multiplier: Multiplier for max price per unit, defaults to 1.5. @@ -651,16 +636,17 @@ def to_resource_bounds( ) l1_resource_bounds = ResourceBounds( - max_amount=int( - (self.overall_fee / self.gas_price) * amount_multiplier - if self.gas_price != 0 - else 0 - ), - max_price_per_unit=int(self.gas_price * unit_price_multiplier), + max_amount=int(self.l1_gas_consumed * amount_multiplier), + max_price_per_unit=int(self.l1_gas_price * unit_price_multiplier), + ) + + l2_resource_bounds = ResourceBounds( + max_amount=int(self.l2_gas_consumed * amount_multiplier), + max_price_per_unit=int(self.l2_gas_price * unit_price_multiplier), ) return ResourceBoundsMapping( - l1_gas=l1_resource_bounds, l2_gas=ResourceBounds.init_with_zeros() + l1_gas=l1_resource_bounds, l2_gas=l2_resource_bounds ) @@ -944,6 +930,7 @@ class TransactionStatusResponse: finality_status: TransactionStatus execution_status: Optional[TransactionExecutionStatus] = None + failure_reason: Optional[str] = None # ------------------------------- Trace API dataclasses ------------------------------- @@ -1019,7 +1006,7 @@ class FunctionInvocation: calls: List["FunctionInvocation"] events: List[OrderedEvent] messages: List[OrderedMessage] - computation_resources: ComputationResources + execution_resources: InnerCallExecutionResources @dataclass @@ -1106,3 +1093,85 @@ class BlockTransactionTrace: transaction_hash: int trace_root: TransactionTrace + + +@dataclass +class BinaryNode: + """ + Dataclass representing an internal node whose both children are non-zero. + """ + + left: int + right: int + + +@dataclass +class EdgeNode: + """ + Dataclass representing a path to the highest non-zero descendant node. + """ + + path: int + length: int + child: int + + +MerkleNode = Union[BinaryNode, EdgeNode] + + +@dataclass +class NodeHashToNodeMappingItem: + node_hash: int + node: MerkleNode + + +NodeHashToNodeMapping = List[NodeHashToNodeMappingItem] + + +@dataclass +class ContractStorageKeys: + """ + Dataclass representing a pair of contract address and storage keys. + """ + + contract_address: int + storage_keys: List[int] + + +@dataclass +class ContractLeafData: + nonce: int + class_hash: int + + +@dataclass +class GlobalRoots: + contracts_tree_root: int + classes_tree_root: int + block_hash: int + + +@dataclass +class ContractsProof: + nodes: NodeHashToNodeMapping + contract_leaves_data: List[ContractLeafData] + contracts_storage_proof: NodeHashToNodeMapping + + +@dataclass +class StorageProofResponse: + """ + Dataclass representing a response to a storage proof request. + """ + + classes_proof: NodeHashToNodeMapping + contracts_proof: ContractsProof + contracts_storage_proofs: List[NodeHashToNodeMapping] + global_roots: GlobalRoots + + +@dataclass +class MessageStatus: + transaction_hash: int + finality_status: TransactionFinalityStatus + failure_reason: Optional[str] = None diff --git a/starknet_py/net/client_utils.py b/starknet_py/net/client_utils.py index 27a86ff3b..6a57cb993 100644 --- a/starknet_py/net/client_utils.py +++ b/starknet_py/net/client_utils.py @@ -1,5 +1,5 @@ import re -from typing import Dict, Union, cast +from typing import Any, Dict, Union, cast from typing_extensions import get_args @@ -86,3 +86,7 @@ def _create_broadcasted_txn(transaction: AccountTransaction) -> dict: Dict, BroadcastedTransactionSchema().dump(obj=transaction), ) + + +def _clear_none_values(input_dict: Dict[str, Any]): + return {key: value for key, value in input_dict.items() if value is not None} diff --git a/starknet_py/net/full_node_client.py b/starknet_py/net/full_node_client.py index 5137d9e4c..dd1c9b1c8 100644 --- a/starknet_py/net/full_node_client.py +++ b/starknet_py/net/full_node_client.py @@ -11,6 +11,7 @@ BlockStateUpdate, BlockTransactionTrace, Call, + ContractStorageKeys, DeclareTransactionResponse, DeployAccountTransactionResponse, DeprecatedContractClass, @@ -18,6 +19,7 @@ EventsChunk, Hash, L1HandlerTransaction, + MessageStatus, PendingBlockStateUpdate, PendingStarknetBlock, PendingStarknetBlockWithReceipts, @@ -29,6 +31,7 @@ StarknetBlock, StarknetBlockWithReceipts, StarknetBlockWithTxHashes, + StorageProofResponse, SyncStatus, Tag, Transaction, @@ -37,6 +40,7 @@ TransactionTrace, ) from starknet_py.net.client_utils import ( + _clear_none_values, _create_broadcasted_txn, _is_valid_eth_address, _to_rpc_felt, @@ -68,6 +72,7 @@ ) from starknet_py.net.schemas.rpc.event import EventsChunkSchema from starknet_py.net.schemas.rpc.general import EstimatedFeeSchema +from starknet_py.net.schemas.rpc.storage_proof import StorageProofResponseSchema from starknet_py.net.schemas.rpc.trace_api import ( BlockTransactionTraceSchema, SimulatedTransactionSchema, @@ -76,6 +81,7 @@ from starknet_py.net.schemas.rpc.transactions import ( DeclareTransactionResponseSchema, DeployAccountTransactionResponseSchema, + MessageStatusSchema, SentTransactionSchema, TransactionReceiptSchema, TransactionStatusResponseSchema, @@ -325,6 +331,27 @@ async def get_storage_at( res = cast(str, res) return int(res, 16) + async def get_storage_proof( + self, + block_id: Union[int, Hash, Tag], + class_hashes: Optional[List[int]] = None, + contract_addresses: Optional[List[int]] = None, + contract_storage_keys: Optional[List[ContractStorageKeys]] = None, + ) -> StorageProofResponse: + params = { + "block_id": block_id, + "class_hashes": class_hashes, + "contract_addresses": contract_addresses, + "contract_storage_keys": contract_storage_keys, + } + params = _clear_none_values(params) + + res = await self._client.call( + method_name="getStorageProof", + params=params, + ) + return cast(StorageProofResponse, StorageProofResponseSchema().load(res)) + async def get_transaction( self, tx_hash: Hash, @@ -456,6 +483,18 @@ async def get_block_hash_and_number(self) -> BlockHashAndNumber: async def get_chain_id(self) -> str: return await self._client.call(method_name="chainId", params={}) + async def get_messages_status( + self, l1_transaction_hash: int + ) -> List[MessageStatus]: + res = await self._client.call( + method_name="getMessagesStatus", + params={"l1_transaction_hash": l1_transaction_hash}, + ) + return cast( + List[MessageStatus], + MessageStatusSchema().load(res, many=True), + ) + async def get_syncing_status(self) -> Union[bool, SyncStatus]: """Returns an object about the sync status, or false if the node is not syncing""" sync_status = await self._client.call(method_name="syncing", params={}) diff --git a/starknet_py/net/schemas/rpc/general.py b/starknet_py/net/schemas/rpc/general.py index e22488988..aeafafda2 100644 --- a/starknet_py/net/schemas/rpc/general.py +++ b/starknet_py/net/schemas/rpc/general.py @@ -1,61 +1,25 @@ from marshmallow import fields, post_load from starknet_py.net.client_models import ( - ComputationResources, - DataResources, EstimatedFee, ExecutionResources, + InnerCallExecutionResources, ) from starknet_py.net.schemas.common import Felt, PriceUnitField from starknet_py.utils.schema import Schema -class ComputationResourcesSchema(Schema): - steps = fields.Integer(data_key="steps", required=True) - memory_holes = fields.Integer(data_key="memory_holes", load_default=None) - range_check_builtin_applications = fields.Integer( - data_key="range_check_builtin_applications", load_default=None - ) - pedersen_builtin_applications = fields.Integer( - data_key="pedersen_builtin_applications", load_default=None - ) - poseidon_builtin_applications = fields.Integer( - data_key="poseidon_builtin_applications", load_default=None - ) - ec_op_builtin_applications = fields.Integer( - data_key="ec_op_builtin_applications", load_default=None - ) - ecdsa_builtin_applications = fields.Integer( - data_key="ecdsa_builtin_applications", load_default=None - ) - bitwise_builtin_applications = fields.Integer( - data_key="bitwise_builtin_applications", load_default=None - ) - keccak_builtin_applications = fields.Integer( - data_key="keccak_builtin_applications", load_default=None - ) - segment_arena_builtin = fields.Integer( - data_key="segment_arena_builtin", load_default=None - ) - - @post_load - def make_dataclass(self, data, **kwargs) -> ComputationResources: - return ComputationResources(**data) - - -class DataResourcesSchema(Schema): +class InnerCallExecutionResourcesSchema(Schema): l1_gas = fields.Integer(data_key="l1_gas", required=True) l1_data_gas = fields.Integer(data_key="l1_data_gas", required=True) @post_load - def make_dataclass(self, data, **kwargs) -> DataResources: - return DataResources(**data) + def make_dataclass(self, data, **kwargs) -> InnerCallExecutionResources: + return InnerCallExecutionResources(**data) -class ExecutionResourcesSchema(ComputationResourcesSchema): - data_availability = fields.Nested( - DataResourcesSchema(), data_key="data_availability", required=True - ) +class ExecutionResourcesSchema(InnerCallExecutionResourcesSchema): + l2_gas = fields.Integer(data_key="l2_gas", required=True) @post_load def make_dataclass(self, data, **kwargs) -> ExecutionResources: @@ -63,10 +27,12 @@ def make_dataclass(self, data, **kwargs) -> ExecutionResources: class EstimatedFeeSchema(Schema): - gas_consumed = Felt(data_key="gas_consumed", required=True) - gas_price = Felt(data_key="gas_price", required=True) - data_gas_consumed = Felt(data_key="data_gas_consumed", required=True) - data_gas_price = Felt(data_key="data_gas_price", required=True) + l1_gas_consumed = Felt(data_key="l1_gas_consumed", required=True) + l1_gas_price = Felt(data_key="l1_gas_price", required=True) + l2_gas_consumed = Felt(data_key="l2_gas_consumed", required=True) + l2_gas_price = Felt(data_key="l2_gas_price", required=True) + l1_data_gas_consumed = Felt(data_key="l1_data_gas_consumed", required=True) + l1_data_gas_price = Felt(data_key="l1_data_gas_price", required=True) overall_fee = Felt(data_key="overall_fee", required=True) unit = PriceUnitField(data_key="unit", required=True) diff --git a/starknet_py/net/schemas/rpc/storage_proof.py b/starknet_py/net/schemas/rpc/storage_proof.py new file mode 100644 index 000000000..cc7b26a4e --- /dev/null +++ b/starknet_py/net/schemas/rpc/storage_proof.py @@ -0,0 +1,132 @@ +from typing import Any, Optional, Union + +from marshmallow import ValidationError, fields, post_load + +from starknet_py.net.client_models import ( + BinaryNode, + ContractLeafData, + ContractsProof, + EdgeNode, + GlobalRoots, + NodeHashToNodeMappingItem, + StorageProofResponse, +) +from starknet_py.net.schemas.common import Felt, NumberAsHex +from starknet_py.utils.schema import Schema + + +class BinaryNodeSchema(Schema): + left = fields.Integer(data_key="left", required=True) + right = fields.Integer(data_key="right", required=True) + + @post_load + def make_dataclass(self, data, **kwargs) -> BinaryNode: + return BinaryNode(**data) + + +class EdgeNodeSchema(Schema): + path = NumberAsHex(data_key="path", required=True) + length = fields.Integer(data_key="length", required=True) + child = Felt(data_key="child", required=True) + + @post_load + def make_dataclass(self, data, **kwargs) -> EdgeNode: + return EdgeNode(**data) + + +class MerkleNodeSchema(Schema): + @post_load + def make_dataclass(self, data, **kwargs) -> Union[BinaryNode, EdgeNode]: + # pylint: disable=no-self-use + binary_node_keys = set(BinaryNodeSchema().fields.keys()) + edge_node_keys = set(EdgeNodeSchema().fields.keys()) + + data_keys = set(data.keys()) + + if data_keys == binary_node_keys: + return BinaryNode(**data) + elif data_keys == edge_node_keys: + return EdgeNode(**data) + raise ValidationError(f"Invalid data provided for MerkleNode: {data}.") + + +class NodeHashToNodeMappingField(fields.Field): + def _serialize(self, value: Any, attr: Optional[str], obj: Any, **kwargs): + if value is None: + return None + if not isinstance(value, list): + raise ValidationError( + f"Invalid value provided for NodeHashToNodeMapping: {value}. Expected a list." + ) + return [NodeHashToNodeMappingItemSchema().dump(item) for item in value] + + def _deserialize(self, value: Any, attr: Optional[str], data: Any, **kwargs): + if value is None: + return None + if not isinstance(value, list): + raise ValidationError( + f"Invalid value provided for NodeHashToNodeMapping: {value}. Expected a list." + ) + return [NodeHashToNodeMappingItemSchema().load(item) for item in value] + + +class NodeHashToNodeMappingItemSchema(Schema): + node_hash = Felt(data_key="node_hash", required=True) + node = fields.Nested(MerkleNodeSchema(), data_key="node", required=True) + + @post_load + def make_dataclass(self, data, **kwargs) -> NodeHashToNodeMappingItem: + return NodeHashToNodeMappingItem(**data) + + +class ContractLeafDataSchema(Schema): + nonce = Felt(data_key="nonce", required=True) + class_hash = Felt(data_key="class_hash", required=True) + + @post_load + def make_dataclass(self, data, **kwargs) -> ContractLeafData: + return ContractLeafData(**data) + + +class GlobalRootsSchema(Schema): + contracts_tree_root = fields.Integer(data_key="contracts_tree_root", required=True) + classes_tree_root = fields.Integer(data_key="classes_tree_root", required=True) + block_hash = fields.Integer(data_key="block_hash", required=True) + + @post_load + def make_dataclass(self, data, **kwargs) -> GlobalRoots: + return GlobalRoots(**data) + + +class ContractsProofSchema(Schema): + nodes = NodeHashToNodeMappingField(data_key="nodes", required=True) + contract_leaves_data = fields.List( + fields.Nested(ContractLeafDataSchema()), + data_key="contract_leaves_data", + required=True, + ) + + @post_load + def make_dataclass(self, data, **kwargs) -> ContractsProof: + return ContractsProof(**data) + + +class StorageProofResponseSchema(Schema): + classes_proof = fields.List( + fields.Nested(NodeHashToNodeMappingItemSchema()), + data_key="classes_proof", + required=True, + ) + contracts_proof = fields.Nested( + ContractsProofSchema(), data_key="contracts_proof", required=True + ) + contracts_storage_proofs = fields.List( + NodeHashToNodeMappingField(), data_key="contracts_storage_proofs", required=True + ) + global_roots = fields.Nested( + GlobalRootsSchema(), data_key="global_roots", required=True + ) + + @post_load + def make_dataclass(self, data, **kwargs) -> StorageProofResponse: + return StorageProofResponse(**data) diff --git a/starknet_py/net/schemas/rpc/trace_api.py b/starknet_py/net/schemas/rpc/trace_api.py index 3e9b392c4..015cb204a 100644 --- a/starknet_py/net/schemas/rpc/trace_api.py +++ b/starknet_py/net/schemas/rpc/trace_api.py @@ -16,9 +16,9 @@ from starknet_py.net.schemas.common import CallTypeField, EntryPointTypeField, Felt from starknet_py.net.schemas.rpc.block import StateDiffSchema from starknet_py.net.schemas.rpc.general import ( - ComputationResourcesSchema, EstimatedFeeSchema, ExecutionResourcesSchema, + InnerCallExecutionResourcesSchema, ) from starknet_py.utils.schema import Schema @@ -67,8 +67,10 @@ class FunctionInvocationSchema(Schema): messages = fields.List( fields.Nested(OrderedMessageSchema()), data_key="messages", required=True ) - computation_resources = fields.Nested( - ComputationResourcesSchema(), data_key="execution_resources", required=True + execution_resources = fields.Nested( + InnerCallExecutionResourcesSchema(), + data_key="execution_resources", + required=True, ) @post_load diff --git a/starknet_py/net/schemas/rpc/transactions.py b/starknet_py/net/schemas/rpc/transactions.py index f96cc82d2..62b2c7bcf 100644 --- a/starknet_py/net/schemas/rpc/transactions.py +++ b/starknet_py/net/schemas/rpc/transactions.py @@ -18,6 +18,7 @@ InvokeTransactionV3, L1HandlerTransaction, L2toL1Message, + MessageStatus, ResourceBounds, ResourceBoundsMapping, SentTransactionResponse, @@ -94,6 +95,7 @@ class TransactionStatusResponseSchema(Schema): execution_status = ExecutionStatusField( data_key="execution_status", load_default=None ) + failure_reason = fields.String(data_key="failure_reason", load_default=None) @post_load def make_dataclass(self, data, **kwargs) -> TransactionStatusResponse: @@ -350,3 +352,13 @@ class DeployAccountTransactionResponseSchema(SentTransactionSchema): @post_load def make_dataclass(self, data, **kwargs) -> DeployAccountTransactionResponse: return DeployAccountTransactionResponse(**data) + + +class MessageStatusSchema(Schema): + transaction_hash = NumberAsHex(data_key="transaction_hash", required=True) + finality_status = FinalityStatusField(data_key="finality_status", required=True) + failure_reason = fields.String(data_key="failure_reason", load_default=None) + + @post_load + def make_dataclass(self, data, **kwargs) -> MessageStatus: + return MessageStatus(**data) diff --git a/starknet_py/tests/e2e/account/account_test.py b/starknet_py/tests/e2e/account/account_test.py index 54a249841..270073090 100644 --- a/starknet_py/tests/e2e/account/account_test.py +++ b/starknet_py/tests/e2e/account/account_test.py @@ -33,11 +33,7 @@ ) from starknet_py.net.signer.stark_curve_signer import KeyPair from starknet_py.net.udc_deployer.deployer import Deployer -from starknet_py.tests.e2e.fixtures.constants import ( - MAX_FEE, - MAX_RESOURCE_BOUNDS, - MAX_RESOURCE_BOUNDS_L1, -) +from starknet_py.tests.e2e.fixtures.constants import MAX_FEE, MAX_RESOURCE_BOUNDS @pytest.mark.run_on_devnet @@ -95,7 +91,7 @@ async def test_estimate_fee_for_declare_transaction( declare_tx = await account.sign_declare_v3( compiled_contract=compiled_contract, compiled_class_hash=class_hash, - l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1, + resource_bounds=MAX_RESOURCE_BOUNDS, ) estimated_fee = await account.client.estimate_fee(tx=declare_tx) @@ -117,7 +113,7 @@ async def test_account_estimate_fee_for_declare_transaction( declare_tx = await account.sign_declare_v3( compiled_contract=compiled_contract, compiled_class_hash=class_hash, - l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1, + resource_bounds=MAX_RESOURCE_BOUNDS, ) estimated_fee = await account.estimate_fee(tx=declare_tx) @@ -134,16 +130,15 @@ async def test_account_estimate_fee_for_declare_transaction( @pytest.mark.asyncio async def test_account_estimate_fee_for_transactions(account, map_contract): - invoke_tx_1 = await account.sign_invoke_v3( calls=Call(map_contract.address, get_selector_from_name("put"), [3, 4]), - l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1, + resource_bounds=MAX_RESOURCE_BOUNDS, nonce=(await account.get_nonce()), ) invoke_tx_2 = await account.sign_invoke_v3( calls=Call(map_contract.address, get_selector_from_name("put"), [5, 1]), - l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1, + resource_bounds=MAX_RESOURCE_BOUNDS, nonce=(await account.get_nonce() + 1), ) @@ -265,9 +260,7 @@ async def test_sign_invoke_v1_auto_estimate(account, map_contract): "calls", [[Call(10, 20, [30])], [Call(10, 20, [30]), Call(40, 50, [60])]] ) async def test_sign_invoke_v3(account, calls): - signed_tx = await account.sign_invoke_v3( - calls, l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1 - ) + signed_tx = await account.sign_invoke_v3(calls, resource_bounds=MAX_RESOURCE_BOUNDS) assert isinstance(signed_tx, InvokeV3) assert isinstance(signed_tx.signature, list) @@ -347,11 +340,10 @@ async def test_sign_declare_v3( compiled_contract, compiled_class_hash, ) = sierra_minimal_compiled_contract_and_class_hash - signed_tx = await account.sign_declare_v3( compiled_contract, compiled_class_hash, - l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1, + ource_bounds=MAX_RESOURCE_BOUNDS, ) assert isinstance(signed_tx, DeclareV3) @@ -432,7 +424,7 @@ async def test_sign_deploy_account_v3(account): signed_tx = await account.sign_deploy_account_v3( class_hash, salt, - l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1, + resource_bounds=MAX_RESOURCE_BOUNDS, constructor_calldata=calldata, ) @@ -521,7 +513,7 @@ async def test_deploy_account_v3(client, deploy_account_details_factory): salt=salt, key_pair=key_pair, client=client, - l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1, + resource_bounds=MAX_RESOURCE_BOUNDS, ) await deploy_result.wait_for_acceptance() @@ -661,7 +653,7 @@ async def test_sign_invoke_v1_for_fee_estimation(account, map_contract): async def test_sign_invoke_v3_for_fee_estimation(account, map_contract): call = map_contract.functions["put"].prepare_invoke_v3(key=1, value=2) transaction = await account.sign_invoke_v3( - calls=call, l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1 + calls=call, resource_bounds=MAX_RESOURCE_BOUNDS ) estimate_fee_transaction = await account.sign_for_fee_estimate(transaction) @@ -826,7 +818,7 @@ async def test_account_execute_v3(account, deployed_balance_contract): (initial_balance,) = await account.client.call_contract(call=get_balance_call) execute_increase_balance = await account.execute_v3( - calls=increase_balance_call, l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1 + calls=increase_balance_call, resource_bounds=MAX_RESOURCE_BOUNDS ) receipt = await account.client.wait_for_tx( tx_hash=execute_increase_balance.transaction_hash diff --git a/starknet_py/tests/e2e/client/client_test.py b/starknet_py/tests/e2e/client/client_test.py index 5d140b695..bc4ddc4a8 100644 --- a/starknet_py/tests/e2e/client/client_test.py +++ b/starknet_py/tests/e2e/client/client_test.py @@ -19,7 +19,7 @@ InvokeTransactionV3, L1HandlerTransaction, PriceUnit, - ResourceBounds, + ResourceBoundsMapping, SierraContractClass, SierraEntryPointsByType, TransactionExecutionStatus, @@ -120,6 +120,18 @@ async def test_get_storage_at(client, contract_address): assert storage == 1897 +@pytest.mark.asyncio +async def test_get_storage_proof(): + # TODO (#1498): Add test for get_storage_proof + pass + + +@pytest.mark.asyncio +async def test_get_messages_status(): + # TODO (#1498): Add test for get_messages_status + pass + + @pytest.mark.asyncio async def test_get_transaction_receipt( client, invoke_transaction_hash, block_with_invoke_number @@ -147,10 +159,12 @@ async def test_estimate_fee_invoke(account, contract_address): assert isinstance(estimate_fee, EstimatedFee) assert estimate_fee.unit == PriceUnit.WEI assert estimate_fee.overall_fee > 0 - assert estimate_fee.gas_price > 0 - assert estimate_fee.gas_consumed > 0 - assert estimate_fee.data_gas_price > 0 - assert estimate_fee.data_gas_consumed > 0 + assert estimate_fee.l1_gas_price > 0 + assert estimate_fee.l1_gas_consumed > 0 + assert estimate_fee.l2_gas_price > 0 + assert estimate_fee.l2_gas_consumed > 0 + assert estimate_fee.l1_data_gas_price > 0 + assert estimate_fee.l1_data_gas_consumed > 0 @pytest.mark.asyncio @@ -161,7 +175,7 @@ async def test_estimate_fee_invoke_v3(account, contract_address): selector=get_selector_from_name("increase_balance"), calldata=[1000], ), - l1_resource_bounds=ResourceBounds.init_with_zeros(), + resource_bounds=ResourceBoundsMapping.init_with_zeros(), ) invoke_tx = await account.sign_for_fee_estimate(invoke_tx) estimate_fee = await account.client.estimate_fee(tx=invoke_tx) @@ -169,10 +183,12 @@ async def test_estimate_fee_invoke_v3(account, contract_address): assert isinstance(estimate_fee, EstimatedFee) assert estimate_fee.unit == PriceUnit.FRI assert estimate_fee.overall_fee > 0 - assert estimate_fee.gas_price > 0 - assert estimate_fee.gas_consumed > 0 - assert estimate_fee.data_gas_price > 0 - assert estimate_fee.data_gas_consumed > 0 + assert estimate_fee.l1_gas_price > 0 + assert estimate_fee.l1_gas_consumed > 0 + assert estimate_fee.l2_gas_price > 0 + assert estimate_fee.l2_gas_consumed > 0 + assert estimate_fee.l1_data_gas_price > 0 + assert estimate_fee.l1_data_gas_consumed > 0 @pytest.mark.asyncio @@ -191,10 +207,12 @@ async def test_estimate_fee_declare( assert isinstance(estimate_fee, EstimatedFee) assert estimate_fee.unit == PriceUnit.WEI assert estimate_fee.overall_fee > 0 - assert estimate_fee.gas_price > 0 - assert estimate_fee.gas_consumed > 0 - assert estimate_fee.data_gas_price > 0 - assert estimate_fee.data_gas_consumed > 0 + assert estimate_fee.l1_gas_price > 0 + assert estimate_fee.l1_gas_consumed > 0 + assert estimate_fee.l2_gas_price > 0 + assert estimate_fee.l2_gas_consumed > 0 + assert estimate_fee.l1_data_gas_price > 0 + assert estimate_fee.l1_data_gas_consumed > 0 @pytest.mark.asyncio @@ -204,10 +222,12 @@ async def test_estimate_fee_deploy_account(client, deploy_account_transaction): assert isinstance(estimate_fee, EstimatedFee) assert estimate_fee.unit == PriceUnit.WEI assert estimate_fee.overall_fee > 0 - assert estimate_fee.gas_price > 0 - assert estimate_fee.gas_consumed > 0 - assert estimate_fee.data_gas_price > 0 - assert estimate_fee.data_gas_consumed > 0 + assert estimate_fee.l1_gas_price > 0 + assert estimate_fee.l1_gas_consumed > 0 + assert estimate_fee.l2_gas_price > 0 + assert estimate_fee.l2_gas_consumed > 0 + assert estimate_fee.l1_data_gas_price > 0 + assert estimate_fee.l1_data_gas_consumed >= 0 @pytest.mark.asyncio @@ -234,10 +254,12 @@ async def test_estimate_fee_for_multiple_transactions( assert isinstance(estimated_fee, EstimatedFee) assert estimated_fee.unit == PriceUnit.WEI assert estimated_fee.overall_fee > 0 - assert estimated_fee.gas_price > 0 - assert estimated_fee.gas_consumed > 0 - assert estimated_fee.data_gas_price > 0 - assert estimated_fee.data_gas_consumed > 0 + assert estimated_fee.l1_gas_price > 0 + assert estimated_fee.l1_gas_consumed > 0 + assert estimated_fee.l2_gas_price > 0 + assert estimated_fee.l2_gas_consumed > 0 + assert estimated_fee.l1_data_gas_price > 0 + assert estimated_fee.l1_data_gas_consumed > 0 @pytest.mark.asyncio diff --git a/starknet_py/tests/e2e/client/fixtures/prepare_net_for_gateway_test.py b/starknet_py/tests/e2e/client/fixtures/prepare_net_for_gateway_test.py index 94587985a..bb0160c88 100755 --- a/starknet_py/tests/e2e/client/fixtures/prepare_net_for_gateway_test.py +++ b/starknet_py/tests/e2e/client/fixtures/prepare_net_for_gateway_test.py @@ -2,7 +2,7 @@ from starknet_py.contract import Contract from starknet_py.net.account.account import Account -from starknet_py.tests.e2e.fixtures.constants import MAX_RESOURCE_BOUNDS_L1 +from starknet_py.tests.e2e.fixtures.constants import MAX_RESOURCE_BOUNDS from starknet_py.tests.e2e.utils import ( AccountToBeDeployedDetails, get_deploy_account_transaction, @@ -38,7 +38,7 @@ async def prepare_net_for_tests( block_with_declare_hash = declare_receipt.block_hash invoke_res = await contract.functions["increase_balance"].invoke_v3( - amount=1777, l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1 + amount=1777, resource_bounds=MAX_RESOURCE_BOUNDS ) await invoke_res.wait_for_acceptance() diff --git a/starknet_py/tests/e2e/client/fixtures/prepare_network.py b/starknet_py/tests/e2e/client/fixtures/prepare_network.py index ed7f049b8..424b164bc 100644 --- a/starknet_py/tests/e2e/client/fixtures/prepare_network.py +++ b/starknet_py/tests/e2e/client/fixtures/prepare_network.py @@ -14,7 +14,7 @@ prepare_net_for_tests, ) from starknet_py.tests.e2e.fixtures.accounts import AccountToBeDeployedDetailsFactory -from starknet_py.tests.e2e.fixtures.constants import MAX_RESOURCE_BOUNDS_L1 +from starknet_py.tests.e2e.fixtures.constants import MAX_RESOURCE_BOUNDS from starknet_py.tests.e2e.fixtures.contracts_v1 import declare_contract from starknet_py.tests.e2e.fixtures.misc import load_contract @@ -37,11 +37,12 @@ async def deployed_balance_contract( balance_abi, ) -> Contract: class_hash, _ = balance_class_and_transaction_hash + deploy_result = await Contract.deploy_contract_v3( account=account, abi=balance_abi, class_hash=class_hash, - l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1, + resource_bounds=MAX_RESOURCE_BOUNDS, ) await deploy_result.wait_for_acceptance() diff --git a/starknet_py/tests/e2e/contract_interaction/declare_test.py b/starknet_py/tests/e2e/contract_interaction/declare_test.py index 221028a46..1e8b55393 100644 --- a/starknet_py/tests/e2e/contract_interaction/declare_test.py +++ b/starknet_py/tests/e2e/contract_interaction/declare_test.py @@ -1,6 +1,7 @@ import pytest from starknet_py.contract import Contract +from starknet_py.net.client_models import ResourceBounds, ResourceBoundsMapping from starknet_py.tests.e2e.fixtures.constants import MAX_FEE, MAX_RESOURCE_BOUNDS_L1 from starknet_py.tests.e2e.fixtures.misc import load_contract @@ -21,8 +22,12 @@ async def test_throws_when_cairo1_without_compiled_contract_casm_and_class_hash( ) with pytest.raises(ValueError, match=error_message): + resource_bounds = ResourceBoundsMapping( + l1_gas=MAX_RESOURCE_BOUNDS_L1, + l2_gas=ResourceBounds.init_with_zeros(), + ) await Contract.declare_v3( account, compiled_contract=compiled_contract, - l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1, + resource_bounds=resource_bounds, ) diff --git a/starknet_py/tests/e2e/contract_interaction/deploy_test.py b/starknet_py/tests/e2e/contract_interaction/deploy_test.py index c623d3325..163bea400 100644 --- a/starknet_py/tests/e2e/contract_interaction/deploy_test.py +++ b/starknet_py/tests/e2e/contract_interaction/deploy_test.py @@ -8,7 +8,7 @@ from starknet_py.contract import Contract, DeclareResult from starknet_py.net.client_models import InvokeTransactionV1 from starknet_py.net.models import DeclareV2 -from starknet_py.tests.e2e.fixtures.constants import MAX_FEE, MAX_RESOURCE_BOUNDS_L1 +from starknet_py.tests.e2e.fixtures.constants import MAX_FEE, MAX_RESOURCE_BOUNDS from starknet_py.tests.e2e.fixtures.misc import load_contract @@ -54,9 +54,7 @@ async def test_declare_deploy_v3( declare_transaction=Mock(spec=DeclareV2), ) - deploy_result = await declare_result.deploy_v3( - l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1 - ) + deploy_result = await declare_result.deploy_v3(resource_bounds=MAX_RESOURCE_BOUNDS) await deploy_result.wait_for_acceptance() assert isinstance(deploy_result.hash, int) diff --git a/starknet_py/tests/e2e/contract_interaction/interaction_test.py b/starknet_py/tests/e2e/contract_interaction/interaction_test.py index 1ffdd29c6..9600e99cc 100644 --- a/starknet_py/tests/e2e/contract_interaction/interaction_test.py +++ b/starknet_py/tests/e2e/contract_interaction/interaction_test.py @@ -7,7 +7,7 @@ ) from starknet_py.hash.selector import get_selector_from_name from starknet_py.net.client_errors import ClientError -from starknet_py.net.client_models import Call, ResourceBounds +from starknet_py.net.client_models import Call, ResourceBounds, ResourceBoundsMapping from starknet_py.net.models import InvokeV1, InvokeV3 from starknet_py.tests.e2e.fixtures.constants import ( MAX_FEE, @@ -31,7 +31,7 @@ async def test_prepare_and_invoke_v1(map_contract): @pytest.mark.asyncio async def test_prepare_and_invoke_v3(map_contract): prepared_invoke = map_contract.functions["put"].prepare_invoke_v3( - key=1, value=2, l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1 + key=1, value=2, resource_bounds=MAX_RESOURCE_BOUNDS ) assert isinstance(prepared_invoke, PreparedFunctionInvokeV3) @@ -52,7 +52,7 @@ async def test_invoke_v1(map_contract): @pytest.mark.asyncio async def test_invoke_v3(map_contract): invocation = await map_contract.functions["put"].invoke_v3( - key=1, value=2, l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1 + key=1, value=2, resource_bounds=MAX_RESOURCE_BOUNDS ) assert isinstance(invocation.invoke_transaction, InvokeV3) assert invocation.invoke_transaction.resource_bounds == MAX_RESOURCE_BOUNDS @@ -90,7 +90,7 @@ async def test_throws_invoke_v1_without_max_fee(map_contract): async def test_throws_invoke_v3_without_resource_bounds(map_contract): error_message = ( "One of arguments: " - "l1_resource_bounds or auto_estimate must be specified when invoking a transaction." + "resource_bounds or auto_estimate must be specified when invoking a transaction." ) with pytest.raises(ValueError, match=error_message): @@ -112,7 +112,7 @@ async def test_throws_prepared_invoke_v1_without_max_fee(map_contract): async def test_throws_prepared_invoke_v3_without_resource_bounds(map_contract): error_message = ( "One of arguments: " - "l1_resource_bounds or auto_estimate must be specified when invoking a transaction." + "resource_bounds or auto_estimate must be specified when invoking a transaction." ) prepared_invoke = map_contract.functions["put"].prepare_invoke_v3(2, 3) @@ -158,24 +158,25 @@ async def test_latest_max_fee_takes_precedence(map_contract): @pytest.mark.asyncio async def test_latest_resource_bounds_take_precedence(map_contract): prepared_function = map_contract.functions["put"].prepare_invoke_v3( - key=1, value=2, l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1 + key=1, value=2, resource_bounds=MAX_RESOURCE_BOUNDS ) - updated_resource_bounds = ResourceBounds( + updated_l1_resource_bounds = ResourceBounds( max_amount=MAX_RESOURCE_BOUNDS_L1.max_amount + 100, max_price_per_unit=MAX_RESOURCE_BOUNDS_L1.max_price_per_unit + 200, ) - invocation = await prepared_function.invoke( - l1_resource_bounds=updated_resource_bounds + resource_bounds = ResourceBoundsMapping( + l1_gas=updated_l1_resource_bounds, + l2_gas=ResourceBounds.init_with_zeros(), ) + invocation = await prepared_function.invoke(resource_bounds=resource_bounds) assert isinstance(invocation.invoke_transaction, InvokeV3) assert ( - invocation.invoke_transaction.resource_bounds.l1_gas == updated_resource_bounds + invocation.invoke_transaction.resource_bounds.l1_gas == resource_bounds.l1_gas ) assert ( - invocation.invoke_transaction.resource_bounds.l2_gas - == ResourceBounds.init_with_zeros() + invocation.invoke_transaction.resource_bounds.l2_gas == resource_bounds.l2_gas ) diff --git a/starknet_py/tests/e2e/declare/declare_test.py b/starknet_py/tests/e2e/declare/declare_test.py index 7e5e3924a..b6ccc3c17 100644 --- a/starknet_py/tests/e2e/declare/declare_test.py +++ b/starknet_py/tests/e2e/declare/declare_test.py @@ -2,7 +2,7 @@ from starknet_py.net.client_models import TransactionExecutionStatus from starknet_py.net.models.transaction import DeclareV3 -from starknet_py.tests.e2e.fixtures.constants import MAX_RESOURCE_BOUNDS_L1 +from starknet_py.tests.e2e.fixtures.constants import MAX_RESOURCE_BOUNDS @pytest.mark.asyncio @@ -16,7 +16,7 @@ async def test_declare_v3_tx(account, abi_types_compiled_contract_and_class_hash declare_tx = await account.sign_declare_v3( compiled_contract=abi_types_compiled_contract_and_class_hash[0], compiled_class_hash=abi_types_compiled_contract_and_class_hash[1], - l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1, + resource_bounds=MAX_RESOURCE_BOUNDS, ) assert isinstance(declare_tx, DeclareV3) diff --git a/starknet_py/tests/e2e/deploy_account/deploy_account_test.py b/starknet_py/tests/e2e/deploy_account/deploy_account_test.py index c9156d3fa..6d94c1630 100644 --- a/starknet_py/tests/e2e/deploy_account/deploy_account_test.py +++ b/starknet_py/tests/e2e/deploy_account/deploy_account_test.py @@ -3,7 +3,7 @@ from starknet_py.net.account.account import Account from starknet_py.net.models import StarknetChainId from starknet_py.net.models.transaction import DeployAccountV3 -from starknet_py.tests.e2e.fixtures.constants import MAX_FEE, MAX_RESOURCE_BOUNDS_L1 +from starknet_py.tests.e2e.fixtures.constants import MAX_FEE, MAX_RESOURCE_BOUNDS @pytest.mark.asyncio @@ -43,7 +43,7 @@ async def test_deploy_account_v3(client, deploy_account_details_factory): class_hash=class_hash, contract_address_salt=salt, constructor_calldata=[key_pair.public_key], - l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1, + resource_bounds=MAX_RESOURCE_BOUNDS, ) assert isinstance(deploy_account_tx, DeployAccountV3) diff --git a/starknet_py/tests/e2e/docs/code_examples/test_account.py b/starknet_py/tests/e2e/docs/code_examples/test_account.py index 4cdf82a0f..88bf6ab57 100644 --- a/starknet_py/tests/e2e/docs/code_examples/test_account.py +++ b/starknet_py/tests/e2e/docs/code_examples/test_account.py @@ -6,7 +6,7 @@ from starknet_py.constants import FEE_CONTRACT_ADDRESS from starknet_py.hash.selector import get_selector_from_name from starknet_py.net.account.account import Account -from starknet_py.net.client_models import Call, ResourceBounds +from starknet_py.net.client_models import Call, ResourceBounds, ResourceBoundsMapping from starknet_py.net.full_node_client import FullNodeClient from starknet_py.net.models import StarknetChainId from starknet_py.net.models.typed_data import TypedDataDict @@ -50,15 +50,17 @@ async def test_execute_v1(account, contract_address): @pytest.mark.asyncio async def test_execute_v3(account, contract_address): # docs-start: execute_v3 + resource_bounds = ResourceBoundsMapping( + l1_gas=ResourceBounds(max_amount=int(1e5), max_price_per_unit=int(1e13)), + l2_gas=ResourceBounds.init_with_zeros(), + ) resp = await account.execute_v3( Call( to_addr=contract_address, selector=get_selector_from_name("increase_balance"), calldata=[123], ), - l1_resource_bounds=ResourceBounds( - max_amount=int(1e5), max_price_per_unit=int(1e13) - ), + resource_bounds=resource_bounds, ) # or # docs-end: execute_v3 diff --git a/starknet_py/tests/e2e/docs/code_examples/test_contract.py b/starknet_py/tests/e2e/docs/code_examples/test_contract.py index 821103c5f..e500bc794 100644 --- a/starknet_py/tests/e2e/docs/code_examples/test_contract.py +++ b/starknet_py/tests/e2e/docs/code_examples/test_contract.py @@ -4,7 +4,11 @@ from starknet_py.common import create_sierra_compiled_contract from starknet_py.contract import Contract from starknet_py.net.account.account import Account -from starknet_py.net.client_models import InvokeTransactionV3, ResourceBounds +from starknet_py.net.client_models import ( + InvokeTransactionV3, + ResourceBounds, + ResourceBoundsMapping, +) from starknet_py.net.full_node_client import FullNodeClient from starknet_py.net.models import DeclareV2, DeclareV3, StarknetChainId from starknet_py.net.signer.stark_curve_signer import KeyPair @@ -80,13 +84,15 @@ async def test_declare_v3(account): contract = load_contract(contract_name="TestContract", version=ContractVersion.V2) # docs-start: declare_v3 # here `contract` is a dict containing sierra and casm artifacts + resource_bounds = ResourceBoundsMapping( + l1_gas=ResourceBounds(max_amount=int(1e5), max_price_per_unit=int(1e13)), + l2_gas=ResourceBounds.init_with_zeros(), + ) declare_result = await Contract.declare_v3( account, compiled_contract=contract["sierra"], compiled_contract_casm=contract["casm"], - l1_resource_bounds=ResourceBounds( - max_amount=int(1e5), max_price_per_unit=int(1e13) - ), + resource_bounds=resource_bounds, ) # docs-end: declare_v3 await declare_result.wait_for_acceptance() @@ -141,13 +147,15 @@ async def test_deploy_contract_v3(account, hello_starknet_class_hash: int): # docs-end: deploy_contract_v3 class_hash = hello_starknet_class_hash # docs-start: deploy_contract_v3 + resource_bounds = ResourceBoundsMapping( + l1_gas=ResourceBounds(max_amount=int(1e5), max_price_per_unit=int(1e13)), + l2_gas=ResourceBounds.init_with_zeros(), + ) deploy_result = await Contract.deploy_contract_v3( class_hash=class_hash, account=account, abi=abi, - l1_resource_bounds=ResourceBounds( - max_amount=int(1e5), max_price_per_unit=int(1e13) - ), + resource_bounds=resource_bounds, ) # docs-end: deploy_contract_v3 await deploy_result.wait_for_acceptance() @@ -167,12 +175,14 @@ async def test_deploy_contract_v3(account, hello_starknet_class_hash: int): @pytest.mark.asyncio async def test_deploy_contract_v3_without_abi(account, hello_starknet_class_hash: int): + resource_bounds = ResourceBoundsMapping( + l1_gas=ResourceBounds(max_amount=int(1e5), max_price_per_unit=int(1e13)), + l2_gas=ResourceBounds.init_with_zeros(), + ) deploy_result = await Contract.deploy_contract_v3( class_hash=hello_starknet_class_hash, account=account, - l1_resource_bounds=ResourceBounds( - max_amount=int(1e5), max_price_per_unit=int(1e13) - ), + resource_bounds=resource_bounds, ) await deploy_result.wait_for_acceptance() diff --git a/starknet_py/tests/e2e/docs/code_examples/test_contract_function.py b/starknet_py/tests/e2e/docs/code_examples/test_contract_function.py index b0b2dbf11..2e32cdb3b 100644 --- a/starknet_py/tests/e2e/docs/code_examples/test_contract_function.py +++ b/starknet_py/tests/e2e/docs/code_examples/test_contract_function.py @@ -2,7 +2,7 @@ import pytest from starknet_py.contract import Contract, ContractFunction -from starknet_py.net.client_models import ResourceBounds +from starknet_py.net.client_models import ResourceBounds, ResourceBoundsMapping def test_prepare_invoke_v1(map_contract: Contract): @@ -40,12 +40,14 @@ def test_invoke_v1(map_contract: Contract): def test_invoke_v3(map_contract: Contract): # docs-start: invoke_v3 + resource_bounds = ResourceBoundsMapping( + l1_gas=ResourceBounds(max_amount=5000, max_price_per_unit=int(1e12)), + l2_gas=ResourceBounds.init_with_zeros(), + ) invoke_result = map_contract.functions["put"].invoke_v3( key=10, value=20, - l1_resource_bounds=ResourceBounds( - max_amount=5000, max_price_per_unit=int(1e12) - ), + resource_bounds=resource_bounds, ) # docs-end: invoke_v3 diff --git a/starknet_py/tests/e2e/docs/code_examples/test_prepared_function_invoke_v3.py b/starknet_py/tests/e2e/docs/code_examples/test_prepared_function_invoke_v3.py index 17cac8b7e..8fda67af5 100644 --- a/starknet_py/tests/e2e/docs/code_examples/test_prepared_function_invoke_v3.py +++ b/starknet_py/tests/e2e/docs/code_examples/test_prepared_function_invoke_v3.py @@ -2,7 +2,7 @@ import pytest from starknet_py.contract import Contract -from starknet_py.net.client_models import ResourceBounds +from starknet_py.net.client_models import ResourceBounds, ResourceBoundsMapping @pytest.mark.asyncio @@ -10,19 +10,20 @@ async def test_invoke(map_contract: Contract): prepared_function_call = map_contract.functions["put"].prepare_invoke_v3( key=10, value=20 ) - l1_resource_bounds = ResourceBounds(max_amount=5000, max_price_per_unit=int(1e12)) # docs-start: invoke - invoke_result = await prepared_function_call.invoke( - l1_resource_bounds=ResourceBounds(max_amount=5000, max_price_per_unit=int(1e12)) + resource_bounds = ResourceBoundsMapping( + l1_gas=ResourceBounds(max_amount=5000, max_price_per_unit=int(1e12)), + l2_gas=ResourceBounds.init_with_zeros(), ) + invoke_result = await prepared_function_call.invoke(resource_bounds=resource_bounds) # docs-end: invoke - prepared_function_call.l1_resource_bounds = None + prepared_function_call.resource_bounds = None # docs-start: invoke - # l1_resource_bounds can be estimated automatically + # resource_bounds can be estimated automatically invoke_result = await prepared_function_call.invoke(auto_estimate=True) - # or if l1_resource_bounds was specified in prepared_function_call + # or if resource_bounds was specified in prepared_function_call # docs-end: invoke - prepared_function_call.l1_resource_bounds = l1_resource_bounds + prepared_function_call.resource_bounds = resource_bounds # docs-start: invoke invoke_result = await prepared_function_call.invoke() # docs-end: invoke diff --git a/starknet_py/tests/e2e/docs/devnet_utils/test_l1_integration.py b/starknet_py/tests/e2e/docs/devnet_utils/test_l1_integration.py index 65ba38c1d..2bc1a7b37 100644 --- a/starknet_py/tests/e2e/docs/devnet_utils/test_l1_integration.py +++ b/starknet_py/tests/e2e/docs/devnet_utils/test_l1_integration.py @@ -1,7 +1,7 @@ import pytest from starknet_py.hash.selector import get_selector_from_name -from starknet_py.net.client_models import ResourceBounds +from starknet_py.net.client_models import ResourceBounds, ResourceBoundsMapping @pytest.mark.skip(reason="Test require eth node running.") @@ -37,12 +37,14 @@ async def test_postman_load(devnet_client, l1_l2_contract, account): # docs: messaging-contract-start contract = await Contract.from_address(address=contract_address, provider=account) + resource_bounds = ResourceBoundsMapping( + l1_gas=ResourceBounds(max_amount=50000, max_price_per_unit=int(1e12)), + l2_gas=ResourceBounds.init_with_zeros(), + ) await contract.functions["increase_balance"].invoke_v3( user=account.address, amount=100, - l1_resource_bounds=ResourceBounds( - max_amount=50000, max_price_per_unit=int(1e12) - ), + resource_bounds=resource_bounds, ) # docs: messaging-contract-end @@ -50,13 +52,15 @@ async def test_postman_load(devnet_client, l1_l2_contract, account): # docs: messaging-contract-start # Invoking function that is emitting message + resource_bounds = ResourceBoundsMapping( + l1_gas=ResourceBounds(max_amount=50000, max_price_per_unit=int(1e12)), + l2_gas=ResourceBounds.init_with_zeros(), + ) await contract.functions["withdraw"].invoke_v3( user=account.address, amount=100, l1_address=eth_account_address, - l1_resource_bounds=ResourceBounds( - max_amount=50000, max_price_per_unit=int(1e12) - ), + resource_bounds=resource_bounds, ) # docs: messaging-contract-end assert await contract.functions["get_balance"].call(user=account.address) == (0,) diff --git a/starknet_py/tests/e2e/docs/guide/test_declaring_contracts.py b/starknet_py/tests/e2e/docs/guide/test_declaring_contracts.py index fabf285d5..9a9291085 100644 --- a/starknet_py/tests/e2e/docs/guide/test_declaring_contracts.py +++ b/starknet_py/tests/e2e/docs/guide/test_declaring_contracts.py @@ -2,7 +2,7 @@ import pytest -from starknet_py.net.client_models import ResourceBounds +from starknet_py.net.client_models import ResourceBounds, ResourceBoundsMapping @pytest.mark.skipif( @@ -20,12 +20,14 @@ async def test_declaring_contracts( # and a class hash (casm_class_hash) # They return DeclareV2 and DeclareV3 respectively + resource_bounds = ResourceBoundsMapping( + l1_gas=ResourceBounds(max_amount=int(1e5), max_price_per_unit=int(1e13)), + l2_gas=ResourceBounds.init_with_zeros(), + ) declare_transaction = await account.sign_declare_v3( compiled_contract=compiled_contract, compiled_class_hash=class_hash, - l1_resource_bounds=ResourceBounds( - max_amount=int(1e5), max_price_per_unit=int(1e13) - ), + resource_bounds=resource_bounds, ) # To declare a contract, send Declare transaction with Client.declare method diff --git a/starknet_py/tests/e2e/docs/guide/test_simple_deploy.py b/starknet_py/tests/e2e/docs/guide/test_simple_deploy.py index ed89a066d..71b41dc87 100644 --- a/starknet_py/tests/e2e/docs/guide/test_simple_deploy.py +++ b/starknet_py/tests/e2e/docs/guide/test_simple_deploy.py @@ -1,6 +1,6 @@ import pytest -from starknet_py.net.client_models import ResourceBounds +from starknet_py.net.client_models import ResourceBounds, ResourceBoundsMapping @pytest.mark.asyncio @@ -25,14 +25,16 @@ async def test_simple_deploy(account, hello_starknet_class_hash, hello_starknet_ constructor_args = None # docs: start + resource_bounds = ResourceBoundsMapping( + l1_gas=ResourceBounds(max_amount=int(1e5), max_price_per_unit=int(1e13)), + l2_gas=ResourceBounds.init_with_zeros(), + ) deploy_result = await Contract.deploy_contract_v3( account=account, class_hash=class_hash, abi=abi, # abi is optional constructor_args=constructor_args, - l1_resource_bounds=ResourceBounds( - max_amount=int(1e5), max_price_per_unit=int(1e13) - ), + resource_bounds=resource_bounds, ) # `Contract.deploy_contract_v1` and `Contract.deploy_contract_v3` methods have an optional parameter diff --git a/starknet_py/tests/e2e/docs/quickstart/test_using_account.py b/starknet_py/tests/e2e/docs/quickstart/test_using_account.py index 9a39291af..a4c6aa838 100644 --- a/starknet_py/tests/e2e/docs/quickstart/test_using_account.py +++ b/starknet_py/tests/e2e/docs/quickstart/test_using_account.py @@ -3,6 +3,8 @@ import pytest +from starknet_py.net.client_models import ResourceBoundsMapping + directory = os.path.dirname(__file__) @@ -12,8 +14,8 @@ ) @pytest.mark.asyncio async def test_using_account(account, map_compiled_contract_and_class_hash_copy_2): - (compiled_contract, class_hash) = map_compiled_contract_and_class_hash_copy_2 # pylint: disable=import-outside-toplevel, duplicate-code, too-many-locals + (compiled_contract, class_hash) = map_compiled_contract_and_class_hash_copy_2 # docs: start from starknet_py.contract import Contract from starknet_py.net.client_models import ResourceBounds @@ -23,6 +25,10 @@ async def test_using_account(account, map_compiled_contract_and_class_hash_copy_ l1_resource_bounds = ResourceBounds( max_amount=int(1e5), max_price_per_unit=int(1e13) ) + resource_bounds = ResourceBoundsMapping( + l1_gas=l1_resource_bounds, + l2_gas=ResourceBounds.init_with_zeros(), + ) # Declare and deploy an example contract which implements a simple k-v store. # Contract.declare_v3 takes string containing a compiled contract (sierra) and # a class hash (casm_class_hash) or string containing a compiled contract (casm) @@ -30,12 +36,12 @@ async def test_using_account(account, map_compiled_contract_and_class_hash_copy_ account, compiled_contract=compiled_contract, compiled_class_hash=class_hash, - l1_resource_bounds=l1_resource_bounds, + resource_bounds=resource_bounds, ) await declare_result.wait_for_acceptance() deploy_result = await declare_result.deploy_v3( - l1_resource_bounds=l1_resource_bounds, + resource_bounds=resource_bounds, ) # Wait until deployment transaction is accepted await deploy_result.wait_for_acceptance() @@ -45,13 +51,15 @@ async def test_using_account(account, map_compiled_contract_and_class_hash_copy_ k, v = 13, 4324 # Adds a transaction to mutate the state of k-v store. The call goes through account proxy, because we've used # Account to create the contract object + resource_bounds = ResourceBoundsMapping( + l1_gas=l1_resource_bounds, + l2_gas=ResourceBounds.init_with_zeros(), + ) await ( await map_contract.functions["put"].invoke_v3( k, v, - l1_resource_bounds=ResourceBounds( - max_amount=int(1e5), max_price_per_unit=int(1e13) - ), + resource_bounds=resource_bounds, ) ).wait_for_acceptance() @@ -69,7 +77,7 @@ async def test_using_account(account, map_compiled_contract_and_class_hash_copy_ # Executes only one transaction with prepared calls transaction_response = await account.execute_v3( calls=calls, - l1_resource_bounds=l1_resource_bounds, + resource_bounds=resource_bounds, ) await account.client.wait_for_tx(transaction_response.transaction_hash) # docs: end diff --git a/starknet_py/tests/e2e/tests_on_networks/client_test.py b/starknet_py/tests/e2e/tests_on_networks/client_test.py index 192223a30..5c5c509c8 100644 --- a/starknet_py/tests/e2e/tests_on_networks/client_test.py +++ b/starknet_py/tests/e2e/tests_on_networks/client_test.py @@ -178,10 +178,12 @@ async def test_estimate_message_fee(client_sepolia_testnet): assert isinstance(estimated_message, EstimatedFee) assert estimated_message.overall_fee > 0 - assert estimated_message.gas_price > 0 - assert estimated_message.gas_consumed > 0 - assert estimated_message.data_gas_price > 0 - assert estimated_message.data_gas_consumed >= 0 + assert estimated_message.l1_gas_price > 0 + assert estimated_message.l1_gas_consumed > 0 + assert estimated_message.l2_gas_price > 0 + assert estimated_message.l2_gas_consumed > 0 + assert estimated_message.l1_data_gas_price > 0 + assert estimated_message.l1_data_gas_consumed >= 0 assert estimated_message.unit is not None @@ -313,6 +315,12 @@ async def test_get_transaction_status(client_sepolia_testnet): assert tx_status.execution_status == TransactionExecutionStatus.SUCCEEDED +@pytest.mark.asyncio +async def test_get_transaction_status_with_failure_reason(): + # TODO (#1498): Add a test for a transaction with failure_reason + pass + + @pytest.mark.asyncio async def test_get_block_new_header_fields(client_sepolia_testnet): # testing l1_gas_price and starknet_version fields diff --git a/starknet_py/tests/unit/net/account/account_test.py b/starknet_py/tests/unit/net/account/account_test.py index 5e34e271c..f9406d13c 100644 --- a/starknet_py/tests/unit/net/account/account_test.py +++ b/starknet_py/tests/unit/net/account/account_test.py @@ -9,7 +9,7 @@ from starknet_py.net.signer.stark_curve_signer import KeyPair, StarkCurveSigner from starknet_py.tests.e2e.fixtures.constants import ( MAX_FEE, - MAX_RESOURCE_BOUNDS_L1, + MAX_RESOURCE_BOUNDS, STRK_FEE_CONTRACT_ADDRESS, ) @@ -61,7 +61,7 @@ async def test_account_get_balance_strk(account, hello_starknet_contract): block = await account.client.get_block(block_number="latest") await hello_starknet_contract.functions["increase_balance"].invoke_v3( - amount=10, l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1 + amount=10, resource_bounds=MAX_RESOURCE_BOUNDS ) new_balance = await account.get_balance(token_address=STRK_FEE_CONTRACT_ADDRESS) diff --git a/starknet_py/tests/unit/net/client_test.py b/starknet_py/tests/unit/net/client_test.py index e35d4152a..c36ac5882 100644 --- a/starknet_py/tests/unit/net/client_test.py +++ b/starknet_py/tests/unit/net/client_test.py @@ -23,7 +23,7 @@ InvokeV1, InvokeV3, ) -from starknet_py.tests.e2e.fixtures.constants import MAX_FEE, MAX_RESOURCE_BOUNDS_L1 +from starknet_py.tests.e2e.fixtures.constants import MAX_FEE, MAX_RESOURCE_BOUNDS @pytest.mark.asyncio @@ -98,7 +98,7 @@ async def test_broadcasted_txn_declare_v3( declare_v3 = await account.sign_declare_v3( compiled_contract=abi_types_compiled_contract_and_class_hash[0], compiled_class_hash=abi_types_compiled_contract_and_class_hash[1], - l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1, + resource_bounds=MAX_RESOURCE_BOUNDS, ) brodcasted_txn = _create_broadcasted_txn(declare_v3) @@ -134,7 +134,7 @@ async def test_broadcasted_txn_invoke_v3(account, hello_starknet_contract): get_selector_from_name("increaseBalance"), [10], ), - l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1, + resource_bounds=MAX_RESOURCE_BOUNDS, ) brodcasted_txn = _create_broadcasted_txn(invoke_tx) @@ -172,7 +172,7 @@ async def test_broadcasted_txn_deploy_account_v3(account): signed_tx = await account.sign_deploy_account_v3( class_hash, salt, - l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1, + resource_bounds=MAX_RESOURCE_BOUNDS, constructor_calldata=calldata, ) brodcasted_txn = _create_broadcasted_txn(signed_tx)