software-mansion / starknet.py

✨ 🐍 Python SDK for Starknet.
https://starknetpy.rtfd.io/
MIT License
259 stars 74 forks source link

invoke_sync method throws an error #208

Closed iraklio closed 2 years ago

iraklio commented 2 years ago

Hello, I am trying to run below snippet, it is throwing an error.

from starknet_py.contract import Contract from starknet_py.net.client import Client client = Client("testnet") contract_address = "0x01336fa7c870a7403aced14dda865b75f29113230ed84e3a661f7af70fe83e7b" key = 12345678 contract = Contract.from_address_sync(contract_address, client) invocation = contract.functions["set_value"].invoke_sync(key, 7, max_fee=500) invocation.wait_for_acceptance_sync()

_Got BadRequest while trying to access https://alpha4.starknet.io/gateway/add_transaction. Status code: 500; text: {"code": "StarknetErrorCode.UNSUPPORTED_SELECTOR_FOR_FEE", "message": "All transactions should go through the execute entrypoint."}. Traceback (most recent call last): File "/home/iodishar/.local/lib/python3.8/site-packages/services/external_api/client.py", line 121, in _send_request raise BadRequest(status_code=response.status, text=text) services.external_api.client.BadRequest: HTTP error ocurred. Status: 500. Text: {"code": "StarknetErrorCode.UNSUPPORTED_SELECTOR_FOR_FEE", "message": "All transactions should go through the execute entrypoint."} Traceback (most recent call last): File "app/test.py", line 10, in invocation = contract.functions["set_value"].invoke_sync(key, 7, max_fee=500) File "/home/iodishar/.local/lib/python3.8/site-packages/starknet_py/utils/sync/sync.py", line 15, in impl return sync_fun(*args, *kwargs) File "/home/iodishar/.local/lib/python3.8/site-packages/asgiref/sync.py", line 218, in call return call_result.result() File "/usr/lib/python3.8/concurrent/futures/_base.py", line 437, in result return self.get_result() File "/usr/lib/python3.8/concurrent/futures/_base.py", line 389, in get_result raise self._exception File "/home/iodishar/.local/lib/python3.8/site-packages/asgiref/sync.py", line 284, in main_wrap result = await self.awaitable(args, **kwargs) File "/home/iodishar/.local/lib/python3.8/site-packages/starknet_py/contract.py", line 354, in invoke return await prepared_call.invoke(max_fee=max_fee, auto_estimate=auto_estimate) File "/home/iodishar/.local/lib/python3.8/site-packages/starknet_py/contract.py", line 241, in invoke response = await self._client.add_transaction(tx=tx) File "/home/iodishar/.local/lib/python3.8/site-packages/starknet_py/net/client.py", line 248, in add_transaction return await self._gateway.add_transaction(tx, token) File "/home/iodishar/.local/lib/python3.8/site-packages/starkware/starknet/services/api/gateway/gateway_client.py", line 16, in add_transaction raw_response = await self._send_request( File "/home/iodishar/.local/lib/python3.8/site-packages/services/external_api/client.py", line 121, in _send_request raise BadRequest(status_code=response.status, text=text) services.external_api.client.BadRequest: HTTP error ocurred. Status: 500. Text: {"code": "StarknetErrorCode.UNSUPPORTED_SELECTOR_FORFEE", "message": "All transactions should go through the execute entrypoint."}

war-in commented 2 years ago

Hello, to send transactions with max_fee > 0 you should use AccountClient instead of Client.

iraklio commented 2 years ago

Thanks for getting back. I have created a testnet account in ArgentX. I would like to use that account to interact with StarkNet, through starknetpy. This is what I have tried:

from starknet_py.net import AccountClient

private_key = 3481907968109126366631341857992198869776879917929289470748436139290217987122 acc_client = AccountClient.create_account_sync(net="testnet", private_key=private_key)

print(acc_client.get_balance_sync()) # this prints 0. Instead of 0.04ETH, so something is off...

contract_address = "0x01336fa7c870a7403aced14dda865b75f29113230ed84e3a661f7af70fe83e7b" contract = Contract.from_address_sync(contract_address, acc_client) invocation = contract.functions["set_value"].invoke_sync(key, 7, max_fee=500) invocation.wait_for_acceptance_sync()

Is this the right way to do it? It would be supper helpful if you can provide short snippet on how to interact with StarkNet, using existing ArgentX accounts. View calls work fine, but I am unable to call invoke functions... Thanks!

war-in commented 2 years ago

We should definitely update the docs. Here is how to create an AccountClient if it is already deployed:

AccountClient( address=address, key_pair=KeyPair.from_private_key(private_key), net=net, chain=chain)

You can create key_pair this way or if you have a private and public key: key_pair = KeyPair(private_key, public_key)

In your case net is "testnet" and chain is StarknetChainId.TESTNET

The rest of your code seems fine, so it should work.

iraklio commented 2 years ago

Thank you. I was able to initialize the existing account.

from starknet_py.contract import Contract from starknet_py.net import AccountClient from starknet_py.net.models import StarknetChainId from starknet_py.net.signer.stark_curve_signer import KeyPair

private_key = 0x7B2B0A883AE59D5DFB31B7256F3064961BE7C3C54179E26F30AFE4964F8BC32 account_address = 0x06C55071C86BC33C0C8D95A03190941641E664C43C228E0B0389F6566BDF0965 key_pair = KeyPair.from_private_key(private_key)

acc_client = AccountClient( address=account_address, net="testnet", chain=StarknetChainId.TESTNET, key_pair=key_pair, ) print(acc_client.get_balance_sync()) #this now prints 0.04ETH as expected!

But I still have a problem with the second part, when I try to call invoke_sync. set_value method exists on the contract and I am able to call it directly from voyager.

contract_address = 0x01336FA7C870A7403ACED14DDA865B75F29113230ED84E3A661F7AF70FE83E7B key = 1234 contract = Contract.from_address_sync(contract_address, acc_client) invocation = contract.functions["set_value"].invoke_sync(key, 7, max_fee=500) invocation.wait_for_acceptance_sync()

Here is the error. Is it possible that ArgentX does not implement OpenZeppelin's Account contract interface? It seems that there is no execute method on ArgentX client account I am using. Thanks again for your help.

File "app/test.py", line 27, in invocation = contract.functions["set_value"].invoke_sync(key, 7, max_fee=500) File "/home/.local/lib/python3.8/site-packages/starknet_py/utils/sync/sync.py", line 15, in impl return sync_fun(*args, *kwargs) File "/home/.local/lib/python3.8/site-packages/asgiref/sync.py", line 218, in call return call_result.result() File "/usr/lib/python3.8/concurrent/futures/_base.py", line 437, in result return self.get_result() File "/usr/lib/python3.8/concurrent/futures/_base.py", line 389, in get_result raise self._exception File "/home/.local/lib/python3.8/site-packages/asgiref/sync.py", line 284, in main_wrap result = await self.awaitable(args, **kwargs) File "/home/.local/lib/python3.8/site-packages/starknet_py/contract.py", line 354, in invoke return await prepared_call.invoke(max_fee=max_fee, auto_estimate=auto_estimate) File "/home/.local/lib/python3.8/site-packages/starknet_py/contract.py", line 241, in invoke response = await self._client.add_transaction(tx=tx) File "/home/.local/lib/python3.8/site-packages/starknet_py/net/account/account_client.py", line 159, in add_transaction return await super().add_transaction(await self._sign_transaction(tx)) File "/home/.local/lib/python3.8/site-packages/starknet_py/net/account/account_client.py", line 135, in _sign_transaction execute_tx = await self._prepare_execute_transaction(tx) File "/home/.local/lib/python3.8/site-packages/starknet_py/net/account/account_client.py", line 117, in _prepare_execute_transaction [execute_abi] = [a for a in abi if a["name"] == "execute"] ValueError: not enough values to unpack (expected 1, got 0)

iraklio commented 2 years ago

so looks like ArgentX use proxy contracts that point to actual OpenZeppelin contract implementation. Does Starknet_py support this type of setup for ClientAccount?

image

war-in commented 2 years ago

Thanks for the information. We checked it and now it is working properly. If you want to use it you can wait until the next release, or take it from our development branch.

iraklio commented 2 years ago

ok thanks! I will wait for the release. I found a work around meanwhile.