Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate v1 and v2 transactions #1542

15 changes: 8 additions & 7 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ env:
DEVNET_SHA: 7e7dbb5
LEDGER_APP_SHA: dd58c5c
LEDGER_APP_DEV_TOOLS_SHA: a037d42181f4bed9694246256e2c9e2a899e775c302a9c6482c81f87c28e1432
POETRY_VERSION: "1.8.5"

on:
push:
Expand All @@ -31,7 +32,7 @@ jobs:
- name: Install poetry
run: |
python -m pip install --upgrade pip
pip install poetry
pip install poetry==${{ env.POETRY_VERSION }}
poetry config installer.modern-installation false

- name: Set up Python 3.12
Expand Down Expand Up @@ -84,7 +85,7 @@ jobs:
- name: Install poetry
run: |
python -m pip install --upgrade pip
pip install poetry
pip install poetry==${{ env.POETRY_VERSION }}
poetry config installer.modern-installation false

- name: Set up Python ${{ matrix.python-version }}
Expand Down Expand Up @@ -165,7 +166,7 @@ jobs:
- name: Install poetry
run: |
python -m pip install --upgrade pip
pip install poetry
pip install poetry==${{ env.POETRY_VERSION }}
poetry config installer.modern-installation false

- name: Set up Python ${{ matrix.python-version }}
Expand Down Expand Up @@ -277,7 +278,7 @@ jobs:
- name: Install poetry
run: |
python -m pip install --upgrade pip
pip install poetry
pip install poetry==${{ env.POETRY_VERSION }}
poetry config installer.modern-installation false

- name: Set up Python 3.12
Expand Down Expand Up @@ -364,7 +365,7 @@ jobs:
- name: Install poetry
run: |
python -m pip install --upgrade pip
pip install poetry
pip install poetry==${{ env.POETRY_VERSION }}
poetry config installer.modern-installation false

- name: Set up Python ${{ matrix.python-version }}
Expand Down Expand Up @@ -426,7 +427,7 @@ jobs:
- name: Install poetry
run: |
python -m pip install --upgrade pip
pip install poetry
pip install poetry==${{ env.POETRY_VERSION }}
poetry config installer.modern-installation false

- name: Set up Python ${{ matrix.python-version }}
Expand Down Expand Up @@ -493,7 +494,7 @@ jobs:
- name: Install poetry
run: |
python -m pip install --upgrade pip
pip install poetry
pip install poetry==${{ env.POETRY_VERSION }}
poetry config installer.modern-installation false

- name: Set up Python ${{ matrix.python-version }}
Expand Down
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ It supports an account contract which proxies the calls to other contracts on St

Account can be created in two ways:
- By constructor (It is required to provide an `address` and either `key_pair` or `signer`).
- By static methods `Account.deploy_account_v1` or `Account.deploy_account_v3`
- By static method `Account.deploy_account_v3`

Additionally, you can use the [sncast](https://foundry-rs.github.io/starknet-foundry/starknet/index.html) tool to create an account,
which will automatically be saved to a file.
Expand Down Expand Up @@ -159,6 +159,8 @@ await account.client.wait_for_tx(transaction_response.transaction_hash)
[Contract](https://starknetpy.readthedocs.io/en/latest/api/contract.html#starknet_py.contract.Contract) makes interacting with contracts deployed on Starknet much easier:
```python
from starknet_py.contract import Contract
from starknet_py.net.client_models import ResourceBounds


contract_address = (
"0x01336fa7c870a7403aced14dda865b75f29113230ed84e3a661f7af70fe83e7b"
Expand All @@ -178,8 +180,13 @@ contract = Contract(

# All exposed functions are available at contract.functions.
# Here we invoke a function, creating a new transaction.
invocation = await contract.functions["put"].invoke_v1(key, 7, max_fee=int(1e16))

invocation = await contract.functions["put"].invoke_v3(
key,
7,
l1_resource_bounds=ResourceBounds(
max_amount=int(1e5), max_price_per_unit=int(1e13)
),
)
# Invocation returns InvokeResult object. It exposes a helper for waiting until transaction is accepted.
await invocation.wait_for_acceptance()

Expand Down
3 changes: 1 addition & 2 deletions docs/account_creation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,5 @@ Here is step by step example:

If you are experiencing transaction failures with ``FEE_TRANSFER_FAILURE``
make sure that the address you are trying to deploy is prefunded with enough
tokens, and verify that ``max_fee`` argument in :meth:`~starknet_py.net.account.account.Account.sign_deploy_account_v1`
or ``l1_resource_bounds`` argument in :meth:`~starknet_py.net.account.account.Account.sign_deploy_account_v3` is set
tokens, and verify that ``l1_resource_bounds`` argument in :meth:`~starknet_py.net.account.account.Account.sign_deploy_account_v3` is set
to a high enough value.
16 changes: 6 additions & 10 deletions docs/guide/account_and_client.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ Account and Client
Executing transactions
----------------------

To execute transactions on Starknet, use :meth:`~starknet_py.net.account.account.Account.execute_v1` or :meth:`~starknet_py.net.account.account.Account.execute_v3` methods from :ref:`Account` interface.
These methods will send :class:`~starknet_py.net.models.InvokeV1` and :class:`~starknet_py.net.models.InvokeV3` transactions respectively. To read about differences between transaction versions please visit `transaction types <https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/transactions>`_ from the Starknet docs.
To execute transactions on Starknet, use :meth:`~starknet_py.net.account.account.Account.execute_v3` method from :ref:`Account` interface, which will send :class:`~starknet_py.net.models.InvokeV3` transaction.

.. codesnippet:: ../../starknet_py/tests/e2e/docs/guide/test_executing_transactions.py
:language: python
Expand All @@ -15,25 +14,22 @@ Transaction Fee
---------------

All methods within the :ref:`Account` that involve on-chain modifications require either specifying a maximum transaction fee or using auto estimation.
In the case of V1 and V2 transactions, the transaction fee, denoted in Wei, is configured by the ``max_fee`` parameter.
For V3 transactions, however, the fee is expressed in Fri and is determined by the ``l1_resource_bounds`` parameter.
For V3 transaction, the fee is expressed in Fri and is determined by the ``l1_resource_bounds`` parameter.
To enable auto estimation, set the ``auto_estimate`` parameter to ``True``.

.. code-block:: python
resp = await account.execute_v1(calls=call, auto_estimate=True)
resp = await account.execute_v3(calls=call, auto_estimate=True)
.. warning::

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`` and ``1.5`` respectively.
The returned estimated fee (``max_amount`` and ``max_price_per_unit``) 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,
by changing ``ESTIMATED_FEE_MULTIPLIER`` for V1 and V2 transactions in :class:`~starknet_py.net.account.account.Account`.
The same applies to ``ESTIMATED_AMOUNT_MULTIPLIER`` and ``ESTIMATED_UNIT_PRICE_MULTIPLIER`` for V3 transactions.
by changing ``ESTIMATED_AMOUNT_MULTIPLIER`` and ``ESTIMATED_UNIT_PRICE_MULTIPLIER`` in :class:`~starknet_py.net.account.account.Account`.

The fee for a specific transaction or list of transactions can be also estimated using the :meth:`~starknet_py.net.account.account.Account.estimate_fee` of the :ref:`Account` class.

Expand Down Expand Up @@ -61,7 +57,7 @@ Multicall
---------

There is a possibility to execute an Invoke transaction containing multiple calls.
Simply pass a list of calls to :meth:`~starknet_py.net.account.account.Account.execute_v1` or :meth:`~starknet_py.net.account.account.Account.execute_v3` methods.
Simply pass a list of calls to :meth:`~starknet_py.net.account.account.Account.execute_v3` method.
Note that the nonce will be bumped only by 1.

.. codesnippet:: ../../starknet_py/tests/e2e/docs/guide/test_multicall.py
Expand Down
8 changes: 4 additions & 4 deletions docs/guide/deploying_contracts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Deploying contracts
Declaring contracts
-------------------

A declare transaction can be issued in version 2 or 3. Contracts written in Cairo 0 cannot be declared while those written in Cairo 1 or higher should be declared with versions 2 or 3.
To sign a declare transaction, you should utilize the :meth:`~starknet_py.net.account.account.Account.sign_declare_v2` or :meth:`~starknet_py.net.account.account.Account.sign_declare_v3` method, respectively.
Contracts written in Cairo 0 cannot be declared while those written in Cairo 1 or higher should be declared with transaction version 3.
To sign a declare transaction, you should utilize :meth:`~starknet_py.net.account.account.Account.sign_declare_v3` method.

Here's an example how to use it.

Expand All @@ -17,7 +17,7 @@ Here's an example how to use it.
Simple deploy
-------------

If you know the class hash of an already declared contract you want to deploy just use the :meth:`~starknet_py.contract.Contract.deploy_contract_v1` or :meth:`~starknet_py.contract.Contract.deploy_contract_v3`.
If you know the class hash of an already declared contract you want to deploy just use the :meth:`~starknet_py.contract.Contract.deploy_contract_v3`.
It will deploy the contract using funds from your account. Deployment is handled by UDC.

.. codesnippet:: ../../starknet_py/tests/e2e/docs/guide/test_simple_deploy.py
Expand Down Expand Up @@ -57,7 +57,7 @@ Cairo1 contracts
Declaring Cairo1 contracts
##########################

To declare a contract in Cairo version 1 or higher, Declare V2 or Declare V3 transaction has to be sent.
To declare a contract in Cairo version 1 or higher, Declare V3 transaction has to be sent.
You can see the structure of these transactions `here <https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/transactions/#declare-transaction>`_.

The main differences in the structure of the transaction from its previous version are:
Expand Down
40 changes: 21 additions & 19 deletions docs/guide/using_existing_contracts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,30 +39,34 @@ Fees

.. currentmodule:: starknet_py.contract

Starknet.py requires you to specify amount of Wei (for V1 transaction) or Fri (for V3 transaction) you
are willing to pay when executing either :meth:`~ContractFunction.invoke_v1` or :meth:`~ContractFunction.invoke_v3` transactions.
Starknet.py requires you to specify amount of Fri that you are willing to pay when executing :meth:`~ContractFunction.invoke_v3`.
Alternatively, you can estimate fee automatically, as described in the :ref:`automatic-fee-estimation` section below.

.. code-block:: python
await contract.functions["put"].invoke_v1(k, v, max_fee=5000)
await contract.functions["put"].invoke_v3(k, v, l1_resource_bounds=ResourceBounds(
max_amount=int(1e5), max_price_per_unit=int(1e13)
))
The ``max_fee`` argument can be also defined in :meth:`~ContractFunction.prepare_invoke_v1`. Subsequently, the :meth:`~PreparedFunctionInvokeV1.invoke` method on a prepared call can be used either with ``max_fee`` omitted or with its value overridden.
The same behavior applies to :meth:`~ContractFunction.prepare_invoke_v3` and ``l1_resource_bounds``.
The ``l1_resource_bounds`` argument can be also defined in :meth:`~ContractFunction.prepare_invoke_v3`. Subsequently, the :meth:`~PreparedFunctionInvokeV3.invoke` method on a prepared call can be used either with ``l1_resource_bounds`` omitted or with its value overridden.

.. code-block:: python
prepared_call = contract.function["put"].prepare_invoke_v1(k, v, max_fee=5000)
prepared_call = contract.function["put"].prepare_invoke_v3(k, v, l1_resource_bounds=ResourceBounds(
max_amount=int(1e5), max_price_per_unit=int(1e13)
))
await prepared_call.invoke()
# or max_fee can be overridden
await prepared_call.invoke(max_fee=10000)
# or l1_resource_bounds can be overridden
await prepared_call.invoke(l1_resource_bounds=ResourceBounds(
max_amount=int(1e5), max_price_per_unit=int(1e13)
))
.. warning::

For V1 transactions if ``max_fee`` is not specified at any step it will default to ``None``,
and will raise an exception when invoking a transaction, unless `auto_estimate` is specified and is set to `True`. The same applies to ``l1_resource_bounds`` and V3 transactions.
If ``l1_resource_bounds`` is not specified at any step it will default to ``None``,
and will raise an exception when invoking a transaction, unless `auto_estimate` is specified and is set to `True`.

Please note you will need to have enough Wei (for V1 transaction) or Fri (for V3 transaction) in your Starknet account otherwise
Please note you will need to have enough Fri in your Starknet account otherwise
transaction will be rejected.

Fee estimation
Expand All @@ -73,29 +77,27 @@ using :meth:`PreparedFunctionInvoke.estimate_fee() <starknet_py.contract.Prepare

.. code-block:: python
await contract.functions["put"].prepare_invoke_v1(k, v).estimate_fee()
await contract.functions["put"].prepare_invoke_v3(k, v).estimate_fee()
.. _automatic-fee-estimation:

Automatic fee estimation
------------------------

For testing purposes it is possible to enable automatic fee estimation when making a transaction. Starknet.py will then call :meth:`~starknet_py.net.full_node_client.FullNodeClient.estimate_fee`
internally and use the returned value, multiplied by ``1.5`` to mitigate fluctuations in price, as a ``max_fee`` for V1 transactions. For V3 transactions,
``max_amount`` will be multiplied by ``1.1``, and ``max_price_per_unit`` by ``1.5``.
internally and use the returned value. ``max_amount`` and ``max_price_per_unit`` will be multiplied by ``1.5``.

.. code-block:: python
await contract.functions["put"].invoke_v1(k, v, auto_estimate=True)
await contract.functions["put"].invoke_v3(k, v, auto_estimate=True)
.. warning::

It is strongly discouraged to use automatic fee estimation in production code as it may lead to unexpectedly high fee.

.. note::
For V1 transactions it is possible to configure the value by which the estimated fee is multiplied,
by changing ``ESTIMATED_FEE_MULTIPLIER`` in :class:`~starknet_py.net.account.account.Account`. The same applies to
``ESTIMATED_AMOUNT_MULTIPLIER`` and ``ESTIMATED_UNIT_PRICE_MULTIPLIER`` for V3 transactions.
It is possible to configure the value by which the estimated fee is multiplied,
by changing ``ESTIMATED_AMOUNT_MULTIPLIER`` and ``ESTIMATED_UNIT_PRICE_MULTIPLIER``.

Account and Client interoperability
-----------------------------------
Expand All @@ -104,7 +106,7 @@ Account and Client interoperability

:ref:`Contract` methods have been designed to be compatible with :ref:`Account` and :ref:`Client`.

:ref:`PreparedFunctionInvokeV1` and :ref:`PreparedFunctionInvokeV3` returned by :meth:`ContractFunction.prepare_invoke_v1` and :meth:`ContractFunction.prepare_invoke_v3` respectively can be used in Account methods to create Invoke transactions.
:ref:`PreparedFunctionInvokeV3` returned by :meth:`ContractFunction.prepare_invoke_v3` can be used in Account methods to create invoke transaction.

.. codesnippet:: ../../starknet_py/tests/e2e/docs/guide/test_contract_account_compatibility.py
:language: python
Expand Down
2 changes: 1 addition & 1 deletion docs/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ It supports an account contract which proxies the calls to other contracts on St
Account can be created in two ways:

* By constructor (It is required to provide an ``address`` and either ``key_pair`` or ``signer``).
* By static methods ``Account.deploy_account_v1`` or ``Account.deploy_account_v3``
* By static method ``Account.deploy_account_v3``

There are some examples how to do it:

Expand Down
46 changes: 10 additions & 36 deletions starknet_py/tests/e2e/contract_interaction/deploy_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,12 @@

from starknet_py.common import create_sierra_compiled_contract
from starknet_py.contract import Contract, DeclareResult
from starknet_py.net.client_models import InvokeTransactionV1
from starknet_py.net.models import DeclareV2
from starknet_py.tests.e2e.fixtures.constants import MAX_FEE, MAX_RESOURCE_BOUNDS_L1
from starknet_py.net.client_models import InvokeTransactionV3
from starknet_py.net.models import DeclareV3
from starknet_py.tests.e2e.fixtures.constants import MAX_RESOURCE_BOUNDS_L1
from starknet_py.tests.e2e.fixtures.misc import load_contract


@pytest.mark.asyncio
async def test_declare_deploy_v1(
account,
minimal_contract_class_hash: int,
):
compiled_contract = load_contract("MinimalContract")["sierra"]

declare_result = DeclareResult(
_account=account,
_client=account.client,
_cairo_version=1,
class_hash=minimal_contract_class_hash,
compiled_contract=compiled_contract,
hash=0,
declare_transaction=Mock(spec=DeclareV2),
)

deploy_result = await declare_result.deploy_v1(max_fee=MAX_FEE)
await deploy_result.wait_for_acceptance()

assert isinstance(deploy_result.hash, int)
assert deploy_result.hash != 0
assert deploy_result.deployed_contract.address != 0


@pytest.mark.asyncio
async def test_declare_deploy_v3(
account,
Expand All @@ -51,7 +26,7 @@ async def test_declare_deploy_v3(
class_hash=minimal_contract_class_hash,
compiled_contract=compiled_contract,
hash=0,
declare_transaction=Mock(spec=DeclareV2),
declare_transaction=Mock(spec=DeclareV3),
)

deploy_result = await declare_result.deploy_v3(
Expand All @@ -75,7 +50,7 @@ async def test_throws_on_wrong_abi(account, minimal_contract_class_hash: int):
class_hash=minimal_contract_class_hash,
compiled_contract=compiled_contract,
hash=0,
declare_transaction=Mock(spec=DeclareV2),
declare_transaction=Mock(spec=DeclareV3),
)

compiled_contract = compiled_contract.replace('"abi":[', '"api": ')
Expand All @@ -90,22 +65,21 @@ async def test_throws_on_wrong_abi(account, minimal_contract_class_hash: int):
"Make sure provided compiled_contract is correct."
),
):
await declare_result.deploy_v1(max_fee=MAX_FEE)
await declare_result.deploy_v3(l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1)


@pytest.mark.asyncio
async def test_deploy_contract_v1(account, hello_starknet_class_hash: int):
async def test_deploy_contract_v3(account, hello_starknet_class_hash: int):
compiled_contract = load_contract("HelloStarknet")["sierra"]
abi = create_sierra_compiled_contract(
compiled_contract=compiled_contract
).parsed_abi

deploy_result = await Contract.deploy_contract_v1(
deploy_result = await Contract.deploy_contract_v3(
class_hash=hello_starknet_class_hash,
account=account,
abi=abi,
max_fee=MAX_FEE,
cairo_version=1,
l1_resource_bounds=MAX_RESOURCE_BOUNDS_L1,
)
await deploy_result.wait_for_acceptance()

Expand All @@ -115,7 +89,7 @@ async def test_deploy_contract_v1(account, hello_starknet_class_hash: int):
assert len(contract.functions) != 0

transaction = await account.client.get_transaction(tx_hash=deploy_result.hash)
assert isinstance(transaction, InvokeTransactionV1)
assert isinstance(transaction, InvokeTransactionV3)

class_hash = await account.client.get_class_hash_at(
contract_address=contract.address
Expand Down
Loading
Loading