From 22593f5fbd69bf23915c7633b3f0a180a9cdcca4 Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Thu, 29 Feb 2024 12:08:58 +0100 Subject: [PATCH 01/19] Merge changes from the initial PR --- docs/guide/account_and_client.rst | 2 +- docs/migration_guide.rst | 24 +++++ starknet_py/net/account/account.py | 5 +- starknet_py/net/client_models.py | 65 +++++++++++++- starknet_py/net/full_node_client.py | 27 ++++++ starknet_py/net/schemas/common.py | 20 +++++ starknet_py/net/schemas/rpc.py | 133 +++++++++++++++++++++------- starknet_py/tests/e2e/block_test.py | 31 +++++++ 8 files changed, 268 insertions(+), 39 deletions(-) diff --git a/docs/guide/account_and_client.rst b/docs/guide/account_and_client.rst index 11af4cc42..fb627dd0d 100644 --- a/docs/guide/account_and_client.rst +++ b/docs/guide/account_and_client.rst @@ -28,7 +28,7 @@ To enable auto estimation, set the ``auto_estimate`` parameter to ``True``. It is strongly discouraged to use automatic fee estimation in production code as it may lead to an unexpectedly high fee. The returned estimated fee is multiplied by ``1.5`` for V1 and V2 transactions to mitigate fluctuations in price. -For V3 transactions, ``max_amount`` and ``max_price_per_unit`` are scaled by ``1.1`` and ``1.5`` respectively. +For V3 transactions, ``max_amount`` and ``max_price_per_unit`` are scaled by ``1.5``. .. note:: diff --git a/docs/migration_guide.rst b/docs/migration_guide.rst index 11c3b8f77..0dc045393 100644 --- a/docs/migration_guide.rst +++ b/docs/migration_guide.rst @@ -1,6 +1,30 @@ Migration guide =============== +********************** +0.21.0 Migration guide +********************** + + +Version 0.21.0 of **starknet.py** comes with support for RPC 0.7.0 and python 3.12! + +New classes added to mirror the recent changes in the RPC v0.7.0 specification include: +:class:`StarknetBlockWithReceipts`, :class:`PendingStarknetBlockWithReceipts`, :class:`TransactionWithReceipt` :class:`DataResources`. + + +0.21.0 Targeted versions +------------------------ + +- Starknet - `0.13.1 `_ +- RPC - `0.7.0 `_ + +0.21.0 Minor changes +-------------------- + +1. :class:`ExecutionResources` now has an additional optional field: ``data_availability`` +2. :class:`StarknetBlock`, :class:`StarknetBlockWithTxHashes`, :class:`PendingStarknetBlock` and :class:`PendingStarknetBlockWithTxHashes` now have two additional option fields: ``l1_data_gas_price`` and ``l1_da_mode``. +3. :class:`DeclareTransactionTrace`, :class:`InvokeTransactionTrace` and :class:`DeployAccountTransactionTrace` have additional field ``execution_resources`` + ********************** 0.20.0 Migration guide ********************** diff --git a/starknet_py/net/account/account.py b/starknet_py/net/account/account.py index 9d7f9cb8f..f9ff857a1 100644 --- a/starknet_py/net/account/account.py +++ b/starknet_py/net/account/account.py @@ -60,7 +60,7 @@ class Account(BaseAccount): ESTIMATED_FEE_MULTIPLIER: float = 1.5 """Amount by which each estimated fee is multiplied when using `auto_estimate`.""" - ESTIMATED_AMOUNT_MULTIPLIER: float = 1.1 + ESTIMATED_AMOUNT_MULTIPLIER: float = 1.5 ESTIMATED_UNIT_PRICE_MULTIPLIER: float = 1.5 """Values by which each estimated `max_amount` and `max_price_per_unit` are multiplied when using `auto_estimate`. Used only for V3 transactions""" @@ -165,7 +165,8 @@ async def _get_resource_bounds( l1_resource_bounds = ResourceBounds( max_amount=int( - estimated_fee.gas_consumed * Account.ESTIMATED_AMOUNT_MULTIPLIER + (estimated_fee.overall_fee / estimated_fee.gas_price) + * Account.ESTIMATED_AMOUNT_MULTIPLIER ), max_price_per_unit=int( estimated_fee.gas_price * Account.ESTIMATED_UNIT_PRICE_MULTIPLIER diff --git a/starknet_py/net/client_models.py b/starknet_py/net/client_models.py index cf9288225..6201b1b7c 100644 --- a/starknet_py/net/client_models.py +++ b/starknet_py/net/client_models.py @@ -347,9 +347,19 @@ class TransactionFinalityStatus(Enum): @dataclass -class ExecutionResources: +class DataResources: """ - Dataclass representing the resources consumed by the transaction. + Dataclass representing the data-availability resources of the transaction + """ + + l1_gas: int + l1_data_gas: int + + +@dataclass +class ComputationResources: + """ + Dataclass representing the resources consumed by the VM. """ # pylint: disable=too-many-instance-attributes @@ -366,6 +376,15 @@ class ExecutionResources: segment_arena_builtin: Optional[int] = None +@dataclass +class ExecutionResources(ComputationResources): + """ + Dataclass representing the the resources consumed by the transaction, includes both computation and data. + """ + + data_availability: Optional[DataResources] = None + + # TODO (#1219): split into PendingTransactionReceipt and TransactionReceipt @dataclass class TransactionReceipt: @@ -463,6 +482,25 @@ class PendingStarknetBlockWithTxHashes: starknet_version: str +@dataclass +class PendingStarknetBlockWithReceipts: + """ + Dataclass representing a pending block on Starknet with txs and receipts result + """ + + transactions: List[TransactionReceipt] + parent_block_hash: int + timestamp: int + sequencer_address: int + l1_gas_price: ResourcePrice + starknet_version: str + + +class DaModeType(Enum): + BLOB = "BLOB" + CALLDATA = "CALLDATA" + + @dataclass class StarknetBlockCommon: """ @@ -479,6 +517,8 @@ class StarknetBlockCommon: timestamp: int sequencer_address: int l1_gas_price: ResourcePrice + l1_data_gas_price: Optional[ResourcePrice] + l1_da_mode: Optional[DaModeType] starknet_version: str @@ -502,6 +542,22 @@ class StarknetBlockWithTxHashes(StarknetBlockCommon): transactions: List[int] +@dataclass +class TransactionWithReceipt: + transaction: Transaction + receipt: TransactionReceipt + + +@dataclass +class StarknetBlockWithReceipts(StarknetBlockCommon): + """ + Dataclass representing a block on Starknet with txs and receipts result + """ + + status: BlockStatus + transactions: List[TransactionWithReceipt] + + @dataclass class BlockHashAndNumber: block_hash: int @@ -548,6 +604,8 @@ class EstimatedFee: gas_price: int gas_consumed: int unit: PriceUnit + data_gas_consumed: Optional[int] + data_gas_price: Optional[int] @dataclass @@ -850,6 +908,7 @@ class InvokeTransactionTrace: """ execute_invocation: Union[FunctionInvocation, RevertedFunctionInvocation] + execution_resources: Optional[ExecutionResources] = None validate_invocation: Optional[FunctionInvocation] = None fee_transfer_invocation: Optional[FunctionInvocation] = None state_diff: Optional[StateDiff] = None @@ -861,6 +920,7 @@ class DeclareTransactionTrace: Dataclass representing a transaction trace of an DECLARE transaction. """ + execution_resources: Optional[ExecutionResources] = None validate_invocation: Optional[FunctionInvocation] = None fee_transfer_invocation: Optional[FunctionInvocation] = None state_diff: Optional[StateDiff] = None @@ -873,6 +933,7 @@ class DeployAccountTransactionTrace: """ constructor_invocation: FunctionInvocation + execution_resources: Optional[ExecutionResources] = None validate_invocation: Optional[FunctionInvocation] = None fee_transfer_invocation: Optional[FunctionInvocation] = None state_diff: Optional[StateDiff] = None diff --git a/starknet_py/net/full_node_client.py b/starknet_py/net/full_node_client.py index 453126402..cda5d3654 100644 --- a/starknet_py/net/full_node_client.py +++ b/starknet_py/net/full_node_client.py @@ -21,12 +21,14 @@ L1HandlerTransaction, PendingBlockStateUpdate, PendingStarknetBlock, + PendingStarknetBlockWithReceipts, PendingStarknetBlockWithTxHashes, SentTransactionResponse, SierraContractClass, SimulatedTransaction, SimulationFlag, StarknetBlock, + StarknetBlockWithReceipts, StarknetBlockWithTxHashes, SyncStatus, Tag, @@ -60,11 +62,13 @@ EventsChunkSchema, PendingBlockStateUpdateSchema, PendingStarknetBlockSchema, + PendingStarknetBlockWithReceiptsSchema, PendingStarknetBlockWithTxHashesSchema, SentTransactionSchema, SierraContractClassSchema, SimulatedTransactionSchema, StarknetBlockSchema, + StarknetBlockWithReceiptsSchema, StarknetBlockWithTxHashesSchema, SyncStatusSchema, TransactionReceiptSchema, @@ -146,6 +150,29 @@ async def get_block_with_tx_hashes( StarknetBlockWithTxHashesSchema().load(res, unknown=EXCLUDE), ) + async def get_block_with_receipt( + self, + block_hash: Optional[Union[Hash, Tag]] = None, + block_number: Optional[Union[int, Tag]] = None, + ): + block_identifier = get_block_identifier( + block_hash=block_hash, block_number=block_number + ) + + res = await self._client.call( + method_name="getBlockWithReceipts", + params=block_identifier, + ) + if block_identifier == {"block_id": "pending"}: + return cast( + PendingStarknetBlockWithReceipts, + PendingStarknetBlockWithReceiptsSchema().load(res, unknown=EXCLUDE), + ) + return cast( + StarknetBlockWithReceipts, + StarknetBlockWithReceiptsSchema().load(res, unknown=EXCLUDE), + ) + # TODO (#809): add tests with multiple emitted keys async def get_events( self, diff --git a/starknet_py/net/schemas/common.py b/starknet_py/net/schemas/common.py index d7e9ebb38..f0be92a2d 100644 --- a/starknet_py/net/schemas/common.py +++ b/starknet_py/net/schemas/common.py @@ -8,6 +8,7 @@ BlockStatus, CallType, DAMode, + DaModeType, EntryPointType, PriceUnit, StorageEntry, @@ -270,6 +271,25 @@ def _deserialize( return CallType(value) +class DaModeTypeField(fields.Field): + def _serialize(self, value: Any, attr: str, obj: Any, **kwargs): + return value.name if value is not None else "" + + def _deserialize( + self, + value: Any, + attr: Optional[str], + data: Optional[Mapping[str, Any]], + **kwargs, + ) -> DaModeType: + values = [v.value for v in DaModeType] + + if value not in values: + raise ValidationError(f"Invalid value provided for DaModeType: {value}.") + + return DaModeType(value) + + class PriceUnitField(fields.Field): def _serialize(self, value: Any, attr: str, obj: Any, **kwargs): return value.name if value is not None else "" diff --git a/starknet_py/net/schemas/rpc.py b/starknet_py/net/schemas/rpc.py index 7a064b7db..ff3118e6a 100644 --- a/starknet_py/net/schemas/rpc.py +++ b/starknet_py/net/schemas/rpc.py @@ -1,3 +1,5 @@ +# pylint: disable=too-many-lines + from marshmallow import EXCLUDE, Schema, fields, post_load from marshmallow_oneofschema import OneOfSchema @@ -6,9 +8,11 @@ BlockHashAndNumber, BlockStateUpdate, BlockTransactionTrace, + ComputationResources, ContractClass, ContractsNonce, DAMode, + DataResources, DeclaredContractHash, DeclareTransactionResponse, DeclareTransactionTrace, @@ -41,6 +45,7 @@ OrderedMessage, PendingBlockStateUpdate, PendingStarknetBlock, + PendingStarknetBlockWithReceipts, PendingStarknetBlockWithTxHashes, ReplacedClass, ResourceBounds, @@ -53,17 +58,20 @@ SierraEntryPointsByType, SimulatedTransaction, StarknetBlock, + StarknetBlockWithReceipts, StarknetBlockWithTxHashes, StateDiff, StorageDiffItem, SyncStatus, TransactionReceipt, TransactionStatusResponse, + TransactionWithReceipt, ) from starknet_py.net.schemas.common import ( BlockStatusField, CallTypeField, DAModeField, + DaModeTypeField, EntryPointTypeField, ExecutionStatusField, Felt, @@ -115,9 +123,18 @@ def make_dataclass(self, data, **kwargs) -> L2toL1Message: return L2toL1Message(**data) -class ExecutionResourcesSchema(Schema): - steps = fields.Integer(data_key="steps", required=True) - range_check_builtin_applications = fields.Integer( +class DataResourcesSchema(Schema): + l1_gas = Felt(data_key="l1_gas", required=True) + l1_data_gas = Felt(data_key="l1_data_gas", required=True) + + @post_load + def make_dataclass(self, data, **kwargs) -> DataResources: + return DataResources(**data) + + +class ComputationResourcesSchema(Schema): + steps = Felt(data_key="steps", required=True) + range_check_builtin_applications = Felt( data_key="range_check_builtin_applications", load_default=None ) pedersen_builtin_applications = fields.Integer( @@ -143,6 +160,16 @@ class ExecutionResourcesSchema(Schema): ) memory_holes = fields.Integer(data_key="memory_holes", load_default=None) + @post_load + def make_dataclass(self, data, **kwargs) -> ComputationResources: + return ComputationResources(**data) + + +class ExecutionResourcesSchema(ComputationResourcesSchema): + data_availability = fields.Nested( + DataResourcesSchema(), data_key="data_availability", load_default=None + ) + @post_load def make_dataclass(self, data, **kwargs) -> ExecutionResources: return ExecutionResources(**data) @@ -188,6 +215,8 @@ class EstimatedFeeSchema(Schema): gas_price = Felt(data_key="gas_price", required=True) gas_consumed = Felt(data_key="gas_consumed", required=True) unit = PriceUnitField(data_key="unit", required=True) + data_gas_consumed = PriceUnitField(data_key="data_gas_consumed", load_default=None) + data_gas_price = PriceUnitField(data_key="data_gas_price", load_default=None) @post_load def make_dataclass(self, data, **kwargs): @@ -433,14 +462,9 @@ class TypesOfTransactionsSchema(OneOfSchema): } -class PendingStarknetBlockSchema(Schema): +class PendingBlockHeaderSchema(Schema): parent_block_hash = Felt(data_key="parent_hash", required=True) sequencer_address = Felt(data_key="sequencer_address", required=True) - transactions = fields.List( - fields.Nested(TypesOfTransactionsSchema(unknown=EXCLUDE)), - data_key="transactions", - required=True, - ) timestamp = fields.Integer(data_key="timestamp", required=True) l1_gas_price = fields.Nested( ResourcePriceSchema(), data_key="l1_gas_price", required=True @@ -452,22 +476,36 @@ def make_dataclass(self, data, **kwargs): return PendingStarknetBlock(**data) -class StarknetBlockSchema(Schema): +class BlockHeaderSchema(Schema): block_hash = Felt(data_key="block_hash", required=True) parent_block_hash = Felt(data_key="parent_hash", required=True) block_number = fields.Integer(data_key="block_number", required=True) sequencer_address = Felt(data_key="sequencer_address", required=True) status = BlockStatusField(data_key="status", required=True) root = NonPrefixedHex(data_key="new_root", required=True) + timestamp = fields.Integer(data_key="timestamp", required=True) + starknet_version = fields.String(data_key="starknet_version", required=True) + l1_gas_price = fields.Nested( + ResourcePriceSchema(), data_key="l1_gas_price", required=True + ) + l1_data_gas_price = fields.Nested( + ResourcePriceSchema(), data_key="l1_data_gas_price", load_default=None + ) + l1_da_mode = DaModeTypeField(data_key="l1_da_mode", load_default=None) + + +class PendingStarknetBlockSchema(PendingBlockHeaderSchema): transactions = fields.List( fields.Nested(TypesOfTransactionsSchema(unknown=EXCLUDE)), data_key="transactions", required=True, ) - timestamp = fields.Integer(data_key="timestamp", required=True) - starknet_version = fields.String(data_key="starknet_version", required=True) - l1_gas_price = fields.Nested( - ResourcePriceSchema(), data_key="l1_gas_price", required=True + +class StarknetBlockSchema(BlockHeaderSchema): + transactions = fields.List( + fields.Nested(TypesOfTransactionsSchema(unknown=EXCLUDE)), + data_key="transactions", + required=True, ) @post_load @@ -475,25 +513,35 @@ def make_dataclass(self, data, **kwargs) -> StarknetBlock: return StarknetBlock(**data) -class StarknetBlockWithTxHashesSchema(Schema): - block_hash = Felt(data_key="block_hash", required=True) - parent_block_hash = Felt(data_key="parent_hash", required=True) - block_number = fields.Integer(data_key="block_number", required=True) - sequencer_address = Felt(data_key="sequencer_address", required=True) - status = BlockStatusField(data_key="status", required=True) - root = NonPrefixedHex(data_key="new_root", required=True) +class StarknetBlockWithTxHashesSchema(BlockHeaderSchema): transactions = fields.List(Felt(), data_key="transactions", required=True) - timestamp = fields.Integer(data_key="timestamp", required=True) - starknet_version = fields.String(data_key="starknet_version", required=True) - l1_gas_price = fields.Nested( - ResourcePriceSchema(), data_key="l1_gas_price", required=True - ) @post_load def make_dataclass(self, data, **kwargs) -> StarknetBlockWithTxHashes: return StarknetBlockWithTxHashes(**data) +class TransactionWithReceiptSchema(Schema): + transaction = fields.Nested(TransactionSchema(), data_key="transaction") + receipt = fields.Nested(TransactionReceiptSchema(), data_key="receipt") + + @post_load + def make_dataclass(self, data, **kwargs) -> TransactionWithReceipt: + return TransactionWithReceipt(**data) + + +class StarknetBlockWithReceiptsSchema(BlockHeaderSchema): + transactions = fields.List( + fields.Nested(TransactionWithReceiptSchema()), + data_key="transactions", + required=True, + ) + + @post_load + def make_dataclass(self, data, **kwargs) -> StarknetBlockWithReceipts: + return StarknetBlockWithReceipts(**data) + + class BlockHashAndNumberSchema(Schema): block_hash = Felt(data_key="block_hash", required=True) block_number = fields.Integer(data_key="block_number", required=True) @@ -516,16 +564,21 @@ def make_dataclass(self, data, **kwargs) -> SyncStatus: return SyncStatus(**data) -class PendingStarknetBlockWithTxHashesSchema(Schema): - parent_block_hash = Felt(data_key="parent_hash", required=True) - sequencer_address = Felt(data_key="sequencer_address", required=True) - transactions = fields.List(Felt(), data_key="transactions", required=True) - timestamp = fields.Integer(data_key="timestamp", required=True) - starknet_version = fields.String(data_key="starknet_version", required=True) - l1_gas_price = fields.Nested( - ResourcePriceSchema(), data_key="l1_gas_price", required=True +class PendingStarknetBlockWithReceiptsSchema(PendingBlockHeaderSchema): + transactions = fields.List( + fields.Nested(TransactionWithReceiptSchema()), + data_key="transactions", + required=True, ) + @post_load + def make_dataclass(self, data, **kwargs) -> PendingStarknetBlockWithReceipts: + return PendingStarknetBlockWithReceipts(**data) + + +class PendingStarknetBlockWithTxHashesSchema(PendingBlockHeaderSchema): + transactions = fields.List(Felt(), data_key="transactions", required=True) + @post_load def make_dataclass(self, data, **kwargs) -> PendingStarknetBlockWithTxHashes: return PendingStarknetBlockWithTxHashes(**data) @@ -839,6 +892,10 @@ class InvokeTransactionTraceSchema(Schema): StateDiffSchema(), data_key="state_diff", load_default=None ) + execution_resources = fields.Nested( + ExecutionResourcesSchema(), data_key="execution_resources", load_default=None + ) + @post_load def make_dataclass(self, data, **kwargs) -> InvokeTransactionTrace: return InvokeTransactionTrace(**data) @@ -857,6 +914,10 @@ class DeclareTransactionTraceSchema(Schema): StateDiffSchema(), data_key="state_diff", load_default=None ) + execution_resources = fields.Nested( + ExecutionResourcesSchema(), data_key="execution_resources", load_default=None + ) + @post_load def make_dataclass(self, data, **kwargs) -> DeclareTransactionTrace: return DeclareTransactionTrace(**data) @@ -878,6 +939,10 @@ class DeployAccountTransactionTraceSchema(Schema): StateDiffSchema(), data_key="state_diff", load_default=None ) + execution_resources = fields.Nested( + ExecutionResourcesSchema(), data_key="execution_resources", load_default=None + ) + @post_load def make_dataclass(self, data, **kwargs) -> DeployAccountTransactionTrace: return DeployAccountTransactionTrace(**data) diff --git a/starknet_py/tests/e2e/block_test.py b/starknet_py/tests/e2e/block_test.py index a6e24fbb1..a372f6296 100644 --- a/starknet_py/tests/e2e/block_test.py +++ b/starknet_py/tests/e2e/block_test.py @@ -4,9 +4,11 @@ from starknet_py.net.account.base_account import BaseAccount from starknet_py.net.client_models import ( PendingStarknetBlock, + PendingStarknetBlockWithReceipts, PendingStarknetBlockWithTxHashes, StarknetBlock, StarknetBlockWithTxHashes, + TransactionWithReceipt, ) from starknet_py.tests.e2e.fixtures.constants import MAX_FEE @@ -89,3 +91,32 @@ async def test_get_block_with_txs_latest( assert blk.root is not None assert blk.timestamp is not None assert blk.sequencer_address is not None + + +@pytest.mark.skip +@pytest.mark.asyncio +async def test_block_with_receipts_latest( + account, + map_contract_declare_hash, +): + blk = await account.client.get_block_with_tx_hashes(block_number="latest") + + assert isinstance(blk, StarknetBlockWithTxHashes) + assert isinstance(blk.transactions, list) + assert map_contract_declare_hash in blk.transactions + assert blk.block_hash is not None + assert blk.parent_block_hash is not None + assert blk.block_number is not None + assert blk.root is not None + assert blk.timestamp is not None + assert blk.sequencer_address is not None + + +@pytest.mark.skip +@pytest.mark.asyncio +async def test_block_with_receipts_pending(account): + blk = await account.client.get_block_with_receipts(block_number="pending") + + assert isinstance(blk, PendingStarknetBlockWithReceipts) + assert isinstance(blk.transactions, list) + assert isinstance(blk.transactions[0], TransactionWithReceipt) From dc28de0b8aa73203dfbdf04f557f41fbf1390411 Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Thu, 29 Feb 2024 14:40:59 +0100 Subject: [PATCH 02/19] Add `BlockHeader` and `PendingBlockHeader` --- starknet_py/net/client_models.py | 72 +++++++++++++---------------- starknet_py/net/full_node_client.py | 1 + starknet_py/net/schemas/common.py | 12 ++--- starknet_py/net/schemas/rpc.py | 33 +++++++------ starknet_py/tests/e2e/block_test.py | 12 ++--- 5 files changed, 63 insertions(+), 67 deletions(-) diff --git a/starknet_py/net/client_models.py b/starknet_py/net/client_models.py index 6201b1b7c..f2ca2ddcc 100644 --- a/starknet_py/net/client_models.py +++ b/starknet_py/net/client_models.py @@ -131,6 +131,11 @@ class DAMode(Enum): L2 = 1 +class L1DAMode(Enum): + BLOB = "BLOB" + CALLDATA = "CALLDATA" + + class TransactionType(Enum): """ Enum representing transaction types. @@ -414,6 +419,12 @@ class TransactionReceipt: revert_reason: Optional[str] = None +@dataclass +class TransactionWithReceipt: + transaction: Transaction + receipt: TransactionReceipt + + @dataclass class SentTransactionResponse: """ @@ -451,79 +462,66 @@ class BlockStatus(Enum): REJECTED = "REJECTED" ACCEPTED_ON_L2 = "ACCEPTED_ON_L2" ACCEPTED_ON_L1 = "ACCEPTED_ON_L1" - PROVEN = "PROVEN" @dataclass -class PendingStarknetBlock: +class PendingBlockHeader: + parent_hash: int + timestamp: int + sequencer_address: int + l1_gas_price: ResourcePrice + starknet_version: str + + +@dataclass +class PendingStarknetBlock(PendingBlockHeader): """ Dataclass representing a pending block on Starknet. """ transactions: List[Transaction] - parent_block_hash: int - timestamp: int - sequencer_address: int - l1_gas_price: ResourcePrice - starknet_version: str @dataclass -class PendingStarknetBlockWithTxHashes: +class PendingStarknetBlockWithTxHashes(PendingBlockHeader): """ Dataclass representing a pending block on Starknet containing transaction hashes. """ transactions: List[int] - parent_block_hash: int - timestamp: int - sequencer_address: int - l1_gas_price: ResourcePrice - starknet_version: str @dataclass -class PendingStarknetBlockWithReceipts: +class PendingStarknetBlockWithReceipts(PendingBlockHeader): """ Dataclass representing a pending block on Starknet with txs and receipts result """ - transactions: List[TransactionReceipt] - parent_block_hash: int - timestamp: int - sequencer_address: int - l1_gas_price: ResourcePrice - starknet_version: str - - -class DaModeType(Enum): - BLOB = "BLOB" - CALLDATA = "CALLDATA" + transactions: List[TransactionWithReceipt] @dataclass -class StarknetBlockCommon: +class BlockHeader: """ Dataclass representing a block header. """ - # TODO (#1219): change that into composition # pylint: disable=too-many-instance-attributes block_hash: int - parent_block_hash: int + parent_hash: int block_number: int - root: int + new_root: int timestamp: int sequencer_address: int l1_gas_price: ResourcePrice - l1_data_gas_price: Optional[ResourcePrice] - l1_da_mode: Optional[DaModeType] + l1_data_gas_price: ResourcePrice + l1_da_mode: L1DAMode starknet_version: str @dataclass -class StarknetBlock(StarknetBlockCommon): +class StarknetBlock(BlockHeader): """ Dataclass representing a block on Starknet. """ @@ -533,7 +531,7 @@ class StarknetBlock(StarknetBlockCommon): @dataclass -class StarknetBlockWithTxHashes(StarknetBlockCommon): +class StarknetBlockWithTxHashes(BlockHeader): """ Dataclass representing a block on Starknet containing transaction hashes. """ @@ -543,13 +541,7 @@ class StarknetBlockWithTxHashes(StarknetBlockCommon): @dataclass -class TransactionWithReceipt: - transaction: Transaction - receipt: TransactionReceipt - - -@dataclass -class StarknetBlockWithReceipts(StarknetBlockCommon): +class StarknetBlockWithReceipts(BlockHeader): """ Dataclass representing a block on Starknet with txs and receipts result """ diff --git a/starknet_py/net/full_node_client.py b/starknet_py/net/full_node_client.py index cda5d3654..6cc94eb36 100644 --- a/starknet_py/net/full_node_client.py +++ b/starknet_py/net/full_node_client.py @@ -163,6 +163,7 @@ async def get_block_with_receipt( method_name="getBlockWithReceipts", params=block_identifier, ) + if block_identifier == {"block_id": "pending"}: return cast( PendingStarknetBlockWithReceipts, diff --git a/starknet_py/net/schemas/common.py b/starknet_py/net/schemas/common.py index f0be92a2d..6b614fbfd 100644 --- a/starknet_py/net/schemas/common.py +++ b/starknet_py/net/schemas/common.py @@ -8,8 +8,8 @@ BlockStatus, CallType, DAMode, - DaModeType, EntryPointType, + L1DAMode, PriceUnit, StorageEntry, TransactionExecutionStatus, @@ -271,7 +271,7 @@ def _deserialize( return CallType(value) -class DaModeTypeField(fields.Field): +class L1DAModeField(fields.Field): def _serialize(self, value: Any, attr: str, obj: Any, **kwargs): return value.name if value is not None else "" @@ -281,13 +281,13 @@ def _deserialize( attr: Optional[str], data: Optional[Mapping[str, Any]], **kwargs, - ) -> DaModeType: - values = [v.value for v in DaModeType] + ) -> L1DAMode: + values = [v.value for v in L1DAMode] if value not in values: - raise ValidationError(f"Invalid value provided for DaModeType: {value}.") + raise ValidationError(f"Invalid value provided for L1DAMode: {value}.") - return DaModeType(value) + return L1DAMode(value) class PriceUnitField(fields.Field): diff --git a/starknet_py/net/schemas/rpc.py b/starknet_py/net/schemas/rpc.py index ff3118e6a..687e6000d 100644 --- a/starknet_py/net/schemas/rpc.py +++ b/starknet_py/net/schemas/rpc.py @@ -71,11 +71,11 @@ BlockStatusField, CallTypeField, DAModeField, - DaModeTypeField, EntryPointTypeField, ExecutionStatusField, Felt, FinalityStatusField, + L1DAModeField, NonPrefixedHex, NumberAsHex, PriceUnitField, @@ -463,35 +463,30 @@ class TypesOfTransactionsSchema(OneOfSchema): class PendingBlockHeaderSchema(Schema): - parent_block_hash = Felt(data_key="parent_hash", required=True) - sequencer_address = Felt(data_key="sequencer_address", required=True) + parent_hash = Felt(data_key="parent_hash", required=True) timestamp = fields.Integer(data_key="timestamp", required=True) + sequencer_address = Felt(data_key="sequencer_address", required=True) l1_gas_price = fields.Nested( ResourcePriceSchema(), data_key="l1_gas_price", required=True ) starknet_version = fields.String(data_key="starknet_version", required=True) - @post_load - def make_dataclass(self, data, **kwargs): - return PendingStarknetBlock(**data) - class BlockHeaderSchema(Schema): block_hash = Felt(data_key="block_hash", required=True) - parent_block_hash = Felt(data_key="parent_hash", required=True) + parent_hash = Felt(data_key="parent_hash", required=True) block_number = fields.Integer(data_key="block_number", required=True) - sequencer_address = Felt(data_key="sequencer_address", required=True) - status = BlockStatusField(data_key="status", required=True) - root = NonPrefixedHex(data_key="new_root", required=True) + new_root = Felt(data_key="new_root", required=True) timestamp = fields.Integer(data_key="timestamp", required=True) - starknet_version = fields.String(data_key="starknet_version", required=True) + sequencer_address = Felt(data_key="sequencer_address", required=True) l1_gas_price = fields.Nested( ResourcePriceSchema(), data_key="l1_gas_price", required=True ) l1_data_gas_price = fields.Nested( - ResourcePriceSchema(), data_key="l1_data_gas_price", load_default=None + ResourcePriceSchema(), data_key="l1_data_gas_price", required=True ) - l1_da_mode = DaModeTypeField(data_key="l1_da_mode", load_default=None) + l1_da_mode = L1DAModeField(data_key="l1_da_mode", required=True) + starknet_version = fields.String(data_key="starknet_version", required=True) class PendingStarknetBlockSchema(PendingBlockHeaderSchema): @@ -501,7 +496,13 @@ class PendingStarknetBlockSchema(PendingBlockHeaderSchema): required=True, ) + @post_load + def make_dataclass(self, data, **kwargs) -> PendingStarknetBlock: + return PendingStarknetBlock(**data) + + class StarknetBlockSchema(BlockHeaderSchema): + status = BlockStatusField(data_key="status", required=True) transactions = fields.List( fields.Nested(TypesOfTransactionsSchema(unknown=EXCLUDE)), data_key="transactions", @@ -514,6 +515,7 @@ def make_dataclass(self, data, **kwargs) -> StarknetBlock: class StarknetBlockWithTxHashesSchema(BlockHeaderSchema): + status = BlockStatusField(data_key="status", required=True) transactions = fields.List(Felt(), data_key="transactions", required=True) @post_load @@ -522,7 +524,7 @@ def make_dataclass(self, data, **kwargs) -> StarknetBlockWithTxHashes: class TransactionWithReceiptSchema(Schema): - transaction = fields.Nested(TransactionSchema(), data_key="transaction") + transaction = fields.Nested(TypesOfTransactionsSchema(), data_key="transaction") receipt = fields.Nested(TransactionReceiptSchema(), data_key="receipt") @post_load @@ -531,6 +533,7 @@ def make_dataclass(self, data, **kwargs) -> TransactionWithReceipt: class StarknetBlockWithReceiptsSchema(BlockHeaderSchema): + status = BlockStatusField(data_key="status", required=True) transactions = fields.List( fields.Nested(TransactionWithReceiptSchema()), data_key="transactions", diff --git a/starknet_py/tests/e2e/block_test.py b/starknet_py/tests/e2e/block_test.py index a372f6296..0a9104ed6 100644 --- a/starknet_py/tests/e2e/block_test.py +++ b/starknet_py/tests/e2e/block_test.py @@ -60,9 +60,9 @@ async def test_block_with_tx_hashes_latest( assert isinstance(blk.transactions, list) assert map_contract_declare_hash in blk.transactions assert blk.block_hash is not None - assert blk.parent_block_hash is not None + assert blk.parent_hash is not None assert blk.block_number is not None - assert blk.root is not None + assert blk.new_root is not None assert blk.timestamp is not None assert blk.sequencer_address is not None @@ -86,9 +86,9 @@ async def test_get_block_with_txs_latest( assert isinstance(blk.transactions, list) assert blk.transactions[0].hash == map_contract_declare_hash assert blk.block_hash is not None - assert blk.parent_block_hash is not None + assert blk.parent_hash is not None assert blk.block_number is not None - assert blk.root is not None + assert blk.new_root is not None assert blk.timestamp is not None assert blk.sequencer_address is not None @@ -105,9 +105,9 @@ async def test_block_with_receipts_latest( assert isinstance(blk.transactions, list) assert map_contract_declare_hash in blk.transactions assert blk.block_hash is not None - assert blk.parent_block_hash is not None + assert blk.parent_hash is not None assert blk.block_number is not None - assert blk.root is not None + assert blk.new_root is not None assert blk.timestamp is not None assert blk.sequencer_address is not None From 434f2c778c1da8b37223027219c2429e24215984 Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Thu, 29 Feb 2024 14:42:45 +0100 Subject: [PATCH 03/19] Add tests for `get_block_with_receipt` --- starknet_py/net/client_models.py | 2 ++ starknet_py/net/full_node_client.py | 2 +- starknet_py/net/schemas/rpc.py | 4 +++ .../e2e/tests_on_networks/client_test.py | 35 +++++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/starknet_py/net/client_models.py b/starknet_py/net/client_models.py index f2ca2ddcc..8fdebd7d9 100644 --- a/starknet_py/net/client_models.py +++ b/starknet_py/net/client_models.py @@ -470,6 +470,8 @@ class PendingBlockHeader: timestamp: int sequencer_address: int l1_gas_price: ResourcePrice + l1_data_gas_price: ResourcePrice + l1_da_mode: L1DAMode starknet_version: str diff --git a/starknet_py/net/full_node_client.py b/starknet_py/net/full_node_client.py index 6cc94eb36..f364fe39b 100644 --- a/starknet_py/net/full_node_client.py +++ b/starknet_py/net/full_node_client.py @@ -150,7 +150,7 @@ async def get_block_with_tx_hashes( StarknetBlockWithTxHashesSchema().load(res, unknown=EXCLUDE), ) - async def get_block_with_receipt( + async def get_block_with_receipts( self, block_hash: Optional[Union[Hash, Tag]] = None, block_number: Optional[Union[int, Tag]] = None, diff --git a/starknet_py/net/schemas/rpc.py b/starknet_py/net/schemas/rpc.py index 687e6000d..4ee02f777 100644 --- a/starknet_py/net/schemas/rpc.py +++ b/starknet_py/net/schemas/rpc.py @@ -469,6 +469,10 @@ class PendingBlockHeaderSchema(Schema): l1_gas_price = fields.Nested( ResourcePriceSchema(), data_key="l1_gas_price", required=True ) + l1_data_gas_price = fields.Nested( + ResourcePriceSchema(), data_key="l1_data_gas_price", required=True + ) + l1_da_mode = L1DAModeField(data_key="l1_da_mode", required=True) starknet_version = fields.String(data_key="starknet_version", required=True) 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 d254fa5ee..04d2d5dfb 100644 --- a/starknet_py/tests/e2e/tests_on_networks/client_test.py +++ b/starknet_py/tests/e2e/tests_on_networks/client_test.py @@ -6,6 +6,8 @@ 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 ( + BlockHeader, + BlockStatus, Call, DAMode, DeclareTransactionV3, @@ -13,7 +15,11 @@ EstimatedFee, EventsChunk, InvokeTransactionV3, + L1DAMode, + PendingBlockHeader, + PendingStarknetBlockWithReceipts, ResourceBoundsMapping, + StarknetBlockWithReceipts, TransactionExecutionStatus, TransactionFinalityStatus, TransactionReceipt, @@ -441,3 +447,32 @@ async def test_get_tx_receipt_with_execution_resources(client_sepolia_integratio assert receipt.execution_resources.memory_holes is not None assert receipt.execution_resources.pedersen_builtin_applications is not None assert receipt.execution_resources.range_check_builtin_applications is not None + + +@pytest.mark.asyncio +async def test_get_block_with_receipts(client_goerli_integration): + block_with_receipts = await client_goerli_integration.get_block_with_receipts( + block_number=329520 + ) + + assert isinstance(block_with_receipts, StarknetBlockWithReceipts) + assert block_with_receipts.status == BlockStatus.ACCEPTED_ON_L1 + assert len(block_with_receipts.transactions) == 4 + assert all( + getattr(block_with_receipts, field.name) is not None + for field in dataclasses.fields(BlockHeader) + ) + + +@pytest.mark.asyncio +async def test_get_pending_block_with_receipts(client_goerli_integration): + block_with_receipts = await client_goerli_integration.get_block_with_receipts( + block_number="pending" + ) + + assert isinstance(block_with_receipts, PendingStarknetBlockWithReceipts) + assert len(block_with_receipts.transactions) >= 0 + assert all( + getattr(block_with_receipts, field.name) is not None + for field in dataclasses.fields(PendingBlockHeader) + ) From 09ef33f8a18088845336680cb1a6ffdfd5fa936e Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Thu, 29 Feb 2024 17:16:59 +0100 Subject: [PATCH 04/19] Update client models and schemas --- starknet_py/net/client_models.py | 38 +++++++-------- starknet_py/net/schemas/rpc.py | 47 +++++++++---------- .../e2e/tests_on_networks/client_test.py | 12 ----- 3 files changed, 41 insertions(+), 56 deletions(-) diff --git a/starknet_py/net/client_models.py b/starknet_py/net/client_models.py index 8fdebd7d9..378bf82f9 100644 --- a/starknet_py/net/client_models.py +++ b/starknet_py/net/client_models.py @@ -370,24 +370,24 @@ class ComputationResources: # pylint: disable=too-many-instance-attributes steps: int - range_check_builtin_applications: Optional[int] = None - pedersen_builtin_applications: Optional[int] = None - poseidon_builtin_applications: Optional[int] = None - ec_op_builtin_applications: Optional[int] = None - ecdsa_builtin_applications: Optional[int] = None - bitwise_builtin_applications: Optional[int] = None - keccak_builtin_applications: Optional[int] = None - memory_holes: Optional[int] = None - segment_arena_builtin: Optional[int] = None + 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): """ - Dataclass representing the the resources consumed by the transaction, includes both computation and data. + Dataclass representing the resources consumed by the transaction, includes both computation and data. """ - data_availability: Optional[DataResources] = None + data_availability: DataResources # TODO (#1219): split into PendingTransactionReceipt and TransactionReceipt @@ -594,12 +594,12 @@ class EstimatedFee: Dataclass representing estimated fee. """ - overall_fee: int - gas_price: int gas_consumed: int + gas_price: int + data_gas_consumed: int + data_gas_price: int + overall_fee: int unit: PriceUnit - data_gas_consumed: Optional[int] - data_gas_price: Optional[int] @dataclass @@ -883,7 +883,7 @@ class FunctionInvocation: calls: List["FunctionInvocation"] events: List[OrderedEvent] messages: List[OrderedMessage] - execution_resources: ExecutionResources + computation_resources: ComputationResources @dataclass @@ -902,7 +902,7 @@ class InvokeTransactionTrace: """ execute_invocation: Union[FunctionInvocation, RevertedFunctionInvocation] - execution_resources: Optional[ExecutionResources] = None + execution_resources: ExecutionResources validate_invocation: Optional[FunctionInvocation] = None fee_transfer_invocation: Optional[FunctionInvocation] = None state_diff: Optional[StateDiff] = None @@ -914,7 +914,7 @@ class DeclareTransactionTrace: Dataclass representing a transaction trace of an DECLARE transaction. """ - execution_resources: Optional[ExecutionResources] = None + execution_resources: ExecutionResources validate_invocation: Optional[FunctionInvocation] = None fee_transfer_invocation: Optional[FunctionInvocation] = None state_diff: Optional[StateDiff] = None @@ -927,7 +927,7 @@ class DeployAccountTransactionTrace: """ constructor_invocation: FunctionInvocation - execution_resources: Optional[ExecutionResources] = None + execution_resources: ExecutionResources validate_invocation: Optional[FunctionInvocation] = None fee_transfer_invocation: Optional[FunctionInvocation] = None state_diff: Optional[StateDiff] = None diff --git a/starknet_py/net/schemas/rpc.py b/starknet_py/net/schemas/rpc.py index 4ee02f777..bffdb33fa 100644 --- a/starknet_py/net/schemas/rpc.py +++ b/starknet_py/net/schemas/rpc.py @@ -124,8 +124,8 @@ def make_dataclass(self, data, **kwargs) -> L2toL1Message: class DataResourcesSchema(Schema): - l1_gas = Felt(data_key="l1_gas", required=True) - l1_data_gas = Felt(data_key="l1_data_gas", required=True) + 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: @@ -133,8 +133,9 @@ def make_dataclass(self, data, **kwargs) -> DataResources: class ComputationResourcesSchema(Schema): - steps = Felt(data_key="steps", required=True) - range_check_builtin_applications = Felt( + 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( @@ -158,7 +159,6 @@ class ComputationResourcesSchema(Schema): segment_arena_builtin = fields.Integer( data_key="segment_arena_builtin", load_default=None ) - memory_holes = fields.Integer(data_key="memory_holes", load_default=None) @post_load def make_dataclass(self, data, **kwargs) -> ComputationResources: @@ -167,7 +167,7 @@ def make_dataclass(self, data, **kwargs) -> ComputationResources: class ExecutionResourcesSchema(ComputationResourcesSchema): data_availability = fields.Nested( - DataResourcesSchema(), data_key="data_availability", load_default=None + DataResourcesSchema(), data_key="data_availability", required=True ) @post_load @@ -211,15 +211,15 @@ def make_dataclass(self, data, **kwargs) -> TransactionReceipt: class EstimatedFeeSchema(Schema): - overall_fee = Felt(data_key="overall_fee", required=True) - gas_price = Felt(data_key="gas_price", required=True) 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) + overall_fee = Felt(data_key="overall_fee", required=True) unit = PriceUnitField(data_key="unit", required=True) - data_gas_consumed = PriceUnitField(data_key="data_gas_consumed", load_default=None) - data_gas_price = PriceUnitField(data_key="data_gas_price", load_default=None) @post_load - def make_dataclass(self, data, **kwargs): + def make_dataclass(self, data, **kwargs) -> EstimatedFee: return EstimatedFee(**data) @@ -854,8 +854,8 @@ class FunctionInvocationSchema(Schema): messages = fields.List( fields.Nested(L2toL1MessageSchema()), data_key="messages", required=True ) - execution_resources = fields.Nested( - ExecutionResourcesSchema(), data_key="execution_resources", required=True + computation_resources = fields.Nested( + ComputationResourcesSchema(), data_key="execution_resources", required=True ) @post_load @@ -887,6 +887,9 @@ class InvokeTransactionTraceSchema(Schema): execute_invocation = fields.Nested( ExecuteInvocationSchema(), data_key="execute_invocation", required=True ) + execution_resources = fields.Nested( + ExecutionResourcesSchema(), data_key="execution_resources", required=True + ) validate_invocation = fields.Nested( FunctionInvocationSchema(), data_key="validate_invocation", load_default=None ) @@ -899,16 +902,15 @@ class InvokeTransactionTraceSchema(Schema): StateDiffSchema(), data_key="state_diff", load_default=None ) - execution_resources = fields.Nested( - ExecutionResourcesSchema(), data_key="execution_resources", load_default=None - ) - @post_load def make_dataclass(self, data, **kwargs) -> InvokeTransactionTrace: return InvokeTransactionTrace(**data) class DeclareTransactionTraceSchema(Schema): + execution_resources = fields.Nested( + ExecutionResourcesSchema(), data_key="execution_resources", required=True + ) validate_invocation = fields.Nested( FunctionInvocationSchema(), data_key="validate_invocation", load_default=None ) @@ -921,10 +923,6 @@ class DeclareTransactionTraceSchema(Schema): StateDiffSchema(), data_key="state_diff", load_default=None ) - execution_resources = fields.Nested( - ExecutionResourcesSchema(), data_key="execution_resources", load_default=None - ) - @post_load def make_dataclass(self, data, **kwargs) -> DeclareTransactionTrace: return DeclareTransactionTrace(**data) @@ -934,6 +932,9 @@ class DeployAccountTransactionTraceSchema(Schema): constructor_invocation = fields.Nested( FunctionInvocationSchema(), data_key="constructor_invocation", required=True ) + execution_resources = fields.Nested( + ExecutionResourcesSchema(), data_key="execution_resources", required=True + ) validate_invocation = fields.Nested( FunctionInvocationSchema(), data_key="validate_invocation", load_default=None ) @@ -946,10 +947,6 @@ class DeployAccountTransactionTraceSchema(Schema): StateDiffSchema(), data_key="state_diff", load_default=None ) - execution_resources = fields.Nested( - ExecutionResourcesSchema(), data_key="execution_resources", load_default=None - ) - @post_load def make_dataclass(self, data, **kwargs) -> DeployAccountTransactionTrace: return DeployAccountTransactionTrace(**data) 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 04d2d5dfb..375863d91 100644 --- a/starknet_py/tests/e2e/tests_on_networks/client_test.py +++ b/starknet_py/tests/e2e/tests_on_networks/client_test.py @@ -365,18 +365,6 @@ async def test_get_block_with_tx_hashes_new_header_fields(client_goerli_testnet) assert pending_block.l1_gas_price.price_in_wei > 0 -@pytest.mark.asyncio -async def test_get_tx_receipt_new_fields(client_goerli_testnet): - l1_handler_tx_hash = ( - 0xBEFE411182979262478CA8CA73BED724237D03D303CE420D94DE7664A78347 - ) - receipt = await client_goerli_testnet.get_transaction_receipt( - tx_hash=l1_handler_tx_hash - ) - - assert receipt.execution_resources is not None - - @pytest.mark.parametrize( "tx_hash, tx_type", [ From 8d46efb7ffda7395b7f204d973ce47699f84ddb7 Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Thu, 29 Feb 2024 18:26:36 +0100 Subject: [PATCH 05/19] Update docs and workflow --- .github/workflows/checks.yml | 2 -- docs/development.rst | 3 +-- docs/guide/account_and_client.rst | 4 +--- docs/migration_guide.rst | 24 +++++++++++++----------- 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 3afefab19..e9fb3ce02 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -1,8 +1,6 @@ name: Checks env: - STARKNET_VERSION: "0.13.0" - RPC_SPEC_VERSION: "0.6.0" DEVNET_SHA: "1bd447d" on: diff --git a/docs/development.rst b/docs/development.rst index 088d88374..614343ae3 100644 --- a/docs/development.rst +++ b/docs/development.rst @@ -24,11 +24,10 @@ Below is the command you can use to do this, designed for compatibility with the .. code-block:: bash - STARKNET_VERSION="0.13.0" RPC_SPEC_VERSION="0.6.0" \ cargo install \ --locked \ --git https://github.com/0xSpaceShard/starknet-devnet-rs.git \ - --rev 1bd447d + --rev 79a90fd If you choose to install `starknet-devnet-rs `_ using a different method, please make sure to add the executable ``starknet-devnet`` to your ``PATH`` environment variable. diff --git a/docs/guide/account_and_client.rst b/docs/guide/account_and_client.rst index fb627dd0d..94eb317f1 100644 --- a/docs/guide/account_and_client.rst +++ b/docs/guide/account_and_client.rst @@ -27,9 +27,7 @@ To enable auto estimation, set the ``auto_estimate`` parameter to ``True``. It is strongly discouraged to use automatic fee estimation in production code as it may lead to an unexpectedly high fee. -The returned estimated fee is multiplied by ``1.5`` for V1 and V2 transactions to mitigate fluctuations in price. -For V3 transactions, ``max_amount`` and ``max_price_per_unit`` are scaled by ``1.5``. - +The returned estimated fee is multiplied by ``1.5`` to mitigate fluctuations in price. .. note:: It is possible to configure the value by which the estimated fee is multiplied, diff --git a/docs/migration_guide.rst b/docs/migration_guide.rst index 0dc045393..776f722f5 100644 --- a/docs/migration_guide.rst +++ b/docs/migration_guide.rst @@ -5,12 +5,7 @@ Migration guide 0.21.0 Migration guide ********************** - -Version 0.21.0 of **starknet.py** comes with support for RPC 0.7.0 and python 3.12! - -New classes added to mirror the recent changes in the RPC v0.7.0 specification include: -:class:`StarknetBlockWithReceipts`, :class:`PendingStarknetBlockWithReceipts`, :class:`TransactionWithReceipt` :class:`DataResources`. - +Version 0.21.0 of **starknet.py** comes with support for RPC 0.7.0! 0.21.0 Targeted versions ------------------------ @@ -18,12 +13,19 @@ New classes added to mirror the recent changes in the RPC v0.7.0 specification i - Starknet - `0.13.1 `_ - RPC - `0.7.0 `_ -0.21.0 Minor changes --------------------- +0.21.0 Breaking changes +----------------------- + +.. currentmodule:: starknet_py.net.client_models -1. :class:`ExecutionResources` now has an additional optional field: ``data_availability`` -2. :class:`StarknetBlock`, :class:`StarknetBlockWithTxHashes`, :class:`PendingStarknetBlock` and :class:`PendingStarknetBlockWithTxHashes` now have two additional option fields: ``l1_data_gas_price`` and ``l1_da_mode``. -3. :class:`DeclareTransactionTrace`, :class:`InvokeTransactionTrace` and :class:`DeployAccountTransactionTrace` have additional field ``execution_resources`` +1. :class:`ExecutionResources` has a new required field ``data_availability`` +2. :class:`InvokeTransactionTrace`, :class:`DeclareTransactionTrace` and :class:`DeployAccountTransactionTrace` have a new required field ``execution_resources`` +3. :class:`PendingStarknetBlock` and :class:`PendingStarknetBlockWithTxHashes` field ``parent_block_hash`` has been renamed to ``parent_hash`` +4. :class:`StarknetBlockCommon` has been renamed to :class:`BlockHeader` +5. :class:`StarknetBlock` and :class:`StarknetBlockWithTxHashes` fields ``parent_block_hash`` and ``root`` have been renamed to ``parent_hash`` and ``new_root`` respectively +6. :class:`EstimatedFee` has new required fields ``data_gas_consumed`` and ``data_gas_price`` +7. :class:`FunctionInvocation` field ``execution_resources`` has been renamed to ``computation_resources`` +8. :class:`StarknetBlock`, :class:`PendingStarknetBlock`, :class:`StarknetBlockWithTxHashes`, :class:`PendingStarknetBlockWithTxHashes` have new required fields ``l1_data_gas_price`` and ``l1_da_mode`` ********************** 0.20.0 Migration guide From 1df4e61af84afe5dd575ee0bb9cdfa6bd5fa47f6 Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Thu, 29 Feb 2024 18:40:57 +0100 Subject: [PATCH 06/19] Increase max fee for devnet tests --- starknet_py/tests/e2e/account/account_test.py | 12 ++++++++---- starknet_py/tests/e2e/fixtures/constants.py | 6 ++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/starknet_py/tests/e2e/account/account_test.py b/starknet_py/tests/e2e/account/account_test.py index d5ee1a07d..7a1fd03c7 100644 --- a/starknet_py/tests/e2e/account/account_test.py +++ b/starknet_py/tests/e2e/account/account_test.py @@ -79,6 +79,7 @@ async def test_estimated_fee_greater_than_zero(account, erc20_contract): assert estimated_fee.overall_fee > 0 assert ( estimated_fee.gas_price * estimated_fee.gas_consumed + + estimated_fee.data_gas_price * estimated_fee.data_gas_consumed == estimated_fee.overall_fee ) @@ -94,7 +95,8 @@ async def test_estimate_fee_for_declare_transaction(account, map_compiled_contra assert isinstance(estimated_fee.overall_fee, int) assert estimated_fee.overall_fee > 0 assert ( - estimated_fee.gas_consumed * estimated_fee.gas_price + estimated_fee.gas_price * estimated_fee.gas_consumed + + estimated_fee.data_gas_price * estimated_fee.data_gas_consumed == estimated_fee.overall_fee ) @@ -113,7 +115,8 @@ async def test_account_estimate_fee_for_declare_transaction( assert isinstance(estimated_fee.overall_fee, int) assert estimated_fee.overall_fee > 0 assert ( - estimated_fee.gas_consumed * estimated_fee.gas_price + estimated_fee.gas_price * estimated_fee.gas_consumed + + estimated_fee.data_gas_price * estimated_fee.data_gas_consumed == estimated_fee.overall_fee ) @@ -143,6 +146,7 @@ async def test_account_estimate_fee_for_transactions( assert estimated_fee[0].overall_fee > 0 assert ( estimated_fee[0].gas_consumed * estimated_fee[0].gas_price + + estimated_fee[0].data_gas_consumed * estimated_fee[0].data_gas_price == estimated_fee[0].overall_fee ) @@ -786,7 +790,7 @@ async def test_argent_cairo1_account_deploy( client=client, constructor_calldata=[key_pair.public_key, 0], chain=StarknetChainId.GOERLI, - max_fee=int(1e16), + max_fee=int(1e18), ) await deploy_result.wait_for_acceptance() account = deploy_result.account @@ -825,7 +829,7 @@ async def test_argent_cairo1_account_execute( calldata=[value], ) execute = await argent_cairo1_account.execute_v1( - calls=increase_balance_by_20_call, max_fee=int(1e16) + calls=increase_balance_by_20_call, max_fee=int(1e18) ) await argent_cairo1_account.client.wait_for_tx(tx_hash=execute.transaction_hash) receipt = await argent_cairo1_account.client.get_transaction_receipt( diff --git a/starknet_py/tests/e2e/fixtures/constants.py b/starknet_py/tests/e2e/fixtures/constants.py index b48765e7d..b9a144175 100644 --- a/starknet_py/tests/e2e/fixtures/constants.py +++ b/starknet_py/tests/e2e/fixtures/constants.py @@ -90,9 +90,11 @@ def _get_env_lambda(env_name): "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d" ) -MAX_FEE = int(1e16) +MAX_FEE = int(1e18) -MAX_RESOURCE_BOUNDS_L1 = ResourceBounds(max_amount=5000, max_price_per_unit=int(2e12)) +MAX_RESOURCE_BOUNDS_L1 = ResourceBounds( + max_amount=int(1e5), max_price_per_unit=int(1e13) +) MAX_RESOURCE_BOUNDS = ResourceBoundsMapping( l1_gas=MAX_RESOURCE_BOUNDS_L1, l2_gas=ResourceBounds.init_with_zeros() ) From 1683b3bc87e4075f2bcd6712899fd69bf00449ad Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Thu, 29 Feb 2024 19:13:11 +0100 Subject: [PATCH 07/19] Add more tests --- starknet_py/tests/e2e/account/account_test.py | 4 +-- starknet_py/tests/e2e/block_test.py | 35 ++++++++----------- starknet_py/tests/e2e/client/client_test.py | 10 ++++++ .../tests/e2e/client/full_node_test.py | 6 ++++ .../guide/test_simple_declare_and_deploy.py | 4 +-- .../e2e/tests_on_networks/client_test.py | 3 ++ 6 files changed, 38 insertions(+), 24 deletions(-) diff --git a/starknet_py/tests/e2e/account/account_test.py b/starknet_py/tests/e2e/account/account_test.py index 7a1fd03c7..d981f185d 100644 --- a/starknet_py/tests/e2e/account/account_test.py +++ b/starknet_py/tests/e2e/account/account_test.py @@ -790,7 +790,7 @@ async def test_argent_cairo1_account_deploy( client=client, constructor_calldata=[key_pair.public_key, 0], chain=StarknetChainId.GOERLI, - max_fee=int(1e18), + max_fee=MAX_FEE, ) await deploy_result.wait_for_acceptance() account = deploy_result.account @@ -829,7 +829,7 @@ async def test_argent_cairo1_account_execute( calldata=[value], ) execute = await argent_cairo1_account.execute_v1( - calls=increase_balance_by_20_call, max_fee=int(1e18) + calls=increase_balance_by_20_call, max_fee=MAX_FEE ) await argent_cairo1_account.client.wait_for_tx(tx_hash=execute.transaction_hash) receipt = await argent_cairo1_account.client.get_transaction_receipt( diff --git a/starknet_py/tests/e2e/block_test.py b/starknet_py/tests/e2e/block_test.py index 0a9104ed6..c04484eae 100644 --- a/starknet_py/tests/e2e/block_test.py +++ b/starknet_py/tests/e2e/block_test.py @@ -3,12 +3,12 @@ from starknet_py.contract import Contract from starknet_py.net.account.base_account import BaseAccount from starknet_py.net.client_models import ( + BlockStatus, PendingStarknetBlock, - PendingStarknetBlockWithReceipts, PendingStarknetBlockWithTxHashes, StarknetBlock, + StarknetBlockWithReceipts, StarknetBlockWithTxHashes, - TransactionWithReceipt, ) from starknet_py.tests.e2e.fixtures.constants import MAX_FEE @@ -65,6 +65,9 @@ async def test_block_with_tx_hashes_latest( assert blk.new_root is not None assert blk.timestamp is not None assert blk.sequencer_address is not None + assert blk.l1_gas_price is not None + assert blk.l1_data_gas_price is not None + assert blk.l1_da_mode is not None @pytest.mark.asyncio @@ -91,32 +94,24 @@ async def test_get_block_with_txs_latest( assert blk.new_root is not None assert blk.timestamp is not None assert blk.sequencer_address is not None + assert blk.l1_gas_price is not None + assert blk.l1_data_gas_price is not None + assert blk.l1_da_mode is not None -@pytest.mark.skip @pytest.mark.asyncio -async def test_block_with_receipts_latest( - account, - map_contract_declare_hash, -): - blk = await account.client.get_block_with_tx_hashes(block_number="latest") +async def test_block_with_receipts_latest(account): + blk = await account.client.get_block_with_receipts(block_number="latest") - assert isinstance(blk, StarknetBlockWithTxHashes) + assert isinstance(blk, StarknetBlockWithReceipts) assert isinstance(blk.transactions, list) - assert map_contract_declare_hash in blk.transactions + assert blk.status == BlockStatus.ACCEPTED_ON_L2 assert blk.block_hash is not None assert blk.parent_hash is not None assert blk.block_number is not None assert blk.new_root is not None assert blk.timestamp is not None assert blk.sequencer_address is not None - - -@pytest.mark.skip -@pytest.mark.asyncio -async def test_block_with_receipts_pending(account): - blk = await account.client.get_block_with_receipts(block_number="pending") - - assert isinstance(blk, PendingStarknetBlockWithReceipts) - assert isinstance(blk.transactions, list) - assert isinstance(blk.transactions[0], TransactionWithReceipt) + assert blk.l1_gas_price is not None + assert blk.l1_data_gas_price is not None + assert blk.l1_da_mode is not None diff --git a/starknet_py/tests/e2e/client/client_test.py b/starknet_py/tests/e2e/client/client_test.py index 588194557..e88bad74f 100644 --- a/starknet_py/tests/e2e/client/client_test.py +++ b/starknet_py/tests/e2e/client/client_test.py @@ -154,6 +154,8 @@ async def test_estimate_fee_invoke(account, contract_address): 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 @pytest.mark.asyncio @@ -174,6 +176,8 @@ async def test_estimate_fee_invoke_v3(account, contract_address): 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 @pytest.mark.asyncio @@ -192,6 +196,8 @@ async def test_estimate_fee_declare(account): 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 @pytest.mark.asyncio @@ -203,6 +209,8 @@ async def test_estimate_fee_deploy_account(client, deploy_account_transaction): 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 @pytest.mark.asyncio @@ -240,6 +248,8 @@ async def test_estimate_fee_for_multiple_transactions( 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 @pytest.mark.asyncio diff --git a/starknet_py/tests/e2e/client/full_node_test.py b/starknet_py/tests/e2e/client/full_node_test.py index 41af869b9..6cd3dfd6c 100644 --- a/starknet_py/tests/e2e/client/full_node_test.py +++ b/starknet_py/tests/e2e/client/full_node_test.py @@ -456,6 +456,7 @@ async def test_simulate_transactions_invoke(account, deployed_balance_contract): assert isinstance(simulated_txs[0], SimulatedTransaction) assert isinstance(simulated_txs[0].transaction_trace, InvokeTransactionTrace) assert simulated_txs[0].transaction_trace.execute_invocation is not None + assert simulated_txs[0].transaction_trace.execution_resources is not None invoke_tx = await account.sign_invoke_v1(calls=[call, call], auto_estimate=True) simulated_txs = await account.client.simulate_transactions( @@ -465,6 +466,7 @@ async def test_simulate_transactions_invoke(account, deployed_balance_contract): assert isinstance(simulated_txs[0].transaction_trace, InvokeTransactionTrace) assert simulated_txs[0].transaction_trace.validate_invocation is not None assert simulated_txs[0].transaction_trace.execute_invocation is not None + assert simulated_txs[0].transaction_trace.execution_resources is not None @pytest.mark.asyncio @@ -481,6 +483,7 @@ async def test_simulate_transactions_declare(account): assert isinstance(simulated_txs[0].transaction_trace, DeclareTransactionTrace) assert simulated_txs[0].fee_estimation.overall_fee > 0 assert simulated_txs[0].transaction_trace.validate_invocation is not None + assert simulated_txs[0].transaction_trace.execution_resources is not None @pytest.mark.asyncio @@ -518,10 +521,12 @@ async def test_simulate_transactions_two_txs(account, deployed_balance_contract) assert simulated_txs[0].fee_estimation.overall_fee > 0 assert simulated_txs[0].transaction_trace.validate_invocation is not None assert simulated_txs[0].transaction_trace.execute_invocation is not None + assert simulated_txs[0].transaction_trace.execution_resources is not None assert isinstance(simulated_txs[1].transaction_trace, DeclareTransactionTrace) assert simulated_txs[1].fee_estimation.overall_fee > 0 assert simulated_txs[1].transaction_trace.validate_invocation is not None + assert simulated_txs[1].transaction_trace.execution_resources is not None @pytest.mark.asyncio @@ -555,3 +560,4 @@ async def test_simulate_transactions_deploy_account( assert isinstance(simulated_txs[0].transaction_trace, DeployAccountTransactionTrace) assert simulated_txs[0].fee_estimation.overall_fee > 0 assert simulated_txs[0].transaction_trace.constructor_invocation is not None + assert simulated_txs[0].transaction_trace.execution_resources is not None diff --git a/starknet_py/tests/e2e/docs/guide/test_simple_declare_and_deploy.py b/starknet_py/tests/e2e/docs/guide/test_simple_declare_and_deploy.py index c3f4d6930..c1d64a1d4 100644 --- a/starknet_py/tests/e2e/docs/guide/test_simple_declare_and_deploy.py +++ b/starknet_py/tests/e2e/docs/guide/test_simple_declare_and_deploy.py @@ -15,13 +15,13 @@ async def test_simple_declare_and_deploy(account, map_compiled_contract): # To declare through Contract class you have to compile a contract and pass it # to Contract.declare_v1 or Contract.declare_v3 declare_result = await Contract.declare_v1( - account=account, compiled_contract=compiled_contract, max_fee=int(1e16) + account=account, compiled_contract=compiled_contract, max_fee=int(1e18) ) # Wait for the transaction await declare_result.wait_for_acceptance() # After contract is declared it can be deployed - deploy_result = await declare_result.deploy_v1(max_fee=int(1e16)) + deploy_result = await declare_result.deploy_v1(max_fee=int(1e18)) await deploy_result.wait_for_acceptance() # You can pass more arguments to the `deploy` method. Check `API` section to learn more 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 375863d91..3fa2eb0bb 100644 --- a/starknet_py/tests/e2e/tests_on_networks/client_test.py +++ b/starknet_py/tests/e2e/tests_on_networks/client_test.py @@ -174,6 +174,8 @@ async def test_estimate_message_fee(client_goerli_integration): 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.unit is not None @@ -428,6 +430,7 @@ async def test_get_tx_receipt_with_execution_resources(client_sepolia_integratio ) assert receipt.execution_resources is not None + assert receipt.execution_resources.data_availability is not None assert receipt.execution_resources.steps is not None assert receipt.execution_resources.segment_arena_builtin is not None assert receipt.execution_resources.bitwise_builtin_applications is not None From 354e0db4a9d0c6b93d43a485b3609f4337e18787 Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Thu, 29 Feb 2024 20:55:53 +0100 Subject: [PATCH 08/19] Update devnet sha in the workflow --- .github/workflows/checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index e9fb3ce02..9d2a87f3f 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -1,7 +1,7 @@ name: Checks env: - DEVNET_SHA: "1bd447d" + DEVNET_SHA: "79a90fd" on: push: From 900f3e4354dcca4fcb6d07a879783e7614195b02 Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Thu, 29 Feb 2024 21:29:08 +0100 Subject: [PATCH 09/19] Fix failing docs test --- .../e2e/docs/guide/test_simple_declare_and_deploy_cairo1.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/starknet_py/tests/e2e/docs/guide/test_simple_declare_and_deploy_cairo1.py b/starknet_py/tests/e2e/docs/guide/test_simple_declare_and_deploy_cairo1.py index f8f72e72c..935ec1f56 100644 --- a/starknet_py/tests/e2e/docs/guide/test_simple_declare_and_deploy_cairo1.py +++ b/starknet_py/tests/e2e/docs/guide/test_simple_declare_and_deploy_cairo1.py @@ -19,12 +19,12 @@ async def test_simple_declare_and_deploy(account): account=account, compiled_contract=compiled_contract, compiled_contract_casm=compiled_contract_casm, - max_fee=int(1e16), + max_fee=int(1e18), ) await declare_result.wait_for_acceptance() deploy_result = await declare_result.deploy_v1( - constructor_args=constructor_args, max_fee=int(1e16) + constructor_args=constructor_args, max_fee=int(1e18) ) await deploy_result.wait_for_acceptance() From 6d6444e040138205679371d3799be58f5824fd3d Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Mon, 4 Mar 2024 10:54:16 +0100 Subject: [PATCH 10/19] Update estimated fee multiplier description in docs --- docs/guide/account_and_client.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/guide/account_and_client.rst b/docs/guide/account_and_client.rst index 94eb317f1..fa111b5f1 100644 --- a/docs/guide/account_and_client.rst +++ b/docs/guide/account_and_client.rst @@ -27,7 +27,8 @@ To enable auto estimation, set the ``auto_estimate`` parameter to ``True``. It is strongly discouraged to use automatic fee estimation in production code as it may lead to an unexpectedly high fee. -The returned estimated fee is multiplied by ``1.5`` to mitigate fluctuations in price. +The returned estimated fee is multiplied by ``1.5`` for V1 and V2 transactions to mitigate fluctuations in price. +For V3 transactions, ``max_amount`` and ``max_price_per_unit`` are scaled by ``1.5`` and ``1.5`` respectively. .. note:: It is possible to configure the value by which the estimated fee is multiplied, From 8b8ecd93322645f15f8c783845fae9646cb0eb4c Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Mon, 4 Mar 2024 11:01:01 +0100 Subject: [PATCH 11/19] Update devnet sha --- .github/workflows/checks.yml | 2 +- docs/development.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 9d2a87f3f..c0368e0df 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -1,7 +1,7 @@ name: Checks env: - DEVNET_SHA: "79a90fd" + DEVNET_SHA: "c6ffb99" on: push: diff --git a/docs/development.rst b/docs/development.rst index 614343ae3..39d863d78 100644 --- a/docs/development.rst +++ b/docs/development.rst @@ -27,7 +27,7 @@ Below is the command you can use to do this, designed for compatibility with the cargo install \ --locked \ --git https://github.com/0xSpaceShard/starknet-devnet-rs.git \ - --rev 79a90fd + --rev c6ffb99 If you choose to install `starknet-devnet-rs `_ using a different method, please make sure to add the executable ``starknet-devnet`` to your ``PATH`` environment variable. From ec6169bc3604cd95a9739109267de2d5a6634d5c Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Mon, 4 Mar 2024 11:20:14 +0100 Subject: [PATCH 12/19] Enhance asserts in block tests --- starknet_py/tests/e2e/block_test.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/starknet_py/tests/e2e/block_test.py b/starknet_py/tests/e2e/block_test.py index c04484eae..5a6320986 100644 --- a/starknet_py/tests/e2e/block_test.py +++ b/starknet_py/tests/e2e/block_test.py @@ -4,6 +4,7 @@ from starknet_py.net.account.base_account import BaseAccount from starknet_py.net.client_models import ( BlockStatus, + L1DAMode, PendingStarknetBlock, PendingStarknetBlockWithTxHashes, StarknetBlock, @@ -65,9 +66,11 @@ async def test_block_with_tx_hashes_latest( assert blk.new_root is not None assert blk.timestamp is not None assert blk.sequencer_address is not None - assert blk.l1_gas_price is not None - assert blk.l1_data_gas_price is not None - assert blk.l1_da_mode is not None + assert blk.l1_gas_price.price_in_wei > 0 + assert blk.l1_gas_price.price_in_fri > 0 + assert blk.l1_data_gas_price.price_in_wei >= 0 + assert blk.l1_data_gas_price.price_in_fri >= 0 + assert blk.l1_da_mode in L1DAMode @pytest.mark.asyncio @@ -94,9 +97,11 @@ async def test_get_block_with_txs_latest( assert blk.new_root is not None assert blk.timestamp is not None assert blk.sequencer_address is not None - assert blk.l1_gas_price is not None - assert blk.l1_data_gas_price is not None - assert blk.l1_da_mode is not None + assert blk.l1_gas_price.price_in_wei > 0 + assert blk.l1_gas_price.price_in_fri > 0 + assert blk.l1_data_gas_price.price_in_wei >= 0 + assert blk.l1_data_gas_price.price_in_fri >= 0 + assert blk.l1_da_mode in L1DAMode @pytest.mark.asyncio @@ -112,6 +117,8 @@ async def test_block_with_receipts_latest(account): assert blk.new_root is not None assert blk.timestamp is not None assert blk.sequencer_address is not None - assert blk.l1_gas_price is not None - assert blk.l1_data_gas_price is not None - assert blk.l1_da_mode is not None + assert blk.l1_gas_price.price_in_wei > 0 + assert blk.l1_gas_price.price_in_fri > 0 + assert blk.l1_data_gas_price.price_in_wei >= 0 + assert blk.l1_data_gas_price.price_in_fri >= 0 + assert blk.l1_da_mode in L1DAMode From 7077b932e3f9cc5026e52862da77246d6d9e26c2 Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Mon, 4 Mar 2024 11:41:19 +0100 Subject: [PATCH 13/19] Cover case when `estimated_fee.gas_price` equals 0 --- starknet_py/net/account/account.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/starknet_py/net/account/account.py b/starknet_py/net/account/account.py index f9ff857a1..a5f94a73d 100644 --- a/starknet_py/net/account/account.py +++ b/starknet_py/net/account/account.py @@ -167,6 +167,8 @@ async def _get_resource_bounds( max_amount=int( (estimated_fee.overall_fee / estimated_fee.gas_price) * Account.ESTIMATED_AMOUNT_MULTIPLIER + if estimated_fee.gas_price != 0 + else 0 ), max_price_per_unit=int( estimated_fee.gas_price * Account.ESTIMATED_UNIT_PRICE_MULTIPLIER From 41e57a1a7b4de4551caa421ed1ebb145f89718fb Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Mon, 4 Mar 2024 14:18:20 +0100 Subject: [PATCH 14/19] Update migration guide --- docs/migration_guide.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/migration_guide.rst b/docs/migration_guide.rst index ce11d6172..523915b78 100644 --- a/docs/migration_guide.rst +++ b/docs/migration_guide.rst @@ -18,19 +18,19 @@ Version 0.21.0 of **starknet.py** comes with support for RPC 0.7.0! .. currentmodule:: starknet_py.net.client_models -1. :class:`ExecutionResources` has a new required field ``data_availability`` -2. :class:`InvokeTransactionTrace`, :class:`DeclareTransactionTrace` and :class:`DeployAccountTransactionTrace` have a new required field ``execution_resources`` -3. :class:`PendingStarknetBlock` and :class:`PendingStarknetBlockWithTxHashes` field ``parent_block_hash`` has been renamed to ``parent_hash`` -4. :class:`StarknetBlockCommon` has been renamed to :class:`BlockHeader` -5. :class:`StarknetBlock` and :class:`StarknetBlockWithTxHashes` fields ``parent_block_hash`` and ``root`` have been renamed to ``parent_hash`` and ``new_root`` respectively -6. :class:`EstimatedFee` has new required fields ``data_gas_consumed`` and ``data_gas_price`` -7. :class:`FunctionInvocation` field ``execution_resources`` has been renamed to ``computation_resources`` -8. :class:`StarknetBlock`, :class:`PendingStarknetBlock`, :class:`StarknetBlockWithTxHashes`, :class:`PendingStarknetBlockWithTxHashes` have new required fields ``l1_data_gas_price`` and ``l1_da_mode`` +1. :class:`PendingStarknetBlock` and :class:`PendingStarknetBlockWithTxHashes` field ``parent_block_hash`` has been renamed to ``parent_hash`` +2. :class:`StarknetBlockCommon` has been renamed to :class:`BlockHeader` +3. :class:`StarknetBlock` and :class:`StarknetBlockWithTxHashes` fields ``parent_block_hash`` and ``root`` have been renamed to ``parent_hash`` and ``new_root`` respectively +4. :class:`FunctionInvocation` field ``execution_resources`` has been renamed to ``computation_resources`` 0.21.0 Minor changes ----------------------- 1. :class:`EventsChunk` field ``events`` is now a list of :class:`EmittedEvent` instead of :class:`Event` +2. :class:`ExecutionResources` has a new required field ``data_availability`` +3. :class:`InvokeTransactionTrace`, :class:`DeclareTransactionTrace` and :class:`DeployAccountTransactionTrace` have a new required field ``execution_resources`` +4. :class:`EstimatedFee` has new required fields ``data_gas_consumed`` and ``data_gas_price`` +5. :class:`StarknetBlock`, :class:`PendingStarknetBlock`, :class:`StarknetBlockWithTxHashes`, :class:`PendingStarknetBlockWithTxHashes` have new required fields ``l1_data_gas_price`` and ``l1_da_mode`` ********************** 0.20.0 Migration guide From 543c3712da614ea887f97c632e76b1d07e8af692 Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Fri, 8 Mar 2024 13:23:10 +0100 Subject: [PATCH 15/19] Fix `trace_transaction` --- starknet_py/net/full_node_client.py | 2 +- starknet_py/net/schemas/rpc.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/starknet_py/net/full_node_client.py b/starknet_py/net/full_node_client.py index f364fe39b..8a8a2fcda 100644 --- a/starknet_py/net/full_node_client.py +++ b/starknet_py/net/full_node_client.py @@ -716,7 +716,7 @@ async def trace_transaction( res = await self._client.call( method_name="traceTransaction", params={ - "transaction_hash": tx_hash, + "transaction_hash": _to_rpc_felt(tx_hash), }, ) return cast( diff --git a/starknet_py/net/schemas/rpc.py b/starknet_py/net/schemas/rpc.py index 023fc2477..7d648ca3f 100644 --- a/starknet_py/net/schemas/rpc.py +++ b/starknet_py/net/schemas/rpc.py @@ -863,7 +863,7 @@ class FunctionInvocationSchema(Schema): fields.Nested(OrderedEventSchema()), data_key="events", required=True ) messages = fields.List( - fields.Nested(L2toL1MessageSchema()), data_key="messages", required=True + fields.Nested(OrderedMessageSchema()), data_key="messages", required=True ) computation_resources = fields.Nested( ComputationResourcesSchema(), data_key="execution_resources", required=True From 0abe8e4ffee9e1bdb83381592e735aedb43cd0d2 Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Fri, 8 Mar 2024 13:23:53 +0100 Subject: [PATCH 16/19] Reorder fields in `TransactionReceipt` --- starknet_py/net/client_models.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/starknet_py/net/client_models.py b/starknet_py/net/client_models.py index 91d0c8cdd..7a3783206 100644 --- a/starknet_py/net/client_models.py +++ b/starknet_py/net/client_models.py @@ -420,12 +420,11 @@ class TransactionReceipt: events: List[Event] = field(default_factory=list) messages_sent: List[L2toL1Message] = field(default_factory=list) - contract_address: Optional[int] = None - block_number: Optional[int] = None block_hash: Optional[int] = None - message_hash: Optional[int] = None # L1_HANDLER_TXN_RECEIPT-only + contract_address: Optional[int] = None # DEPLOY_ACCOUNT_TXN_RECEIPT only + message_hash: Optional[int] = None # L1_HANDLER_TXN_RECEIPT only revert_reason: Optional[str] = None From 5d8e3c85ba32f222fa429c28a7028db8e8ac3420 Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Fri, 8 Mar 2024 13:24:16 +0100 Subject: [PATCH 17/19] Run trace api tests on integration --- .../e2e/tests_on_networks/client_test.py | 3 +- .../e2e/tests_on_networks/trace_api_test.py | 54 ++++++++++--------- 2 files changed, 31 insertions(+), 26 deletions(-) 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 7b4f7cf89..2cc46e966 100644 --- a/starknet_py/tests/e2e/tests_on_networks/client_test.py +++ b/starknet_py/tests/e2e/tests_on_networks/client_test.py @@ -16,7 +16,6 @@ EstimatedFee, EventsChunk, InvokeTransactionV3, - L1DAMode, PendingBlockHeader, PendingStarknetBlockWithReceipts, ResourceBoundsMapping, @@ -100,7 +99,7 @@ async def test_transaction_not_received_max_fee_too_small(account_goerli_testnet ) sign_invoke = await account.sign_invoke_v1(calls=call, max_fee=int(1e10)) - with pytest.raises(ClientError, match=r".*Max fee.*"): + with pytest.raises(ClientError, match=r".*MaxFeeTooLow.*"): await account.client.send_transaction(sign_invoke) diff --git a/starknet_py/tests/e2e/tests_on_networks/trace_api_test.py b/starknet_py/tests/e2e/tests_on_networks/trace_api_test.py index c39dfedbf..13f5fd561 100644 --- a/starknet_py/tests/e2e/tests_on_networks/trace_api_test.py +++ b/starknet_py/tests/e2e/tests_on_networks/trace_api_test.py @@ -2,6 +2,7 @@ from starknet_py.net.client_models import ( DeclareTransactionTrace, + DeclareTransactionV1, DeclareTransactionV2, DeployAccountTransactionTrace, DeployAccountTransactionV1, @@ -21,79 +22,84 @@ @pytest.mark.asyncio -async def test_trace_transaction(client_goerli_testnet): +async def test_trace_transaction(client_goerli_integration): tx_to_trace: dict[type[Transaction], type[TransactionTrace]] = { InvokeTransactionV0: InvokeTransactionTrace, InvokeTransactionV1: InvokeTransactionTrace, + DeclareTransactionV1: DeclareTransactionTrace, DeclareTransactionV2: DeclareTransactionTrace, DeployAccountTransactionV1: DeployAccountTransactionTrace, L1HandlerTransaction: L1HandlerTransactionTrace, } - block = await client_goerli_testnet.get_block(block_number=600000) + block = await client_goerli_integration.get_block(block_number=319080) for tx in block.transactions: - trace = await client_goerli_testnet.trace_transaction(tx_hash=tx.hash) - tx = await client_goerli_testnet.get_transaction(tx_hash=tx.hash) + trace = await client_goerli_integration.trace_transaction(tx_hash=tx.hash) + tx = await client_goerli_integration.get_transaction(tx_hash=tx.hash) assert tx_to_trace[type(tx)] == type(trace) @pytest.mark.asyncio -async def test_trace_transaction_invoke(client_goerli_testnet): - invoke_tx_hash = 0xDC6B381884866DD6C4ACCDE75AA1FA7506E6B57612D3D3659F7B919EA07D7C - trace = await client_goerli_testnet.trace_transaction(tx_hash=invoke_tx_hash) +async def test_trace_transaction_invoke(client_goerli_integration): + invoke_tx_hash = 0x05C3407F664E9A95A809FA0E0EB35C941863D280F30F73E292DA2F06779F7C59 + trace = await client_goerli_integration.trace_transaction(tx_hash=invoke_tx_hash) assert type(trace) is InvokeTransactionTrace assert trace.execute_invocation is not None + assert trace.execution_resources is not None @pytest.mark.asyncio -async def test_trace_transaction_declare(client_goerli_testnet): - declare_tx_hash = 0x62DD22627065568C6E4BD619C511217456B5A82ACBDEAD7C3B5DFFF92209451 - trace = await client_goerli_testnet.trace_transaction(tx_hash=declare_tx_hash) +async def test_trace_transaction_declare(client_goerli_integration): + declare_tx_hash = 0x05C2B2EE93E7BD33B911AFC822289EED2AE3A3B27CAECF92D7F793C5379C13D6 + trace = await client_goerli_integration.trace_transaction(tx_hash=declare_tx_hash) assert type(trace) is DeclareTransactionTrace + assert trace.execution_resources is not None @pytest.mark.asyncio -async def test_trace_transaction_deploy_account(client_goerli_testnet): +async def test_trace_transaction_deploy_account(client_goerli_integration): deploy_account_tx_hash = ( - 0x7AD24E5D266CE371EC88C1AE537A92109E8AF637C35673B6D459082431AF7B + 0x0270E24EA145B0A6022D0C50A97598B3BDCAB812BCCC24A97FFBB4365F90962C ) - trace = await client_goerli_testnet.trace_transaction( + trace = await client_goerli_integration.trace_transaction( tx_hash=deploy_account_tx_hash ) assert type(trace) is DeployAccountTransactionTrace assert trace.constructor_invocation is not None + assert trace.execution_resources is not None @pytest.mark.asyncio -async def test_trace_transaction_l1_handler(client_goerli_testnet): +async def test_trace_transaction_l1_handler(client_goerli_integration): l1_handler_tx_hash = ( - 0x6712D5CF540C1C2E51C03D6238F71CF86607F681669AF586CD2EB8A92AF68AC + 0x04D54ACFEDB65334C2D8C4DB67E320E2ACA692412FD0E1311846FFCA568EFFAD + ) + trace = await client_goerli_integration.trace_transaction( + tx_hash=l1_handler_tx_hash ) - trace = await client_goerli_testnet.trace_transaction(tx_hash=l1_handler_tx_hash) assert type(trace) is L1HandlerTransactionTrace assert trace.function_invocation is not None @pytest.mark.asyncio -async def test_trace_transaction_reverted(client_goerli_testnet): - tx_hash = "0x604371f9414d26ad9e745301596de1d1219c1045f00c68d3be9bd195eb18632" - trace = await client_goerli_testnet.trace_transaction(tx_hash=tx_hash) +async def test_trace_transaction_reverted(client_goerli_integration): + tx_hash = 0x0306673636C16CD3EC686EDCF24383D50099CD66C91CC89EC904AC8882BFB30C + trace = await client_goerli_integration.trace_transaction(tx_hash=tx_hash) assert isinstance(trace.execute_invocation, RevertedFunctionInvocation) @pytest.mark.asyncio -async def test_get_block_traces(client_goerli_testnet): - # 800002 because I guess sometimes juno doesn't return valid transactions/parses input wrong - block_number = 800006 - block_transaction_traces = await client_goerli_testnet.trace_block_transactions( +async def test_get_block_traces(client_goerli_integration): + block_number = 329180 + block_transaction_traces = await client_goerli_integration.trace_block_transactions( block_number=block_number ) - block = await client_goerli_testnet.get_block(block_number=block_number) + block = await client_goerli_integration.get_block(block_number=block_number) assert len(block_transaction_traces) == len(block.transactions) for i in range(len(block_transaction_traces)): From f3e91e567ccc515facaf4fd5c09e260a445155e1 Mon Sep 17 00:00:00 2001 From: Dariusz Doktorski Date: Fri, 8 Mar 2024 13:30:13 +0100 Subject: [PATCH 18/19] Add alpha infromation to migration guide --- docs/migration_guide.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/migration_guide.rst b/docs/migration_guide.rst index 523915b78..07fab2802 100644 --- a/docs/migration_guide.rst +++ b/docs/migration_guide.rst @@ -1,9 +1,9 @@ Migration guide =============== -********************** -0.21.0 Migration guide -********************** +****************************** +0.21.0 (alpha) Migration guide +****************************** Version 0.21.0 of **starknet.py** comes with support for RPC 0.7.0! @@ -11,7 +11,7 @@ Version 0.21.0 of **starknet.py** comes with support for RPC 0.7.0! ------------------------ - Starknet - `0.13.1 `_ -- RPC - `0.7.0 `_ +- RPC - `0.7.0-rc2 `_ 0.21.0 Breaking changes ----------------------- From 0114df53c19dc2929380c12cb2bc2c005cd2d0ad Mon Sep 17 00:00:00 2001 From: ddoktorski <45050160+ddoktorski@users.noreply.github.com> Date: Fri, 8 Mar 2024 15:36:25 +0100 Subject: [PATCH 19/19] Update docs/migration_guide.rst Co-authored-by: Maksim Zdobnikau <43750648+DelevoXDG@users.noreply.github.com> --- docs/migration_guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/migration_guide.rst b/docs/migration_guide.rst index 07fab2802..573af5d94 100644 --- a/docs/migration_guide.rst +++ b/docs/migration_guide.rst @@ -5,7 +5,7 @@ Migration guide 0.21.0 (alpha) Migration guide ****************************** -Version 0.21.0 of **starknet.py** comes with support for RPC 0.7.0! +Version 0.21.0 of **starknet.py** comes with support for RPC 0.7.0-rc2! 0.21.0 Targeted versions ------------------------