Skip to content

Commit 79b6659

Browse files
Change cairo_version into Account property (#1183)
* add cairo_version property, remove it from arguments in methods * change cairo_version * update Account.deploy_account * add tests * add precompiled contracts * update docs * deprecate cairo_version parameter from previous impl * change previous parameter into Optional * update BaseAccount interface * update migration guide * update docs code snippets * check docs * formatting * docs * fix devnet version on windows checks * docstrings once again * add todos * add test for codecov * formatting * add a helper comment * remove cairo_version from Account constructor, change cairo_version property * remove unnecessary pyright comment * change cairo_version into async property * fix tests * another tests fix * another tests fix * woops
1 parent ff2639e commit 79b6659

File tree

12 files changed

+40395
-23
lines changed

12 files changed

+40395
-23
lines changed

.github/workflows/checks.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ jobs:
340340
apt-get install -y python3-pip
341341
sudo apt install -y libgmp3-dev
342342
sudo apt-get install -y git
343-
pip3 install git+https://github.com/0xSpaceShard/starknet-devnet.git@v0.5.5
343+
pip3 install git+https://github.com/0xSpaceShard/starknet-devnet.git@v0.6.2
344344
345345
# ====================== SETUP PYTHON ====================== #
346346

@@ -492,7 +492,7 @@ jobs:
492492
apt-get install -y python3-pip
493493
sudo apt install -y libgmp3-dev
494494
sudo apt-get install -y git
495-
pip3 install git+https://github.com/0xSpaceShard/starknet-devnet.git@v0.5.5
495+
pip3 install git+https://github.com/0xSpaceShard/starknet-devnet.git@v0.6.2
496496
497497
# ====================== SETUP PYTHON ====================== #
498498

docs/migration_guide.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Migration guide
66
**********************
77

88
Version 0.18.2 of **starknet.py** comes with support of `RPC v0.4.0 <https://github.com/starkware-libs/starknet-specs/releases/tag/v0.4.0>`_ Trace API!
9+
Additionally, you can now `properly` use Cairo1 accounts! ``starknet.py`` automatically checks if your account is in Cairo1 and
10+
sets the calldata encoding accordingly.
911

1012
0.18.2 Targeted versions
1113
------------------------
@@ -21,6 +23,14 @@ Version 0.18.2 of **starknet.py** comes with support of `RPC v0.4.0 <https://git
2123
1. :meth:`Client.get_block_traces` has been renamed to :meth:`Client.trace_block_transactions` in order to match RPC specification.
2224

2325

26+
0.18.2 Deprecations
27+
-------------------
28+
29+
.. currentmodule:: starknet_py.net.account.account
30+
31+
1. ``cairo_version`` parameter in :meth:`Account.sign_invoke_transaction` and :meth:`Account.execute` has been deprecated.
32+
33+
2434
0.18.2 Minor changes
2535
--------------------
2636

@@ -30,6 +40,10 @@ Version 0.18.2 of **starknet.py** comes with support of `RPC v0.4.0 <https://git
3040

3141
2. ``include_block`` parameter in :meth:`GatewayClient.get_state_update` now works on gateway mainnet.
3242

43+
.. currentmodule:: starknet_py.net.account.account
44+
45+
3. :class:`BaseAccount` interface and :class:`Account` now have an additional **async** property - ``cairo_version``.
46+
3347

3448
0.18.2 Development-related changes
3549
----------------------------------

starknet_py/net/account/account.py

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@
1818
EstimatedFee,
1919
Hash,
2020
SentTransactionResponse,
21+
SierraContractClass,
2122
Tag,
2223
)
24+
from starknet_py.net.full_node_client import FullNodeClient
25+
from starknet_py.net.gateway_client import GatewayClient
2326
from starknet_py.net.models import AddressRepresentation, StarknetChainId, parse_address
2427
from starknet_py.net.models.transaction import (
2528
AccountTransaction,
@@ -74,6 +77,7 @@ def __init__(
7477
"""
7578
self._address = parse_address(address)
7679
self._client = client
80+
self._cairo_version = None
7781

7882
if signer is not None and key_pair is not None:
7983
raise ValueError("Arguments signer and key_pair are mutually exclusive.")
@@ -96,6 +100,23 @@ def __init__(
96100
def address(self) -> int:
97101
return self._address
98102

103+
@property
104+
async def cairo_version(self) -> int:
105+
if self._cairo_version is None:
106+
if isinstance(self._client, GatewayClient):
107+
contract_class = await self._client.get_full_contract(
108+
contract_address=self._address
109+
)
110+
else:
111+
assert isinstance(self._client, FullNodeClient)
112+
contract_class = await self._client.get_class_at(
113+
contract_address=self._address
114+
)
115+
self._cairo_version = (
116+
1 if isinstance(contract_class, SierraContractClass) else 0
117+
)
118+
return self._cairo_version
119+
99120
@property
100121
def client(self) -> Client:
101122
return self._client
@@ -137,7 +158,6 @@ async def _prepare_invoke(
137158
nonce: Optional[int] = None,
138159
max_fee: Optional[int] = None,
139160
auto_estimate: bool = False,
140-
cairo_version: int = 0,
141161
) -> Invoke:
142162
"""
143163
Takes calls and creates Invoke from them.
@@ -150,7 +170,7 @@ async def _prepare_invoke(
150170
if nonce is None:
151171
nonce = await self.get_nonce()
152172

153-
if cairo_version == 1:
173+
if await self.cairo_version == 1:
154174
parsed_calls = _parse_calls_v2(ensure_iterable(calls))
155175
wrapped_calldata = _execute_payload_serializer_v2.serialize(
156176
{"calls": parsed_calls}
@@ -253,14 +273,22 @@ async def sign_invoke_transaction(
253273
nonce: Optional[int] = None,
254274
max_fee: Optional[int] = None,
255275
auto_estimate: bool = False,
256-
cairo_version: int = 0,
276+
# TODO (#1184): remove that
277+
cairo_version: Optional[int] = None,
257278
) -> Invoke:
279+
# TODO (#1184): remove that
280+
if cairo_version is not None:
281+
warnings.warn(
282+
"Parameter 'cairo_version' has been deprecated. It is calculated automatically based on your account's "
283+
"contract class.",
284+
category=DeprecationWarning,
285+
)
286+
258287
execute_tx = await self._prepare_invoke(
259288
calls,
260289
nonce=nonce,
261290
max_fee=max_fee,
262291
auto_estimate=auto_estimate,
263-
cairo_version=cairo_version,
264292
)
265293
signature = self.signer.sign_transaction(execute_tx)
266294
return _add_signature_to_transaction(execute_tx, signature)
@@ -387,14 +415,22 @@ async def execute(
387415
nonce: Optional[int] = None,
388416
max_fee: Optional[int] = None,
389417
auto_estimate: bool = False,
390-
cairo_version: int = 0,
418+
# TODO (#1184): remove that
419+
cairo_version: Optional[int] = None,
391420
) -> SentTransactionResponse:
421+
# TODO (#1184): remove that
422+
if cairo_version is not None:
423+
warnings.warn(
424+
"Parameter 'cairo_version' has been deprecated. It is calculated automatically based on your account's "
425+
"contract class.",
426+
category=DeprecationWarning,
427+
)
428+
392429
execute_transaction = await self.sign_invoke_transaction(
393430
calls,
394431
nonce=nonce,
395432
max_fee=max_fee,
396433
auto_estimate=auto_estimate,
397-
cairo_version=cairo_version,
398434
)
399435
return await self._client.send_transaction(execute_transaction)
400436

@@ -464,7 +500,10 @@ async def deploy_account(
464500
)
465501

466502
account = Account(
467-
address=address, client=client, key_pair=key_pair, chain=chain
503+
address=address,
504+
client=client,
505+
key_pair=key_pair,
506+
chain=chain,
468507
)
469508

470509
deploy_account_tx = await account.sign_deploy_account_transaction(

starknet_py/net/account/base_account.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ def address(self) -> int:
2828
Get the address of the account
2929
"""
3030

31+
@property
32+
@abstractmethod
33+
async def cairo_version(self) -> int:
34+
"""
35+
Get Cairo version of the account.
36+
"""
37+
3138
@property
3239
@abstractmethod
3340
def client(self) -> Client:
@@ -102,6 +109,8 @@ async def sign_invoke_transaction(
102109
nonce: Optional[int] = None,
103110
max_fee: Optional[int] = None,
104111
auto_estimate: bool = False,
112+
# TODO (#1184): remove that and docstring
113+
cairo_version: Optional[int] = None,
105114
) -> Invoke:
106115
"""
107116
Takes calls and creates signed Invoke.
@@ -110,6 +119,12 @@ async def sign_invoke_transaction(
110119
:param nonce: Nonce of the transaction.
111120
:param max_fee: Max amount of Wei to be paid when executing transaction.
112121
:param auto_estimate: Use automatic fee estimation, not recommend as it may lead to high costs.
122+
:param cairo_version:
123+
Cairo version of the account used.
124+
125+
.. deprecated:: 0.18.2
126+
Parameter `cairo_version` has been deprecated - it is calculated automatically based on
127+
your account's contract class.
113128
:return: Invoke created from the calls.
114129
"""
115130

@@ -188,6 +203,8 @@ async def execute(
188203
nonce: Optional[int] = None,
189204
max_fee: Optional[int] = None,
190205
auto_estimate: bool = False,
206+
# TODO (#1184): remove that and docstring
207+
cairo_version: Optional[int] = None,
191208
) -> SentTransactionResponse:
192209
"""
193210
Takes calls and executes transaction.
@@ -196,6 +213,12 @@ async def execute(
196213
:param nonce: Nonce of the transaction.
197214
:param max_fee: Max amount of Wei to be paid when executing transaction.
198215
:param auto_estimate: Use automatic fee estimation, not recommend as it may lead to high costs.
216+
:param cairo_version:
217+
Cairo version of the account used.
218+
219+
.. deprecated:: 0.18.2
220+
Parameter `cairo_version` has been deprecated - it is calculated automatically based on
221+
your account's contract class.
199222
:return: SentTransactionResponse.
200223
"""
201224

starknet_py/tests/e2e/account/account_test.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
DeployAccountTransaction,
1616
DeployAccountTransactionResponse,
1717
EstimatedFee,
18+
SierraContractClass,
1819
TransactionStatus,
1920
)
2021
from starknet_py.net.full_node_client import FullNodeClient
@@ -591,3 +592,107 @@ async def test_sign_transaction_custom_nonce(account, cairo1_hello_starknet_clas
591592

592593
assert invoke_tx.nonce == deploy_tx.nonce + 1
593594
assert result == [new_balance]
595+
596+
597+
@pytest.mark.asyncio
598+
async def test_argent_cairo1_account_deploy(
599+
full_node_client,
600+
argent_cairo1_account_class_hash,
601+
deploy_account_details_factory,
602+
):
603+
address, key_pair, salt, class_hash = await deploy_account_details_factory.get(
604+
class_hash=argent_cairo1_account_class_hash, argent_calldata=True
605+
)
606+
607+
deploy_result = await Account.deploy_account(
608+
address=address,
609+
class_hash=class_hash,
610+
salt=salt,
611+
key_pair=key_pair,
612+
client=full_node_client,
613+
constructor_calldata=[key_pair.public_key, 0],
614+
chain=StarknetChainId.TESTNET,
615+
max_fee=int(1e16),
616+
)
617+
await deploy_result.wait_for_acceptance()
618+
account = deploy_result.account
619+
620+
assert isinstance(account, BaseAccount)
621+
assert await account.cairo_version == 1
622+
623+
account_contract_class = await full_node_client.get_class_at(
624+
contract_address=account.address, block_number="latest"
625+
)
626+
627+
assert isinstance(account_contract_class, SierraContractClass)
628+
629+
630+
@pytest.mark.asyncio
631+
async def test_argent_cairo1_account_execute(
632+
deployed_balance_contract,
633+
argent_cairo1_account: BaseAccount,
634+
):
635+
# verify that initial balance is 0
636+
get_balance_call = Call(
637+
to_addr=deployed_balance_contract.address,
638+
selector=get_selector_from_name("get_balance"),
639+
calldata=[],
640+
)
641+
get_balance = await argent_cairo1_account.client.call_contract(
642+
call=get_balance_call, block_number="latest"
643+
)
644+
645+
assert get_balance[0] == 0
646+
647+
value = 20
648+
increase_balance_by_20_call = Call(
649+
to_addr=deployed_balance_contract.address,
650+
selector=get_selector_from_name("increase_balance"),
651+
calldata=[value],
652+
)
653+
execute = await argent_cairo1_account.execute(
654+
calls=increase_balance_by_20_call, max_fee=int(1e16)
655+
)
656+
await argent_cairo1_account.client.wait_for_tx(tx_hash=execute.transaction_hash)
657+
receipt = await argent_cairo1_account.client.get_transaction_receipt(
658+
tx_hash=execute.transaction_hash
659+
)
660+
661+
# TODO (#1179): devnet 0.3.0 still return STATUS instead of FINALITY_STATUS
662+
assert receipt.status == TransactionStatus.ACCEPTED_ON_L2
663+
664+
# verify that the previous call was executed
665+
get_balance_call = Call(
666+
to_addr=deployed_balance_contract.address,
667+
selector=get_selector_from_name("get_balance"),
668+
calldata=[],
669+
)
670+
get_balance = await argent_cairo1_account.client.call_contract(
671+
call=get_balance_call, block_number="latest"
672+
)
673+
674+
assert get_balance[0] == value
675+
676+
677+
# TODO (#1184): remove that
678+
@pytest.mark.asyncio
679+
async def test_cairo1_account_deprecations(
680+
deployed_balance_contract,
681+
argent_cairo1_account: BaseAccount,
682+
):
683+
call = Call(
684+
to_addr=deployed_balance_contract.address,
685+
selector=get_selector_from_name("increase_balance"),
686+
calldata=[20],
687+
)
688+
with pytest.warns(
689+
DeprecationWarning,
690+
match="Parameter 'cairo_version' has been deprecated. It is calculated automatically based on your account's "
691+
"contract class.",
692+
):
693+
_ = await argent_cairo1_account.execute(
694+
calls=call, max_fee=int(1e16), cairo_version=1
695+
)
696+
_ = await argent_cairo1_account.sign_invoke_transaction(
697+
calls=call, max_fee=int(1e16), cairo_version=1
698+
)

starknet_py/tests/e2e/docs/guide/test_account_sign_without_execute.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ async def test_account_sign_without_execute(account, map_compiled_contract):
2020
call = Call(to_addr=address, selector=selector, calldata=calldata)
2121
invoke_transaction = await account.sign_invoke_transaction(call, max_fee=max_fee)
2222
# Or if you're using Cairo1 account with new calldata encoding
23-
invoke_transaction = await account.sign_invoke_transaction(
24-
call, max_fee=max_fee, cairo_version=1
25-
)
23+
invoke_transaction = await account.sign_invoke_transaction(call, max_fee=max_fee)
2624

2725
# Create a signed Declare transaction
2826
declare_transaction = await account.sign_declare_transaction(

starknet_py/tests/e2e/docs/guide/test_custom_nonce.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66

77

88
@pytest.mark.asyncio
9-
async def test_custom_nonce(full_node_client):
9+
async def test_custom_nonce(full_node_account):
1010
# pylint: disable=import-outside-toplevel
11-
address = 0x1
12-
client = full_node_client
13-
private_key = 0x1
11+
client = full_node_account.client
12+
address = full_node_account.address
13+
private_key = full_node_account.signer.key_pair.private_key
1414

1515
# docs: start
1616
from starknet_py.net.account.account import Account

0 commit comments

Comments
 (0)