Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
0a898fe
init commit of async contract
dbfreem Mar 4, 2022
04bf711
more linting, still more to go
dbfreem Mar 4, 2022
e4dface
more linting. I seem to have broken some of the test on this one.
dbfreem Mar 4, 2022
acdae38
fixed broken test
dbfreem Mar 6, 2022
3c63696
This is most of the linting changes so far
dbfreem Mar 7, 2022
7118d24
async test
dbfreem Mar 7, 2022
e15971e
lint rearrange imports
dbfreem Mar 7, 2022
3682aa3
ContractEvents/ContractEvent Async
dbfreem Mar 7, 2022
b74662e
couple more fixes
dbfreem Mar 7, 2022
2944ee9
more work on contract
dbfreem Mar 8, 2022
6473a54
add non-ens normalize_address func (#2384)
Mar 8, 2022
0064b2a
Merge branch 'asyncify-contract' of https://github.com/ethereum/web3.…
dbfreem Mar 9, 2022
d568a5e
continued work on contract and fixed linting
dbfreem Mar 9, 2022
31c1e34
fixes
dbfreem Mar 9, 2022
3c2e26b
linting
dbfreem Mar 9, 2022
722c711
fix test import in the wrong place
dbfreem Mar 9, 2022
79f99dd
fixing combomethod
dbfreem Mar 9, 2022
c7bbd24
init commit of async contract (#2377)
dbfreem Mar 10, 2022
ba4ef33
Merge branch 'asyncify-contract' of https://github.com/ethereum/web3.…
dbfreem Mar 10, 2022
a2170e6
First test added
dbfreem Mar 10, 2022
1c765e8
ContractConstructor
dbfreem Mar 10, 2022
6e2ee8a
linting fixes
dbfreem Mar 11, 2022
ad97b6e
eth.contract and linting
dbfreem Mar 11, 2022
0d723dd
async_parse_block_identifier_int
dbfreem Mar 11, 2022
1bfda9f
Feature/asyncify contract (#2387)
dbfreem Mar 11, 2022
a0dad2d
pull master into asyncify-contract (#2389)
Mar 14, 2022
f1639b8
Merge branch 'asyncify-contract' of https://github.com/ethereum/web3.…
dbfreem Mar 15, 2022
1dc9a62
added two more async functions
dbfreem Mar 15, 2022
e30aa4e
Feature/asyncify contract (#2392)
dbfreem Mar 15, 2022
fa7d429
fill_transaction_defaults async for later use in build_transaction_fo…
dbfreem Mar 18, 2022
fdc6d50
build_transaction in ContractFunction
dbfreem Mar 19, 2022
dafa820
merge
dbfreem Mar 20, 2022
51248eb
estimateGas async in Contract and docs
dbfreem Mar 22, 2022
814d16b
lint
dbfreem Mar 22, 2022
268fe52
docs
dbfreem Mar 22, 2022
9ed1b7a
Feature/asyncify contract (#2394)
dbfreem Mar 23, 2022
e6b352a
setting default contract factory in AsyncEth to AsyncContract
dbfreem Mar 24, 2022
e1c4576
Merge branch 'asyncify-contract' of https://github.com/ethereum/web3.…
dbfreem Mar 24, 2022
fb238c9
Feature/asyncify contract (#2404)
dbfreem Mar 24, 2022
d1675a1
defaultContractFacotry
dbfreem Mar 25, 2022
74c5e47
Merge branch 'asyncify-contract' of https://github.com/ethereum/web3.…
dbfreem Mar 25, 2022
d34b039
defaultContractFactory
dbfreem Mar 25, 2022
17bbcd0
renaming deprecated methods
dbfreem Mar 25, 2022
067a147
add non-ens normalize_address func (#2384)
Mar 8, 2022
754bcbe
init commit of async contract (#2377)
dbfreem Mar 10, 2022
253f114
Feature/asyncify contract (#2387)
dbfreem Mar 11, 2022
e117b6b
Feature/asyncify contract (#2392)
dbfreem Mar 15, 2022
17cac58
Feature/asyncify contract (#2394)
dbfreem Mar 23, 2022
bfd4f60
Feature/asyncify contract (#2404)
dbfreem Mar 24, 2022
bbac866
Feature/asyncify contract (#2405)
dbfreem Mar 25, 2022
04674e5
Merge branch 'asyncify-contract' of https://github.com/ethereum/web3.…
dbfreem Apr 22, 2022
d4b96bf
removed buildTransaction and estimateGas
dbfreem Apr 22, 2022
4b52eac
docs update
dbfreem Apr 23, 2022
54e7bb3
Feature/asyncify contract (#2439)
dbfreem Apr 23, 2022
655f0dc
add non-ens normalize_address func (#2384)
Mar 8, 2022
543b9dd
init commit of async contract (#2377)
dbfreem Mar 10, 2022
3101010
Feature/asyncify contract (#2387)
dbfreem Mar 11, 2022
009723e
Feature/asyncify contract (#2392)
dbfreem Mar 15, 2022
bdf06c4
Feature/asyncify contract (#2394)
dbfreem Mar 23, 2022
fef9e43
Feature/asyncify contract (#2404)
dbfreem Mar 24, 2022
5887604
Feature/asyncify contract (#2405)
dbfreem Mar 25, 2022
a5b8a04
Feature/asyncify contract (#2439)
dbfreem Apr 23, 2022
ed5289d
Merge branch 'asyncify-contract' of https://github.com/pacrob/web3.py…
Apr 23, 2022
12dc8b4
[WIP] Test asyncify contract (#2422)
Apr 25, 2022
5b0d99a
add missing awaits
Apr 25, 2022
631df02
Merge branch 'asyncify-contract' of https://github.com/ethereum/web3.…
dbfreem May 4, 2022
e13147b
fixed bug with async_call_contract_function
dbfreem May 4, 2022
420897e
lint
dbfreem May 4, 2022
7ee1037
removed async_fill_default from ethtester middleware
dbfreem May 7, 2022
481c6e6
added comment to eth_tester.main
dbfreem May 7, 2022
c2355ab
removed unused comment
dbfreem May 10, 2022
6bf67d5
Feature/asyncify contract (#2458)
dbfreem May 10, 2022
917404d
Merge branch 'ethereum:asyncify-contract' into asyncify-contract
May 10, 2022
245aced
Merge branch 'asyncify-contract' of https://github.com/ethereum/web3.…
dbfreem May 11, 2022
bf877df
change to find_functions_by_identifier
dbfreem May 11, 2022
f51aafd
moved get_fallback_function and get_receive_function
dbfreem May 11, 2022
912dbff
asyncify contract
May 10, 2022
868ae04
rearranged BaseContractFunction.factory
dbfreem May 12, 2022
f8638a0
fixed the type in the cast of get_recieve_function and get_fallback_f…
dbfreem May 12, 2022
95280b2
added comment
dbfreem May 12, 2022
10d0267
asyncify contract
May 10, 2022
993dc7a
asyncify contract
May 12, 2022
8b57026
Merge branch 'feature/asyncify_contract' of https://github.com/dbfree…
May 12, 2022
c97aaad
Merge branch 'dbfreem-feature/asyncify_contract' into asyncify-contract
May 12, 2022
aac8a81
add newsfragment
May 18, 2022
a8c1a62
Add missing await in async build_transaction, add chain_id to eth_tes…
kclowes May 18, 2022
a87838c
Merge branch 'asyncify-contract' of github.com:ethereum/web3.py into …
kclowes May 18, 2022
3c61fdb
Fix tests
kclowes May 18, 2022
94e6622
Remove un-needed chain_id
kclowes May 18, 2022
0081748
Merge branch 'master' into asyncify-contract
May 18, 2022
dae293a
fix conflicts
May 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
import pytest
import time
import warnings
Expand All @@ -9,6 +10,7 @@
Web3,
)
from web3.providers.eth_tester import (
AsyncEthereumTesterProvider,
EthereumTesterProvider,
)

Expand Down Expand Up @@ -44,6 +46,10 @@ def is_testrpc_provider(provider):
return isinstance(provider, EthereumTesterProvider)


def is_async_testrpc_provider(provider):
return isinstance(provider, AsyncEthereumTesterProvider)


@pytest.fixture()
def skip_if_testrpc():

Expand All @@ -53,6 +59,15 @@ def _skip_if_testrpc(w3):
return _skip_if_testrpc


@pytest.fixture()
def async_skip_if_testrpc():

def _skip_if_testrpc(async_w3):
if is_async_testrpc_provider(async_w3.provider):
pytest.skip()
return _skip_if_testrpc


@pytest.fixture()
def wait_for_miner_start():
def _wait_for_miner_start(w3, timeout=60):
Expand Down
32 changes: 16 additions & 16 deletions docs/contracts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ Each Contract Factory exposes the following methods.
>>> txn_receipt['contractAddress']
'0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318'

.. py:classmethod:: Contract.constructor(*args, **kwargs).estimateGas(transaction=None, block_identifier=None)
.. py:classmethod:: Contract.constructor(*args, **kwargs).estimate_gas(transaction=None, block_identifier=None)
:noindex:

Estimate gas for constructing and deploying the contract.
Expand All @@ -264,12 +264,12 @@ Each Contract Factory exposes the following methods.

.. code-block:: python

>>> token_contract.constructor(web3.eth.coinbase, 12345).estimateGas()
>>> token_contract.constructor(web3.eth.coinbase, 12345).estimate_gas()
12563

.. py:classmethod:: Contract.constructor(*args, **kwargs).buildTransaction(transaction=None)
.. py:classmethod:: Contract.constructor(*args, **kwargs).build_transaction(transaction=None)
:noindex:

Construct the contract deploy transaction bytecode data.

If the contract takes constructor parameters they should be provided as
Expand All @@ -286,7 +286,7 @@ Each Contract Factory exposes the following methods.
'gasPrice': w3.eth.gas_price,
'chainId': None
}
>>> contract_data = token_contract.constructor(web3.eth.coinbase, 12345).buildTransaction(transaction)
>>> contract_data = token_contract.constructor(web3.eth.coinbase, 12345).build_transaction(transaction)
>>> web3.eth.send_transaction(contract_data)

.. _contract_createFilter:
Expand Down Expand Up @@ -833,7 +833,7 @@ Methods
a "missing trie node" error, because Ethereum node may have purged the past state from its database.
`More information about archival nodes here <https://ethereum.stackexchange.com/a/84200/620>`_.

.. py:method:: ContractFunction.estimateGas(transaction, block_identifier=None)
.. py:method:: ContractFunction.estimate_gas(transaction, block_identifier=None)

Call a contract function, executing the transaction locally using the
``eth_call`` API. This will not create a new public transaction.
Expand All @@ -842,7 +842,7 @@ Methods

.. code-block:: python

myContract.functions.myMethod(*args, **kwargs).estimateGas(transaction)
myContract.functions.myMethod(*args, **kwargs).estimate_gas(transaction)

This method behaves the same as the :py:meth:`ContractFunction.transact` method,
with transaction details being passed into the end portion of the
Expand All @@ -853,23 +853,23 @@ Methods

.. code-block:: python

>>> my_contract.functions.multiply7(3).estimateGas()
>>> my_contract.functions.multiply7(3).estimate_gas()
42650

.. note::
The parameter ``block_identifier`` is not enabled in geth nodes,
hence passing a value of ``block_identifier`` when connected to a geth
nodes would result in an error like: ``ValueError: {'code': -32602, 'message': 'too many arguments, want at most 1'}``

.. py:method:: ContractFunction.buildTransaction(transaction)
.. py:method:: ContractFunction.build_transaction(transaction)

Builds a transaction dictionary based on the contract function call specified.

Refer to the following invocation:

.. code-block:: python

myContract.functions.myMethod(*args, **kwargs).buildTransaction(transaction)
myContract.functions.myMethod(*args, **kwargs).build_transaction(transaction)

This method behaves the same as the :py:meth:`Contract.transact` method,
with transaction details being passed into the end portion of the
Expand All @@ -881,15 +881,15 @@ Methods

.. code-block:: python

>>> math_contract.functions.increment(5).buildTransaction({'nonce': 10})
>>> math_contract.functions.increment(5).build_transaction({'nonce': 10})

You may use :meth:`~web3.eth.Eth.getTransactionCount` to get the current nonce
for an account. Therefore a shortcut for producing a transaction dictionary with
nonce included looks like:

.. code-block:: python

>>> math_contract.functions.increment(5).buildTransaction({'nonce': web3.eth.get_transaction_count('0xF5...')})
>>> math_contract.functions.increment(5).build_transaction({'nonce': web3.eth.get_transaction_count('0xF5...')})

Returns a transaction dictionary. This transaction dictionary can then be sent using
:meth:`~web3.eth.Eth.send_transaction`.
Expand All @@ -899,7 +899,7 @@ Methods

.. code-block:: python

>>> math_contract.functions.increment(5).buildTransaction({'maxFeePerGas': 2000000000, 'maxPriorityFeePerGas': 1000000000})
>>> math_contract.functions.increment(5).build_transaction({'maxFeePerGas': 2000000000, 'maxPriorityFeePerGas': 1000000000})
{
'to': '0x6Bc272FCFcf89C14cebFC57B8f1543F5137F97dE',
'data': '0x7cf5dab00000000000000000000000000000000000000000000000000000000000000005',
Expand All @@ -923,15 +923,15 @@ Fallback Function
Call fallback function, executing the transaction locally using the
``eth_call`` API. This will not create a new public transaction.

.. py:method:: Contract.fallback.estimateGas(transaction)
.. py:method:: Contract.fallback.estimate_gas(transaction)

Call fallback function and return the gas estimation.

.. py:method:: Contract.fallback.transact(transaction)

Execute fallback function by sending a new public transaction.

.. py:method:: Contract.fallback.buildTransaction(transaction)
.. py:method:: Contract.fallback.build_transaction(transaction)

Builds a transaction dictionary based on the contract fallback function call.

Expand Down
4 changes: 2 additions & 2 deletions docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ The following example demonstrates a few things:

store_var_contract = w3.eth.contract(address=address, abi=contract_interface["abi"])

gas_estimate = store_var_contract.functions.setVar(255).estimateGas()
gas_estimate = store_var_contract.functions.setVar(255).estimate_gas()
print(f'Gas estimate to transact with setVar: {gas_estimate}')

if gas_estimate < 100000:
Expand Down Expand Up @@ -674,7 +674,7 @@ Just remember that you have to sign all transactions locally, as infura does not

.. code-block:: python

transaction = contract.functions.function_Name(params).buildTransaction()
transaction = contract.functions.function_Name(params).build_transaction()
transaction.update({ 'gas' : appropriate_gas_amount })
transaction.update({ 'nonce' : w3.eth.get_transaction_count('Your_Wallet_Address') })
signed_tx = w3.eth.account.sign_transaction(transaction, private_key)
Expand Down
6 changes: 6 additions & 0 deletions docs/providers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,12 @@ Geth
- :meth:`web3.geth.txpool.content() <web3.geth.txpool.TxPool.content()>`
- :meth:`web3.geth.txpool.status() <web3.geth.txpool.TxPool.status()>`

Contract
^^^^^^^^
Contract is fully implemented for the Async provider. The only documented exception to this at
the moment is where :class:`ENS` is needed for address lookup. All addresses that are passed to Async
contract should not be :class:`ENS` addresses.

Supported Middleware
^^^^^^^^^^^^^^^^^^^^
- :meth:`Gas Price Strategy <web3.middleware.gas_price_strategy_middleware>`
Expand Down
2 changes: 1 addition & 1 deletion docs/web3.eth.account.rst
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ To sign a transaction locally that will invoke a smart contract:
>>> unicorn_txn = unicorns.functions.transfer(
... '0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359',
... 1,
... ).buildTransaction({
... ).build_transaction({
... 'chainId': 1,
... 'gas': 70000,
... 'maxFeePerGas': w3.toWei('2', 'gwei'),
Expand Down
24 changes: 15 additions & 9 deletions ens/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
if TYPE_CHECKING:
from web3 import Web3 # noqa: F401
from web3.contract import ( # noqa: F401
AsyncContract,
Contract,
)
from web3.providers import ( # noqa: F401
Expand Down Expand Up @@ -232,7 +233,7 @@ def setup_address(
if address is None:
address = EMPTY_ADDR_HEX
transact['from'] = owner
resolver: 'Contract' = self._set_resolver(name, transact=transact)
resolver: Union['Contract', 'AsyncContract'] = self._set_resolver(name, transact=transact)
return resolver.functions.setAddr(raw_name_to_hash(name), address).transact(transact)

def setup_name(
Expand Down Expand Up @@ -285,7 +286,7 @@ def setup_name(
self.setup_address(name, address, transact=transact)
return self._setup_reverse(name, address, transact=transact)

def resolver(self, name: str) -> Optional['Contract']:
def resolver(self, name: str) -> Optional[Union['Contract', 'AsyncContract']]:
"""
Get the resolver for an ENS name.

Expand All @@ -294,7 +295,8 @@ def resolver(self, name: str) -> Optional['Contract']:
normal_name = normalize_name(name)
return self._get_resolver(normal_name)[0]

def reverser(self, target_address: ChecksumAddress) -> Optional['Contract']:
def reverser(self,
target_address: ChecksumAddress) -> Optional[Union['Contract', 'AsyncContract']]:
reversed_domain = address_to_reverse_domain(target_address)
return self.resolver(reversed_domain)

Expand Down Expand Up @@ -511,7 +513,7 @@ def _set_resolver(
name: str,
resolver_addr: Optional[ChecksumAddress] = None,
transact: Optional["TxParams"] = None
) -> 'Contract':
) -> Union['Contract', 'AsyncContract']:
if not transact:
transact = {}
transact = deepcopy(transact)
Expand All @@ -529,7 +531,7 @@ def _get_resolver(
self,
normal_name: str,
fn_name: str = 'addr'
) -> Tuple[Optional['Contract'], str]:
) -> Tuple[Optional[Union['Contract', 'AsyncContract']], str]:
current_name = normal_name

# look for a resolver, starting at the full name and taking the parent each time that no
Expand All @@ -549,7 +551,8 @@ def _get_resolver(
current_name = self.parent(current_name)

def _decode_ensip10_resolve_data(
self, contract_call_result: bytes, extended_resolver: 'Contract', fn_name: str,
self, contract_call_result: bytes,
extended_resolver: Union['Contract', 'AsyncContract'], fn_name: str,
) -> Any:
func = extended_resolver.get_function_by_name(fn_name)
output_types = get_abi_output_types(func.abi)
Expand All @@ -568,18 +571,21 @@ def _setup_reverse(
transact['from'] = address
return self._reverse_registrar().functions.setName(name).transact(transact)

def _type_aware_resolver(self, address: ChecksumAddress, func: str) -> 'Contract':
def _type_aware_resolver(self,
address: ChecksumAddress,
func: str) -> Union['Contract', 'AsyncContract']:
return (
self._reverse_resolver_contract(address=address) if func == 'name' else
self._resolver_contract(address=address)
)

def _reverse_registrar(self) -> 'Contract':
def _reverse_registrar(self) -> Union['Contract', 'AsyncContract']:
addr = self.ens.caller.owner(normal_name_to_hash(REVERSE_REGISTRAR_DOMAIN))
return self.w3.eth.contract(address=addr, abi=abis.REVERSE_REGISTRAR)


def _resolver_supports_interface(resolver: 'Contract', interface_id: HexStr) -> bool:
def _resolver_supports_interface(resolver: Union['Contract', 'AsyncContract'],
interface_id: HexStr) -> bool:
if not any('supportsInterface' in repr(func) for func in resolver.all_functions()):
return False
return resolver.caller.supportsInterface(interface_id)
3 changes: 2 additions & 1 deletion ethpm/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,8 @@ def get_contract_instance(self, name: ContractName, address: Address) -> Contrac
contract_instance = self.w3.eth.contract(
address=address, **contract_kwargs
)
return contract_instance
# TODO: type ignore may be able to be removed after more of AsyncContract is finished
return contract_instance # type: ignore

#
# Build Dependencies
Expand Down
1 change: 1 addition & 0 deletions newsfragments/2270.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add async version of contract functionality
28 changes: 28 additions & 0 deletions tests/core/conftest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import pytest

import pytest_asyncio

from web3 import Web3
from web3.eth import (
AsyncEth,
)
from web3.module import (
Module,
)
from web3.providers.eth_tester.main import (
AsyncEthereumTesterProvider,
)

# --- inherit from `web3.module.Module` class --- #

Expand Down Expand Up @@ -97,3 +106,22 @@ def __init__(self, a, b):
self.a = a
self.b = b
return ModuleManyArgs


@pytest_asyncio.fixture()
async def async_w3():
provider = AsyncEthereumTesterProvider()
w3 = Web3(provider, modules={'eth': [AsyncEth]},
middlewares=provider.middlewares)
w3.eth.default_account = await w3.eth.coinbase
return w3


@pytest_asyncio.fixture()
async def async_w3_strict_abi():
provider = AsyncEthereumTesterProvider()
w3 = Web3(provider, modules={'eth': [AsyncEth]},
middlewares=provider.middlewares)
w3.enable_strict_bytes_type_checking()
w3.eth.default_account = await w3.eth.coinbase
return w3
39 changes: 39 additions & 0 deletions tests/core/contracts/_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import asyncio

from eth_utils.toolz import (
identity,
)


def deploy(w3, Contract, apply_func=identity, args=None):
args = args or []
deploy_txn = Contract.constructor(*args).transact()
deploy_receipt = w3.eth.wait_for_transaction_receipt(deploy_txn)
assert deploy_receipt is not None
address = apply_func(deploy_receipt['contractAddress'])
contract = Contract(address=address)
assert contract.address == address
assert len(w3.eth.get_code(contract.address)) > 0
return contract


async def async_deploy(async_web3, Contract, apply_func=identity, args=None):
args = args or []
deploy_txn = await Contract.constructor(*args).transact()
deploy_receipt = await async_web3.eth.wait_for_transaction_receipt(deploy_txn)
assert deploy_receipt is not None
address = apply_func(deploy_receipt['contractAddress'])
contract = Contract(address=address)
assert contract.address == address
assert len(await async_web3.eth.get_code(contract.address)) > 0
return contract


def async_partial(f, *args, **kwargs):
async def f2(*args2, **kwargs2):
result = f(*args, *args2, **kwargs, **kwargs2)
if asyncio.iscoroutinefunction(f):
result = await result
return result

return f2
Loading