Skip to content

Commit df9a651

Browse files
authored
Add Account.deploy_account_v3 static method (#1265)
* Add `_prepare_account_to_deploy` function * Rename `Account.deploy_account` to have `v1` postfix * Add `Account.deploy_account_v3` function * Make if condition shorter * Rename parse calls related methods * Rename `execute` to `execute_v1` * Update docstrings
1 parent 4d6175c commit df9a651

File tree

15 files changed

+184
-74
lines changed

15 files changed

+184
-74
lines changed

starknet_py/contract.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ async def deploy(
241241
calldata=constructor_args,
242242
cairo_version=self._cairo_version,
243243
)
244-
res = await self._account.execute(
244+
res = await self._account.execute_v1(
245245
calls=deploy_call, nonce=nonce, max_fee=max_fee, auto_estimate=auto_estimate
246246
)
247247

@@ -728,7 +728,7 @@ async def deploy_contract(
728728
calldata=constructor_args,
729729
cairo_version=cairo_version,
730730
)
731-
res = await account.execute(
731+
res = await account.execute_v1(
732732
calls=deploy_call, nonce=nonce, max_fee=max_fee, auto_estimate=auto_estimate
733733
)
734734

starknet_py/net/account/account.py

Lines changed: 126 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ async def sign_deploy_account_v3_transaction(
550550
signature = self.signer.sign_transaction(deploy_account_tx)
551551
return _add_signature_to_transaction(deploy_account_tx, signature)
552552

553-
async def execute(
553+
async def execute_v1(
554554
self,
555555
calls: Calls,
556556
*,
@@ -592,7 +592,7 @@ def verify_message(self, typed_data: TypedData, signature: List[int]) -> bool:
592592
return verify_message_signature(message_hash, signature, self.signer.public_key)
593593

594594
@staticmethod
595-
async def deploy_account(
595+
async def deploy_account_v1(
596596
*,
597597
address: AddressRepresentation,
598598
class_hash: int,
@@ -605,53 +605,41 @@ async def deploy_account(
605605
max_fee: Optional[int] = None,
606606
auto_estimate: bool = False,
607607
) -> AccountDeploymentResult:
608-
# pylint: disable=too-many-locals
609608
"""
610609
Deploys an account contract with provided class_hash on Starknet and returns
611610
an AccountDeploymentResult that allows waiting for transaction acceptance.
612611
613612
Provided address must be first prefunded with enough tokens, otherwise the method will fail.
614613
615-
If using Client for either TESTNET or MAINNET, this method will verify if the address balance
616-
is high enough to cover deployment costs.
614+
If using Client for MAINNET, GOERLI, SEPOLIA or SEPOLIA_INTEGRATION, this method will verify
615+
if the address balance is high enough to cover deployment costs.
617616
618-
:param address: calculated and prefunded address of the new account.
619-
:param class_hash: class_hash of the account contract to be deployed.
620-
:param salt: salt used to calculate the address.
617+
:param address: Calculated and prefunded address of the new account.
618+
:param class_hash: Class hash of the account contract to be deployed.
619+
:param salt: Salt used to calculate the address.
621620
:param key_pair: KeyPair used to calculate address and sign deploy account transaction.
622-
:param client: a Client instance used for deployment.
623-
:param chain: id of the Starknet chain used.
624-
:param constructor_calldata: optional calldata to account contract constructor. If ``None`` is passed,
621+
:param client: Client instance used for deployment.
622+
:param chain: Id of the Starknet chain used.
623+
:param constructor_calldata: Optional calldata to account contract constructor. If ``None`` is passed,
625624
``[key_pair.public_key]`` will be used as calldata.
626625
:param nonce: Nonce of the transaction.
627-
:param max_fee: max fee to be paid for deployment, must be less or equal to the amount of tokens prefunded.
626+
:param max_fee: Max fee to be paid for deployment, must be less or equal to the amount of tokens prefunded.
628627
:param auto_estimate: Use automatic fee estimation, not recommend as it may lead to high costs.
629628
"""
630-
address = parse_address(address)
631629
calldata = (
632630
constructor_calldata
633631
if constructor_calldata is not None
634632
else [key_pair.public_key]
635633
)
636634

637-
if address != (
638-
computed := compute_address(
639-
salt=salt,
640-
class_hash=class_hash,
641-
constructor_calldata=calldata,
642-
deployer_address=0,
643-
)
644-
):
645-
raise ValueError(
646-
f"Provided address {hex(address)} is different than computed address {hex(computed)} "
647-
f"for the given class_hash and salt."
648-
)
649-
650-
account = Account(
635+
account = _prepare_account_to_deploy(
651636
address=address,
652-
client=client,
637+
class_hash=class_hash,
638+
salt=salt,
653639
key_pair=key_pair,
640+
client=client,
654641
chain=chain,
642+
calldata=calldata,
655643
)
656644

657645
deploy_account_tx = await account.sign_deploy_account_v1_transaction(
@@ -663,12 +651,7 @@ async def deploy_account(
663651
auto_estimate=auto_estimate,
664652
)
665653

666-
if chain in (
667-
StarknetChainId.SEPOLIA_TESTNET,
668-
StarknetChainId.SEPOLIA_INTEGRATION,
669-
StarknetChainId.GOERLI,
670-
StarknetChainId.MAINNET,
671-
):
654+
if chain in StarknetChainId:
672655
balance = await account.get_balance()
673656
if balance < deploy_account_tx.max_fee:
674657
raise ValueError(
@@ -681,6 +664,70 @@ async def deploy_account(
681664
hash=result.transaction_hash, account=account, _client=account.client
682665
)
683666

667+
@staticmethod
668+
async def deploy_account_v3(
669+
*,
670+
address: AddressRepresentation,
671+
class_hash: int,
672+
salt: int,
673+
key_pair: KeyPair,
674+
client: Client,
675+
chain: StarknetChainId,
676+
constructor_calldata: Optional[List[int]] = None,
677+
nonce: int = 0,
678+
l1_resource_bounds: Optional[ResourceBounds] = None,
679+
auto_estimate: bool = False,
680+
) -> AccountDeploymentResult:
681+
"""
682+
Deploys an account contract with provided class_hash on Starknet and returns
683+
an AccountDeploymentResult that allows waiting for transaction acceptance.
684+
685+
Provided address must be first prefunded with enough tokens, otherwise the method will fail.
686+
687+
:param address: Calculated and prefunded address of the new account.
688+
:param class_hash: Class hash of the account contract to be deployed.
689+
:param salt: Salt used to calculate the address.
690+
:param key_pair: KeyPair used to calculate address and sign deploy account transaction.
691+
:param client: Client instance used for deployment.
692+
:param chain: Id of the Starknet chain used.
693+
:param constructor_calldata: Optional calldata to account contract constructor. If ``None`` is passed,
694+
``[key_pair.public_key]`` will be used as calldata.
695+
:param nonce: Nonce of the transaction.
696+
:param l1_resource_bounds: Max amount and max price per unit of L1 gas (in Fri) used when executing
697+
this transaction.
698+
:param auto_estimate: Use automatic fee estimation, not recommend as it may lead to high costs.
699+
"""
700+
calldata = (
701+
constructor_calldata
702+
if constructor_calldata is not None
703+
else [key_pair.public_key]
704+
)
705+
706+
account = _prepare_account_to_deploy(
707+
address=address,
708+
class_hash=class_hash,
709+
salt=salt,
710+
key_pair=key_pair,
711+
client=client,
712+
chain=chain,
713+
calldata=calldata,
714+
)
715+
716+
deploy_account_tx = await account.sign_deploy_account_v3_transaction(
717+
class_hash=class_hash,
718+
contract_address_salt=salt,
719+
constructor_calldata=calldata,
720+
nonce=nonce,
721+
l1_resource_bounds=l1_resource_bounds,
722+
auto_estimate=auto_estimate,
723+
)
724+
725+
result = await client.deploy_account(deploy_account_tx)
726+
727+
return AccountDeploymentResult(
728+
hash=result.transaction_hash, account=account, _client=account.client
729+
)
730+
684731
def _default_token_address_for_chain(
685732
self, chain_id: Optional[StarknetChainId] = None
686733
) -> str:
@@ -697,6 +744,39 @@ def _default_token_address_for_chain(
697744
return FEE_CONTRACT_ADDRESS
698745

699746

747+
def _prepare_account_to_deploy(
748+
address: AddressRepresentation,
749+
class_hash: int,
750+
salt: int,
751+
key_pair: KeyPair,
752+
client: Client,
753+
chain: StarknetChainId,
754+
calldata: List[int],
755+
) -> Account:
756+
# pylint: disable=too-many-arguments
757+
address = parse_address(address)
758+
759+
if address != (
760+
computed := compute_address(
761+
salt=salt,
762+
class_hash=class_hash,
763+
constructor_calldata=calldata,
764+
deployer_address=0,
765+
)
766+
):
767+
raise ValueError(
768+
f"Provided address {hex(address)} is different than computed address {hex(computed)} "
769+
f"for the given class_hash and salt."
770+
)
771+
772+
return Account(
773+
address=address,
774+
client=client,
775+
key_pair=key_pair,
776+
chain=chain,
777+
)
778+
779+
700780
def _is_sierra_contract(data: Dict[str, Any]) -> bool:
701781
return "sierra_program" in data
702782

@@ -721,19 +801,19 @@ def _add_resource_bounds_to_transaction(
721801

722802
def _parse_calls(cairo_version: int, calls: Calls) -> List[int]:
723803
if cairo_version == 1:
724-
parsed_calls = _parse_calls_v2(ensure_iterable(calls))
725-
wrapped_calldata = _execute_payload_serializer_v2.serialize(
804+
parsed_calls = _parse_calls_cairo_v1(ensure_iterable(calls))
805+
wrapped_calldata = _execute_payload_serializer_v1.serialize(
726806
{"calls": parsed_calls}
727807
)
728808
else:
729809
call_descriptions, calldata = _merge_calls(ensure_iterable(calls))
730-
wrapped_calldata = _execute_payload_serializer.serialize(
810+
wrapped_calldata = _execute_payload_serializer_v0.serialize(
731811
{"call_array": call_descriptions, "calldata": calldata}
732812
)
733813
return wrapped_calldata
734814

735815

736-
def _parse_call(call: Call, entire_calldata: List) -> Tuple[Dict, List]:
816+
def _parse_call_cairo_v0(call: Call, entire_calldata: List) -> Tuple[Dict, List]:
737817
_data = {
738818
"to": call.to_addr,
739819
"selector": call.selector,
@@ -749,13 +829,13 @@ def _merge_calls(calls: Iterable[Call]) -> Tuple[List[Dict], List[int]]:
749829
call_descriptions = []
750830
entire_calldata = []
751831
for call in calls:
752-
data, entire_calldata = _parse_call(call, entire_calldata)
832+
data, entire_calldata = _parse_call_cairo_v0(call, entire_calldata)
753833
call_descriptions.append(data)
754834

755835
return call_descriptions, entire_calldata
756836

757837

758-
def _parse_calls_v2(calls: Iterable[Call]) -> List[Dict]:
838+
def _parse_calls_cairo_v1(calls: Iterable[Call]) -> List[Dict]:
759839
calls_parsed = []
760840
for call in calls:
761841
_data = {
@@ -769,30 +849,30 @@ def _parse_calls_v2(calls: Iterable[Call]) -> List[Dict]:
769849

770850

771851
_felt_serializer = FeltSerializer()
772-
_call_description = StructSerializer(
852+
_call_description_cairo_v0 = StructSerializer(
773853
OrderedDict(
774854
to=_felt_serializer,
775855
selector=_felt_serializer,
776856
data_offset=_felt_serializer,
777857
data_len=_felt_serializer,
778858
)
779859
)
780-
_call_description_v2 = StructSerializer(
860+
_call_description_cairo_v1 = StructSerializer(
781861
OrderedDict(
782862
to=_felt_serializer,
783863
selector=_felt_serializer,
784864
calldata=ArraySerializer(_felt_serializer),
785865
)
786866
)
787867

788-
_execute_payload_serializer = PayloadSerializer(
868+
_execute_payload_serializer_v0 = PayloadSerializer(
789869
OrderedDict(
790-
call_array=ArraySerializer(_call_description),
870+
call_array=ArraySerializer(_call_description_cairo_v0),
791871
calldata=ArraySerializer(_felt_serializer),
792872
)
793873
)
794-
_execute_payload_serializer_v2 = PayloadSerializer(
874+
_execute_payload_serializer_v1 = PayloadSerializer(
795875
OrderedDict(
796-
calls=ArraySerializer(_call_description_v2),
876+
calls=ArraySerializer(_call_description_cairo_v1),
797877
)
798878
)

starknet_py/net/account/base_account.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ async def sign_deploy_account_v3_transaction(
264264
"""
265265

266266
@abstractmethod
267-
async def execute(
267+
async def execute_v1(
268268
self,
269269
calls: Calls,
270270
*,

0 commit comments

Comments
 (0)