Web3py Readthedocs Io en v6.17.0
Web3py Readthedocs Io en v6.17.0
Release 6.17.0
1 Getting Started 3
2 Table of Contents 5
Index 295
i
ii
Populus Documentation, Release 6.17.0
Important: For ENS (Ethereum Name Service) users, web3.py v6.6.0 introduced ENS name normalization stan-
dard ENSIP-15. This update to ENS name validation and normalization won’t affect ~99% of names but may prevent
invalid names from being created and from interacting with the ENS contracts via web3.py. We feel strongly that this
change, though breaking, is in the best interest of our users as it ensures compatibility with the latest ENS standards.
INTRO 1
Populus Documentation, Release 6.17.0
2 INTRO
CHAPTER
ONE
GETTING STARTED
3
Populus Documentation, Release 6.17.0
TWO
TABLE OF CONTENTS
2.1 Quickstart
• Installation
• Using Web3
– Test Provider
– Local Providers
– Remote Providers
• Getting Blockchain Info
Note: All code starting with a $ is meant to run on your terminal. All code starting with a >>> is meant to run in a
python interpreter, like ipython.
2.1.1 Installation
Note: If you run into problems during installation, you might have a broken environment. See the troubleshooting
guide to setting up a clean environment.
This library depends on a connection to an Ethereum node. We call these connections Providers and there are several
ways to configure them. The full details can be found in the Providers documentation. This Quickstart guide will
highlight a couple of the most common use cases.
5
Populus Documentation, Release 6.17.0
Test Provider
If you’re just learning the ropes or doing some quick prototyping, you can use a test provider, eth-tester. This provider
includes some accounts prepopulated with test ether and instantly includes each transaction into a block. web3.py
makes this test provider available via EthereumTesterProvider.
Note: The EthereumTesterProvider requires additional dependencies. Install them via pip install
"web3[tester]", then import and instantiate the provider as seen below.
Local Providers
The hardware requirements are steep, but the safest way to interact with Ethereum is to run an Ethereum client on
your own hardware. For locally run nodes, an IPC connection is the most secure option, but HTTP and websocket
configurations are also available. By default, the popular Geth client exposes port 8545 to serve HTTP requests and
8546 for websocket requests. Connecting to this local node can be done as follows:
# IPCProvider:
>>> w3 = Web3(Web3.IPCProvider('./path/to/geth.ipc'))
# HTTPProvider:
>>> w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
# WebsocketProvider:
>>> w3 = Web3(Web3.WebsocketProvider('wss://127.0.0.1:8546'))
>>> w3.is_connected()
True
# AsyncHTTPProvider:
>>> w3 = AsyncWeb3(AsyncWeb3.AsyncHTTPProvider('http://127.0.0.1:8545'))
Remote Providers
The quickest way to interact with the Ethereum blockchain is to use a remote node provider. You can connect to a
remote node by specifying the endpoint, just like the previous local node example:
>>> w3 = Web3(Web3.HTTPProvider('https://<your-provider-url>'))
>>> w3 = AsyncWeb3(AsyncWeb3.AsyncHTTPProvider('https://<your-provider-url>'))
>>> w3 = Web3(Web3.WebsocketProvider('wss://<your-provider-url>'))
This endpoint is provided by the remote node service, typically after you create an account.
It’s time to start using web3.py! Once properly configured, the w3 instance will allow you to interact with the Ethereum
blockchain. Try getting all the information about the latest block:
>>> w3.eth.get_block('latest')
{'difficulty': 1,
'gasLimit': 6283185,
'gasUsed': 0,
'hash': HexBytes('0x53b983fe73e16f6ed8178f6c0e0b91f23dc9dad4cb30d0831f178291ffeb8750'),
'logsBloom': HexBytes(
˓→'0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
˓→'),
'miner': '0x0000000000000000000000000000000000000000',
'mixHash': HexBytes('0x0000000000000000000000000000000000000000000000000000000000000000
˓→'),
'nonce': HexBytes('0x0000000000000000'),
'number': 0,
'parentHash': HexBytes(
˓→'0x0000000000000000000000000000000000000000000000000000000000000000'),
'proofOfAuthorityData': HexBytes(
˓→'0x0000000000000000000000000000000000000000000000000000000000000000dddc391ab2bf6701c74d0c8698c2e13355b
˓→'),
'receiptsRoot': HexBytes(
˓→'0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421'),
'sha3Uncles': HexBytes(
˓→'0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347'),
'size': 622,
'stateRoot': HexBytes(
˓→'0x1f5e460eb84dc0606ab74189dbcfe617300549f8f4778c3c9081c119b5b5d1c1'),
'timestamp': 0,
'totalDifficulty': 1,
'transactions': [],
'transactionsRoot': HexBytes(
˓→'0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421'),
'uncles': []}
web3.py can help you read block data, sign and send transactions, deploy and interact with contracts, and a number of
other features.
2.1. Quickstart 7
Populus Documentation, Release 6.17.0
Note: It is recommended that your development environment have the PYTHONWARNINGS=default environment
variable set. Some deprecation warnings will not show up without this variable being set.
2.2 Overview
The purpose of this page is to give you a sense of everything web3.py can do and to serve as a quick reference guide.
You’ll find a summary of each feature with links to learn more. You may also be interested in the Examples page, which
demonstrates some of these features in greater detail.
2.2.1 Configuration
After installing web3.py (via pip install web3), you’ll need to configure a provider endpoint and any middleware
you want to use beyond the defaults.
Providers
Providers are how web3.py connects to a blockchain. The library comes with the following built-in providers:
• IPCProvider for connecting to ipc socket based JSON-RPC servers.
• HTTPProvider for connecting to http and https based JSON-RPC servers.
• WebsocketProvider for connecting to ws and wss websocket based JSON-RPC servers.
• AsyncHTTPProvider for connecting to http and https based JSON-RPC servers.
Examples
# IPCProvider:
>>> w3 = Web3(Web3.IPCProvider('./path/to/geth.ipc'))
# HTTPProvider:
>>> w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
# WebsocketProvider:
>>> w3 = Web3(Web3.WebsocketProvider('ws://127.0.0.1:8546'))
>>> w3.is_connected()
(continues on next page)
# AsyncHTTPProvider:
>>> w3 = AsyncWeb3(AsyncWeb3.AsyncHTTPProvider('http://127.0.0.1:8545'))
Middleware
Private keys are required to approve any transaction made on your behalf. The manner in which your key is secured
will determine how you create and send transactions in web3.py.
A local node, like Geth, may manage your keys for you. You can reference those keys using the web3.eth.accounts
property.
A hosted node, like Infura, will have no knowledge of your keys. In this case, you’ll need to have your private key
available locally for signing transactions.
Full documentation on the distinction between keys can be found here. The separate guide to Sending Transactions
may also help clarify how to manage keys.
• Web3.is_encodable()
• Web3.to_bytes()
• Web3.to_hex()
• Web3.to_int()
• Web3.to_json()
• Web3.to_text()
2.2. Overview 9
Populus Documentation, Release 6.17.0
Address Helpers
• Web3.is_address()
• Web3.is_checksum_address()
• Web3.to_checksum_address()
Currency Conversions
• Web3.from_wei()
• Web3.to_wei()
Cryptographic Hashing
• Web3.keccak()
• Web3.solidity_keccak()
The most commonly used APIs for interacting with Ethereum can be found under the web3.eth namespace. As a
reminder, the Examples page will demonstrate how to use several of these methods.
Fetching Data
Viewing account balances (get_balance), transactions (get_transaction), and block data (get_block) are some
of the most common starting points in web3.py.
API
• web3.eth.get_balance()
• web3.eth.get_block()
• web3.eth.get_block_transaction_count()
• web3.eth.get_code()
• web3.eth.get_proof()
• web3.eth.get_storage_at()
• web3.eth.get_transaction()
• web3.eth.get_transaction_by_block()
• web3.eth.get_transaction_count()
• web3.eth.get_uncle_by_block()
• web3.eth.get_uncle_count()
Sending Transactions
The most common use cases will be satisfied with send_transaction or the combination of sign_transaction
and send_raw_transaction. For more context, see the full guide to Sending Transactions.
Note: If interacting with a smart contract, a dedicated API exists. See the next section, Contracts.
API
• web3.eth.send_transaction()
• web3.eth.sign_transaction()
• web3.eth.send_raw_transaction()
• web3.eth.replace_transaction()
• web3.eth.modify_transaction()
• web3.eth.wait_for_transaction_receipt()
• web3.eth.get_transaction_receipt()
• web3.eth.sign()
• web3.eth.sign_typed_data()
• web3.eth.estimate_gas()
• web3.eth.generate_gas_price()
• web3.eth.set_gas_price_strategy()
Contracts
web3.py can help you deploy, read from, or execute functions on a deployed contract.
Deployment requires that the contract already be compiled, with its bytecode and ABI available. This compilation step
can be done within Remix or one of the many contract development frameworks, such as Ape.
Once the contract object is instantiated, calling transact on the constructor method will deploy an instance of the
contract:
Once a deployed contract is loaded into a Contract object, the functions of that contract are available on the functions
namespace:
If you want to read data from a contract (or see the result of transaction locally, without executing it on the network),
you can use the ContractFunction.call method, or the more concise ContractCaller syntax:
2.2. Overview 11
Populus Documentation, Release 6.17.0
# Using ContractFunction.call
>>> deployed_contract.functions.getMyValue().call()
42
# Using ContractCaller
>>> deployed_contract.caller().getMyValue()
42
API
• web3.eth.contract()
• Contract.address
• Contract.abi
• Contract.bytecode
• Contract.bytecode_runtime
• Contract.functions
• Contract.events
• Contract.fallback
• Contract.constructor()
• Contract.encode_abi()
• web3.contract.ContractFunction
• web3.contract.ContractEvents
If you want to react to new blocks being mined or specific events being emitted by a contract, you can leverage web3.py
filters.
More complex patterns for creating filters and polling for logs can be found in the Monitoring Events documentation.
API
• web3.eth.filter()
• web3.eth.get_filter_changes()
• web3.eth.get_filter_logs()
• web3.eth.uninstall_filter()
• web3.eth.get_logs()
• Contract.events.your_event_name.create_filter()
• Contract.events.your_event_name.build_filter()
• Filter.get_new_entries()
• Filter.get_all_entries()
• Filter.format_entry()
• Filter.is_valid_entry()
2.2.6 ethPM
ethPM allows you to package up your contracts for reuse or use contracts from another trusted registry. See the full
details here.
2.2.7 ENS
Ethereum Name Service (ENS) provides the infrastructure for human-readable addresses. If an address is registered
with the ENS registry, the domain name can be used in place of the address itself. For example, the registered domain
name ethereum.eth will resolve to the address 0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe. web3.py has
support for ENS, documented here.
Improved Documentation
Features
• Add request formatter for maxFeePerBlobGas when sending blob transactions. Add formatters for
blobGasPrice and blobGasUsed for eth_getTransactionReceipt. (#3323)
• Add formatters to ensure that the result of a eth_createAccessList response can be plugged directly into an
accessList in a transaction. (#3329)
• Add Cancun support to EthereumTesterProvider; update Cancun-related fields in some internal types.
(#3338)
Bugfixes
Deprecations
Features
Performance Improvements
• Utilize async functionality when popping responses from request manager cache for persistent connection
providers. (#3305)
Bugfixes
• Handle new geth errors related to waiting for a transaction receipt while transactions are still being indexed.
(#3217)
Improved Documentation
• Create test fixture for latest geth version. Run tests with geth in --dev mode. (#3191)
• Formatting updates for black==24.1.0. (#3207)
• Add eth-tester version that supports eth_feeHistory (#3222)
• Use a message listener background task for WebsocketProviderV2 rather than relying on ws.recv() blocking.
Some breaking changes to API, notably listen_to_websocket -> process_subscriptions. (#3206)
• Compile contracts with and test against new Solidity version v0.8.24. (#3205)
Bugfixes
• Change fee_history default behavior. If reward_percentiles arg not included, pass it to the provider as an
empty list instead of None. (#3185)
• Use importlib.metadata for version info if python>=3.8 (#3187)
Improved Documentation
• Re-define how async vs sync core test suites are ran. (#3180)
• Add basic import and version tests for the web3 module (#3187)
Features
• Implement async eth_createAccessList RPC method to create an EIP-2930 access list. (#3167)
Improved Documentation
• Make downloadable versions of docs available in pdf, htmlzip, and epub formats (#3153)
• Add 2023 user survey fine art banner in the docs (#3159)
• Polish the community resources docs page (#3162)
Features
Bugfixes
• Fix collision of w3 variable when initializing contract with function of the same name (#3147)
Miscellaneous Changes
• #3148
Bugfixes
• When coming back through the middleware onion after a request is made, we have the response id. Use it to
match to the cached request information and process the response accordingly. (#3140)
Improved Documentation
• Additional contract abi documentation to make it a clear requirement for contract instances. (#2539)
• Fix type annotations for web3 constants. (#3138)
• Add upper pin to deprecated dependency lru-dict whose new minor version release introduced a typing issue
with CI lint builds. (#3144)
• Recompile test contracts with new Solidity version v0.8.23 to ensure compatibility. (#3146)
Improved Documentation
• Speed up the core test suite by splitting up sync and async tests. This reduces the CI build times to ~8min from
~12min. (#3111)
• Re-compile test contracts with Solidity v0.8.22 to ensure compatibility with this latest Solidity version. (#3134)
• Improvements on yielding to the event loop while searching in response caches and calling recv() on the web-
socket connection for WebsocketProviderV2. (#3135)
Improved Documentation
Features
• Updates and refactoring for the WebsocketProviderV2 class and its internal supporting classes and logic. Sep-
aration of one-to-one and one-to-many request responses. Storing of one-to-many responses in a deque and
one-to-one responses in a SimpleCache class. Provide an async lock around the websocket recv(). (#3125)
• Add upper pin to hexbytes dependency to due incoming breaking change (#3127)
Miscellaneous Changes
• #3114, #3129
• Refactor the async iterator pattern for message streams from the websocket connection for
WebsocketProviderV2 to a proper async iterator. This allows for a more natural usage of the iterator
pattern and mimics the behavior of the underlying websockets library. (#3116)
Bugfixes
Improved Documentation
Features
• Allow passing in a float for a request_timeout for requests for the Beacon class. Update some Beacon API
endpoints (sync and async). (#3106)
• Add allow_list kwarg for exception_retry_middleware to allow for a custom list of RPC endpoints. Add
a sleep between retries and a customizable backoff_factor to control the sleep time between retry attempts.
(#3120)
• Refactor logic for the input_munger() method on the Method class. (#2987)
• Pin mypy to v1.4.1, the last to support py37 (#3122)
• Breaking change to the API for interacting with a persistent websocket connection via AsyncWeb3 and
WebsocketProviderV2. This change internalizes the provider.ws property and opts for a w3.ws API
achieved via a new WebsocketConnection class. With these changes, eth_subscription messages now
return the subscription id as the subscription param and the formatted message as the result param. (#3096)
Bugfixes
• Return w3.eth.gas_price when calculating time based gas price strategy for an empty chain. (#1149)
• Update LogReceipt and TxReceipt declarations. Remove LogReceipt’s payload and topic attributes. Refactor
LogEntry to LogReceipt. (#3043)
• Fixes AsyncEth.max_priority_fee_per_gas. It wasn’t falling back to eth_feeHistory since the
MethodUnavailable error was introduced. (#3084)
Improved Documentation
• Update WebsocketProviderV2 documentation to reflect the new public websocket API via the
WebsocketConnection class. (#3096)
Features
• Improved error messaging for exceptions from malformed JSON-RPC responses. (#3053)
• Enable filtering by non-indexed arguments for contract event get_logs(). (#3078)
• Add eth_maxPriorityFeePerGas to exception_retry_middleware whitelist (#3090)
• Sync responses for WebsocketProviderV2 open connections with requests via matching RPC id values.
(#3096)
• Properly JSON encode AttributeDict, bytes, and HexBytes when sending a JSON-RPC request by utilizing
the in-house Web3JsonEncoder class. (#3101)
Bugfixes
• Fix the type for input in TxData from HexStr -> HexBytes. (#3074)
• Fix an issue with WebsocketProviderV2 when responses to a request aren’t found in the cache (None values).
(#3075)
• Re-expose some websockets constants found in web3.providers.websocket.websocket via web3.
providers.websocket. (#3076)
• Return NotImplemented constant, rather than raising NotImplementedError for NamedElementOnion.
__add__(), based on Python standards. (#3080)
• Only release async_lock if it’s locked to begin with. (#3083)
Improved Documentation
Bugfixes
• Fix the type for the optional param asking for “full transactions” when subscribing to
newPendingTransactions via eth_subscribe to bool. (#3067)
Improved Documentation
• Change docs to reflect AsyncHTTPProvider does accept ENS names now (#3070)
Features
• Return structured JSON-RPC errors for missing or unimplemented eth-tester methods. (#3061)
• ENS name-to-address support for eth_subscribe. (#3066)
• Asynchronous iterator support for AsyncWeb3 with WebsocketProviderV2 using async for syntax. (#3067)
• Minor fixes to type hinting in the core tests setup fixtures. (#3069)
Bugfixes
Improved Documentation
• Add note to Release Notes about v5 end-of-life and v6.6.0 yank (#3045)
• Add documentation for WebsocketProviderV2 (beta). (#3048)
Features
• Add ENSIP-9 (Multichain Address Resolution) support for address() and setup_address() for ENS and
AsyncENS classes. (#3030)
• Support for eth_subscribe and eth_unsubscribe methods has been added with the introduction of a new
websocket provider, WebsocketProviderV2. (#3048)
Bugfixes
Note: This release was missing the required ``ens/specs`` directory, so it was yanked from Pypi in favor of v6.6.1
Breaking Changes
• ENS name normalization now uses ENSIP-15 by default. This is technically a breaking change introduced by
ENS but, according to ENSIP-15, 99% of existing names should be unaffected. (#3024)
Bugfixes
Improved Documentation
Features
Miscellaneous Changes
Removals
• Removed references to deprecated middlewares with new tests to check default middlewares (#2972)
Bugfixes
• Properly create a fresh cache for each instance of simple_cache_middleware if no cache is provided. Fixes a
bug when using this middleware with multiple instances of Web3. (#2979)
• Fix potential race condition when writing cache entries in simple_cache_middleware (#2981)
• Catch UnicodeDecodeError for contract revert messages that cannot be decoded and issue a warning instead,
raising a ContractLogicError with the raw data from the response. (#2989)
Improved Documentation
Features
• lint-roll - dropped isort --recursive flag, not needed as of their v5, added black (#2930)
• Moved ethpm deprecation warning to only show when the module is explicitly enabled (#2983)
• Update make release to check remote upstream is pointing to ethereum/web3.py. (#2988)
• Removed pluggy from dev requirements (#2992)
Miscellaneous Changes
• #2960, #2965
Bugfixes
• fix AttributeDicts unhashable if they contain lists recursively tupleizing them (#2908)
Deprecations
Improved Documentation
• remove reference to the ability to specify a list of providers - you can’t anymore (#2949)
• add deprecation notice for the ethPM module (#2953)
Features
• Update eth-tester to pull in Shanghai changes and make additional changes to fully support Shanghai with
eth-tester. (#2958)
Features
Bugfixes
• Typing was being ignored for the get_ipc_path and get_dev_ipc_path functions because of a missing None
return. Those two methods now explicitly return None and have an Optional in their type definition. (#2917)
• fix AsyncEventFilterBuilder looking for Web3 instead of AsyncWeb3 (#2931)
• Add check for null withdrawal field on get_block response (#2941)
Improved Documentation
Features
Bugfixes
Improved Documentation
Features
• Add tracing functionality back in via the tracing module, add formatters for human-readable input and output,
and attach this module to Web3 on init / make it a default module. (#2851)
• Add result formatters for withdrawals_root and withdrawals as part of Shanghai hard fork support.
(#2868)
• add eth_chainId to exception_retry_middleware whitelist (#2892)
Bugfixes
Improved Documentation
Miscellaneous changes
• #2887
Bugfixes
Features
Bugfixes
• More accurately define the eth_call return type as HexBytes since the response is converted to HexBytes in
the pythonic formatters and there are differences between HexBytes and bytes types. (#2842)
• Set default block_identifier in ContractFunction.call() to None (#2846)
Improved Documentation
• Do not invoke setup.py directly; use python -m build where appropriate. (#2714)
• clean up ignored unused imports (#2838)
• Recompile test contracts with the new Solidity version 0.8.19. (#2840)
• Update py-geth version and re-generate integration test fixture with geth v1.11.2. (#2841)
Breaking changes
• Use AsyncWeb3 class and preserve typing for the async api calls. (#2819)
• Fix typing for CallOverrideParams and add proper request formatters for call state overrides. (#2843)
• Remove python warning and doc notes related to unstable async providers. (#2845)
Features
Bugfixes
Improved Documentation
• Organize the eth module into separate files for better readability. (#2753)
• Rename the newly-split eth module files to match convention. (#2772)
• Re-compile all test contracts with latest Solidity version. Refactor test fixtures. Adds a script that compiles all
test contracts to the same directory with selected Solidity version. (#2797)
• Updates to isort and black required some formatting changes and isort config refactoring. (#2802)
• Compile test contracts using newly-released Solidity version 0.8.18. (#2803)
Breaking changes
• All exceptions inherit from a custom class. EthPM exceptions inherit from EthPMException, ENS exceptions
inherit from ENSException, and all other web3.py exceptions inherit from Web3Exception (#1478)
• Reorganized contract to contract.py, async_contract.py, base_contract.py and utils.py. In this change there was
a small breaking change where the constructor of BaseContractCaller contract_function_class was defaulting to
a ContractFunction now there is no default. This was done to separate the base class from the implementation.
(#2567)
• When calling a contract, use w3.eth.default_block if no block_identifier is specified instead of latest.
(#2777)
• Strict bytes type checking is now default for web3.py. This change also adds a boolean flag on the Web3 class
for turning this feature on and off, as well as a flag on the ENS class for control over a standalone ENS instance.
(#2788)
• When a method is not supported by a node provider, raise a MethodUnavailable error instead of the generic
ValueError. (#2796)
• dict to AttributeDict conversion is no longer a default result formatter. This conversion is now done via a
default middleware that may be removed. (#2805)
• Removed deprecated manager.request_async and associated methods. (#2810)
• removed Rinkeby from list of allowed chains in EthPM (#2815)
Features
Bugfixes
Performance improvements
• Some minor performance improvements to the SimpleCache class and simple cache middlewares (sync and
async). (#2719)
• Remove unnecessary await for generate_gas_price() method as it does not need to be awaited. Move this
method to BaseEth to be used directly by both Eth and AsyncEth modules. (#2735)
Improved Documentation
• Use regex pattern for black command for tox / make lint linting commands. (#2727)
• Use regex pattern for mypy command for tox / make lint linting commands. (#2734)
• Remove internal method apply_formatter_to_array and use the method with the same name from the
eth-utils library. (#2737)
Miscellaneous changes
• #2751
Breaking changes
Features
• Async support for caching certain methods via async_simple_cache_middleware as well as constructing
custom async caching middleware via async_construct_simple_cache_middleware. SimpleCache class
was also added to the public utils module. (#2579)
• Remove upper pins on dependencies (#2648)
• Async support for beacon api. (#2689)
• If the loop for a cached async session is closed, or the session itself was closed, create a new session at that cache
key and properly close and evict the stale session. (#2713)
Bugfixes
• move definition of RTD install requirements file from their dashboard into .readthedocs.yml, and remove unused
sphinx-better-theme from requirements (#2688)
Miscellaneous changes
• #2690, #2694
Breaking changes
• Remove support for dictionary-based caches, for simple-cache-middleware, in favor of the internal SimpleCache
class. (#2579)
• Snakecase the clientVersion method (#2686)
• change instances of createFilter to create_filter (#2692)
• Remove SolidityError in favor of ContractLogicError (#2697)
• Snakecase the solidityKeccak method (#2702)
• Snakecase the fromWeb3 method (#2703)
• Snakecase the toBytes, toHex, toInt, toJSON, and toText methods (#2707)
• Snakecase the toAddress, isChecksumAddress, and toChecksumAddress methods (#2708)
Bugfixes
• Protobuf dependency had a DoS-able bug. It was fixed in v4.21.6. See: https://nvd.nist.gov/vuln/detail/
CVE-2022-1941 (#2666)
Improved Documentation
• Remove Ropsten auto provider and the relevant references to Ropsten across the repo (#2672)
Miscellaneous changes
• #2671, #2682
Bugfixes
• Protobuf dependency breaks at version 3.20.2 and above; pin to 3.20.1 for now. (#2657)
Features
Breaking Changes
Bugfixes
Documentation Updates
• Update Proof of Authority middleware (geth_poa_middleware) documentation for better clarity. (#2538)
• Add some missing supported async middlewares to docs. (#2574)
• Introduce AsyncENS and availability on w3 instance in ENS guide. (#2585)
• Fix typo in eth.call docs (#2613)
• remove section for deleted account.recoverHash method (#2615)
• examples docs gave incorrect return type for eth.get_transaction, fixed (#2617)
• minor typo fix in contracts overview (#2628)
• fix bug in Deploying new contracts example (#2646)
Features
Misc
Breaking Changes
• sha3 and soliditySha3 were previously deprecated and now removed (#2479)
• Remove deprecated methods from Geth, Parity and Net modules (#2480)
• Provide better messaging to wrong arguments for contract functions, especially for tuple argument types.
(#2556)
Bugfixes
Documentation Updates
• Remove deprecated methods from Geth, Parity, and Net modules (#2480)
• replace double- with single-quotes to make f-string valid (#2504)
• added geth personal_sign and personal_ec_recover documentation (#2511)
Features
• Add transaction result formatters for type and chainId to convert values to int if hexadecimal if the field is not
null (#2491)
• Add a global flag on the provider for enabling / disabling CCIP Read for calls: global_ccip_read_enabled
(defaults to True). (#2499)
• Deprecate Geth Admin StartRPC and StopRPC for StartHTTP and StopHTTP (#2507)
• Added Async support for ENS (#2547)
• support multi-dimensional arrays for ABI tuples types (#2555)
Misc
• #2345, #2483, #2505, #2513, #2514, #2515, #2516, #2518, #2520, #2521, #2522, #2523, #2524, #2525, #2527,
#2530, #2531, #2534, #2542, #2544, #2550, #2551, #2559
Breaking Changes
Bugfixes
Documentation Updates
Features
Misc
Breaking Changes
• Audit .rst and .py files and convert all Web3 instance variable names to w3 to avoid confusion with the web3
module. (#1183)
• Update dependency requirements: - eth-utils - eth-abi - eth-tester - eth-account - eth-typing (#2342)
• Add attach_methods() to Module class to facilitate attaching methods to modules. (#2383)
• Move IOError -> OSError (#2434)
Documentation Updates
Features
Misc
Breaking Changes
Bugfixes
• Fix types for gas, and gasLimit: Wei -> int. Also fix types for effectiveGasPrice: (int -> Wei)
(#2330)
Features
Misc
• #2353, #2365
Features
• Added Async functions for Geth Personal and Admin modules (#1413)
• async support for formatting, validation, and geth poa middlewares (#2098)
• Calculate a default maxPriorityFeePerGas using eth_feeHistory when eth_maxPriorityFeePerGas is
not available, since the latter is not a part of the Ethereum JSON-RPC specs and only supported by certain clients.
(#2259)
• Allow NamedTuples in ABI inputs (#2312)
• Add async eth.syncing method (#2331)
Bugfixes
Features
Bugfixes
• Fixed issues with parsing tuples and nested tuples in event logs (#2211)
• In ENS the contract function to resolve an ENS address was being called twice in error. One of those calls was
removed. (#2318)
• to_hexbytes block formatters no longer throw when value is None (#2321)
Improved Documentation
Misc
• #2217
Features
Bugfixes
Improved Documentation
Misc
Features
Bugfixes
• BadResponseFormat error thrown instead of KeyError when a response gets sent back without a result key.
(#2188)
Improved Documentation
Misc
Features
Bugfixes
Improved Documentation
Misc
• #2105
Features
• Add constants for the zero address, zero hash, max int, and wei per ether. (#2109)
Improved Documentation
• Renamed “1559 transaction” to “dynamic fee transaction” where appropriate to keep consistency among the
general code base for 1559 transaction (type=2) naming (#2118)
• Update AsyncHTTPProvider doc example to include modules and middlewares keyword arguments (#2123)
Misc
Features
Bugfixes
• Hot fix for string interpolation issue with contract function call decoding exception to facilitate extracting a
meaningful message from the eth_call response (#2096)
• Bypass adding a gasPrice via the gas price strategy, if one is set, when EIP-1559 transaction params are used
for send_transaction (#2099)
Improved Documentation
Features
Bugfixes
Improved Documentation
Misc
Features
• Adds support for EIP 1559 transaction keys: maxFeePerGas and maxPriorityFeePerGas (#2060)
Bugfixes
• Bugfix where an error response got passed to a function expecting a block identifier.
Split out null result formatters from the error formatters and added some tests. (#2022)
• Fix broken tests and use the new 1559 params for most of our test transactions. (#2053)
• Set a default maxFeePerGas value consistent with Geth (#2055)
• Fix bug in geth PoA middleware where a None response should throw a BlockNotFound error, but was instead
throwing an AttributeError (#2064)
Improved Documentation
• Added general documentation on unit and integration testing and how to contribute to our test suite. (#2053)
Bugfixes
• Have the geth dev IPC auto connection check for the WEB3_PROVIDER_URI environment variable. (#2023)
Improved Documentation
Misc
Features
Bugfixes
Improved Documentation
Misc
Features
Improved Documentation
Misc
Features
Improved Documentation
Misc
Features
Improved Documentation
Features
Bugfixes
• Fix event filter creation if the event ABI contains a values key. (#1807)
Improved Documentation
• Remove v5 breaking changes link from the top of the release notes. (#1837)
• Add account creation troubleshooting docs. (#1855)
• Document passing a struct into a contract function. (#1860)
• Add instance configuration troubleshooting docs. (#1865)
• Clarify nonce lookup in sendRawTransaction docs. (#1866)
• Updated docs for web3.eth methods: eth.getTransactionReceipt and eth.waitForTransactionReceipt (#1868)
Features
Bugfixes
• PR #1585 changed the error that was coming back from eth-tester when the Revert opcode was called, which
broke some tests in downstream libraries. This PR reverts back to raising the original error. (#1813)
• Added a new ContractLogicError for when a contract reverts a transaction. ContractLogicError will
replace SolidityError, in v6. (#1814)
Improved Documentation
Misc
Bugfixes
• Remove docs/web3.* from the gitignore to allow for the beacon docs to be added to git, and add beacon to the
default web3 modules that get loaded. (#1824)
• Remove auto-documenting from the Beacon API (#1825)
Features
Misc
• #1815, #1816
Bugfixes
Improved Documentation
Misc
Features
• Raise SolidityError exceptions that contain the revert reason when a call fails. (#941)
Bugfixes
• Update eth-tester dependency to fix tester environment install version conflict. (#1782)
Misc
• #1757, #1767
Misc
Bugfixes
Misc
Misc
Features
Improved Documentation
Misc
• #1687
• #1690
Bugfixes
Bugfixes
Improved Documentation
Features
• Allow consumer to initialize HttpProvider with their own requests.Session. This allows the HttpAdapter con-
nection pool to be tuned as desired. (#1469)
• Update web3.pm and ethpm module to EthPM v3 specification. (#1652)
Bugfixes
Improved Documentation
• Add a getBalance() example and provide more context for using the fromWei and toWei utility methods.
(#1676)
• Overhaul the Overview documentation to provide a tour of major features. (#1681)
Bugfixes
• Added formatter rules for eth_tester middleware to allow getBalance() by using integer block numbers (#1660)
• Fix type annotations within the eth.py module. Several arguments that defaulted to None were not declared
Optional. (#1668)
• Fix type annotation warning when using string URI to instantiate an HTTP or WebsocketProvider. (#1669)
• Fix type annotations within the web3 modules. Several arguments that defaulted to None were not declared
Optional. (#1670)
Improved Documentation
• Breaks up links into three categories (Intro, Guides, and API) and adds content to the index page: a lib introduc-
tion and some “Getting Started” links. (#1671)
• Fills in some gaps in the Quickstart guide and adds provider connection details for local nodes. (#1673)
Features
• Accept a block identifier in the Contract.estimateGas method. Includes a related upgrade of eth-tester to
v0.5.0-beta.1. (#1639)
• Introduce a more specific validation error, ExtraDataLengthError. This enables tools to detect when someone
may be connected to a POA network, for example, and provide a smoother developer experience. (#1666)
Bugfixes
Improved Documentation
• Corrects the return value of getTransactionReceipt, description of caching middleware, and deprecated
method names. (#1663)
• Corrects documentation of websocket timeout configuration. (#1665)
Features
• An update of eth-tester includes a change of the default fork from Constantinople to Muir Glacier. #1636
Bugfixes
Misc
• #1636
Features
• Upgrade eth-account to use v0.5.2+. eth-account 0.5.2 adds support for hd accounts
Also had to pin eth-keys to get dependencies to resolve. (#1622)
Bugfixes
Features
Bugfixes
Improved Documentation
Misc
• #1545
Features
Bugfixes
Misc
• #1590
Features
• Add snake_case methods to Geth Miner class, deprecate camelCase methods (#1579)
• Add snake_case methods for the net module, deprecate camelCase methods (#1581)
• Add PEP561 type marker (#1583)
Bugfixes
Improved Documentation
Misc
• #1576
Features
• ENS had to release a new registry to push a bugfix. See this article for background information. web3.py uses
the new registry for all default ENS interactions, now. (#1573)
Bugfixes
Improved Documentation
Misc
Features
Bugfixes
Bugfixes
Improved Documentation
Misc
• #1518, #1532
Features
Bugfixes
• Make local block filter return empty list when when no blocks mined (#1255)
• Google protobuf dependency was updated to 3.10.0 (#1493)
• Infura websocket provider works when no secret key is present (#1501)
Improved Documentation
• Update Quickstart instructions to use the auto Infura module instead of the more complicated web3 auto module
(#1482)
• Remove outdated py.test command from readme (#1483)
Misc
Features
Bugfixes
Misc
• #1472, #1474
Improved Documentation
Misc
• #1468
Features
Bugfixes
Improved Documentation
Features
Bugfixes
Improved Documentation
• Remove whitespace, move topics key -> topic in Geth docs (#1425)
• Enforce stricter doc checking, turning warnings into errors to fail CI builds to catch issues quickly.
Add missing web3.tools.rst to the table of contents and fix incorrectly formatted JSON example. (#1437)
• Add example using Geth POA Middleware with Infura Rinkeby Node (#1444)
Misc
• #1446, #1451
2.3.78 v5.0.2
2.3.79 v5.0.1
2.3.80 v5.0.0
2.3.81 v5.0.0-beta.5
2.3.82 v5.0.0-beta.4
2.3.83 v5.0.0-beta.3
2.3.84 v5.0.0-beta.2
2.3.85 v5.0.0-beta.1
2.3.86 v5.0.0-alpha.11
2.3.87 v5.0.0-alpha.10
2.3.88 v5.0.0-alpha.9
2.3.89 v5.0.0-alpha.8
2.3.90 v5.0.0-alpha.7
2.3.91 v5.0.0-alpha.6
2.3.92 v5.0.0-alpha.5
2.3.93 v5.0.0-alpha.4
2.3.94 v5.0.0-alpha.3
2.3.95 v5.0.0-alpha.2
2.3.96 v5.0.0-alpha.1
2.3.97 v4.8.2
2.3.98 v4.8.1
2.3.99 v4.7.2
2.3.100 v4.7.1
2.3.101 v4.7.0
2.3.102 v4.6.0
2.3.103 v4.5.0
2.3.104 v4.4.1
2.3.105 v4.4.0
• Misc
– Websockets dependency upgraded to v5
– Raise deprecation warning on getTransactionFromBlock()
– Fix docs for waitForTransactionReceipt()
– Developer Dockerfile now installs testing dependencies
2.3.106 v4.3.0
2.3.107 v4.2.1
2.3.108 v4.2.0
2.3.109 v4.1.0
2.3.110 v4.0.0
2.3.111 v4.0.0-beta.13
2.3.112 v4.0.0-beta.12
2.3.113 v4.0.0-beta.11
2.3.114 v4.0.0-beta.10
2.3.115 v4.0.0-beta.9
2.3.116 v4.0.0-beta.8
Released Feb 7, 2018, then recalled. It added 32MB of test data to git history, so the tag was deleted, as well as the
corresponding release. (Although the release would not have contained that test data)
2.3.117 v4.0.0-beta.7
2.3.118 v4.0.0-beta.6
2.3.119 v4.0.0-beta.5
2.3.120 v4.0.0-beta.4
2.3.121 v4.0.0-beta.3
2.3.122 v4.0.0-beta.2
2.3.123 v4.0.0-beta.1
2.3.124 3.16.1
2.3.125 3.16.0
2.3.126 3.15.0
2.3.127 3.14.2
2.3.128 3.14.1
2.3.129 3.14.0
• New stalecheck_middleware
• Improvements to Web3.toHex and Web3.toText.
• Improvements to Web3.sha3 signature.
• Bugfixes for Web3.eth.sign api
2.3.130 3.13.5
2.3.131 3.13.4
2.3.132 3.13.3
2.3.133 3.13.2
• Bugfix for retrieving filter changes for both new block filters and pending transaction filters.
2.3.134 3.13.1
2.3.135 3.13.0
2.3.136 3.12.0
• Bugfix for abi filtering to correctly handle constructor and fallback type abi entries.
2.3.137 3.11.0
• All web3 apis which accept address parameters now enforce checksums if the address looks like it is check-
summed.
• Improvements to error messaging with when calling a contract on a node that may not be fully synced
• Bugfix for web3.eth.syncing to correctly handle False
2.3.138 3.10.0
2.3.139 3.9.0
2.3.140 3.8.1
2.3.141 3.8.0
2.3.142 3.7.1
2.3.143 3.7.0
2.3.144 3.6.2
2.3.145 3.6.1
2.3.146 3.6.0
2.3.147 3.5.3
2.3.148 3.5.2
2.3.149 3.5.1
2.3.150 3.5.0
• Deprecate web3.providers.rpc.RPCProvider
• Deprecate web3.providers.rpc.KeepAliveRPCProvider
• Add new web3.providers.rpc.HTTPProvider
• Remove hard dependency on gevent.
2.3.151 3.4.4
2.3.152 3.4.3
• Bugfix for event log data decoding to properly handle dynamic sized values.
• New web3.tester module to access extra RPC functionality from eth-testrpc
2.3.153 3.4.2
2.3.154 3.4.1
2.3.155 3.4.0
2.3.156 3.3.0
2.3.157 3.2.0
2.3.158 3.1.1
• Bugfix for contract transaction sending not respecting the web3.eth.defaultAccount configuration.
2.3.159 3.1.0
2.3.160 3.0.2
2.3.161 3.0.1
2.3.162 3.0.0
• Filter objects now support controlling the interval through which they poll using the poll_interval property
2.3.163 2.9.0
2.3.164 2.8.1
2.3.165 2.8.0
2.3.166 2.7.1
2.3.167 2.7.0
2.3.168 2.6.0
2.3.169 2.5.0
• All transactions which contain a data element will now have their gas automatically estimated with 100k addi-
tional buffer. This was previously only true with transactions initiated from a Contract object.
2.3.170 2.4.0
2.3.171 2.3.0
2.3.172 2.2.0
• The filters that come back from the contract on and pastEvents methods now call their callbacks with the same
data format as web3.js.
2.3.173 2.1.1
2.3.174 2.1.0
2.3.175 2.0.0
2.3.176 1.9.0
2.3.177 1.8.0
2.3.178 1.7.1
2.3.179 1.7.0
2.3.180 1.6.0
2.3.181 1.5.0
2.3.182 1.4.0
2.3.183 1.3.0
2.3.184 1.2.0
2.3.185 1.1.0
2.3.186 1.0.1
2.3.187 1.0.0
2.3.188 0.1.0
• Initial release
The Ethereum protocol defines a way for people to interact with smart contracts and each other over a network. In
order to have up-to-date information about the status of contracts, balances, and new transactions, the protocol requires
a connection to nodes on the network. These nodes are constantly sharing new data with each other.
web3.py is a python library for connecting to these nodes. It does not run its own node internally.
Due to the nature of Ethereum, this is largely a question of personal preference, but it has significant ramifications on
security and usability. Further, node software is evolving quickly, so please do your own research about the current
options.
One of the key decisions is whether to use a local node or a hosted node. A quick summary is at Local vs Hosted Nodes.
A local node requires less trust than a hosted one. A malicious hosted node can give you incorrect information, log
your sent transactions with your IP address, or simply go offline. Incorrect information can cause all kinds of problems,
including loss of assets.
On the other hand, with a local node your machine is individually verifying all the transactions on the network, and
providing you with the latest state. Unfortunately, this means using up a significant amount of disk space, and sometimes
notable bandwidth and computation. Additionally, there is a big up-front time cost for downloading the full blockchain
history.
If you want to have your node manage keys for you (a popular option), you must use a local node. Note that even if you
run a node on your own machine, you are still trusting the node software with any accounts you create on the node.
You can find a list of node software at ethereum.org.
Some people decide that the time it takes to sync a local node from scratch is too high, especially if they are just
exploring Ethereum for the first time. One way to work around this issue is to use a hosted node.
Hosted node options can also be found at ethereum.org. You can connect to a hosted node as if it were a local node,
with a few caveats. It cannot (and should not) host private keys for you, meaning that some common methods like
w3.eth.send_transaction() are not directly available. To send transactions to a hosted node, read about Working
with Local Private Keys.
Once you decide what node option you want, you need to choose which network to connect to. Typically, you are
choosing between the main network and one of the available test networks. See Which network should I connect to?
MetaMask is not a node. It is an interface for interacting with a node. Roughly, it’s what you get if you turn web3.py
into a browser extension.
By default, MetaMask connects to an Infura node. You can also set up MetaMask to use a node that you run locally.
If you are trying to use accounts that were already created in MetaMask, see Why isn’t my web3 instance connecting to
the network?
Once you have answered How do I choose which node to use? you have to pick which network to connect to. This is
easy for some scenarios: if you have ether and you want to spend it, or you want to interact with any production smart
contracts, then you connect to the main Ethereum network.
If you want to test these things without using real ether, though, then you need to connect to a test network. There are
several test networks to choose from; view the list on ethereum.org.
Each network has its own version of Ether. Main network ether must be purchased, naturally, but test network ether is
usually available for free. See How do I get ether for my test network?
Once you have decided which network to connect to, and set up your node for that network, you need to decide how to
connect to it. There are a handful of options in most nodes. See Choosing How to Connect to Your Node.
2.5 Providers
The provider is how web3 talks to the blockchain. Providers take JSON-RPC requests and return the response. This is
normally done by submitting the request to an HTTP or IPC socket based server.
Note: web3.py supports one provider per instance. If you have an advanced use case that requires multiple providers,
create and configure a new web3 instance per connection.
If you are already happily connected to your Ethereum node, then you can skip the rest of the Providers section.
Most nodes have a variety of ways to connect to them. If you have not decided what kind of node to use, head on over
to How do I choose which node to use?
The most common ways to connect to your node are:
1. IPC (uses local filesystem: fastest and most secure)
2. Websockets (works remotely, faster than HTTP)
3. HTTP (more nodes support it)
If you’re not sure how to decide, choose this way:
• If you have the option of running web3.py on the same machine as the node, choose IPC.
• If you must connect to a node on a different computer, use Websockets.
• If your node does not support Websockets, use HTTP.
Most nodes have a way of “turning off” connection options. We recommend turning off all connection options that you
are not using. This provides a safer setup: it reduces the number of ways that malicious hackers can try to steal your
ether.
Once you have decided how to connect, you specify the details using a Provider. Providers are web3.py classes that are
configured for the kind of connection you want.
See:
• IPCProvider
• WebsocketProvider
• WebsocketProviderV2
• HTTPProvider
• AsyncHTTPProvider
Once you have configured your provider, for example:
Then you are ready to initialize your Web3 instance, like so:
w3 = Web3(my_provider)
Alternatively, you can set the environment variable WEB3_PROVIDER_URI before starting your script, and web3 will
look for that provider first.
Valid formats for this environment variable are:
• file:///path/to/node/rpc-json/file.ipc
• http://192.168.1.2:8545
• https://node.ontheweb.com
• ws://127.0.0.1:8546
2.5. Providers 85
Populus Documentation, Release 6.17.0
Web3 ships with the following providers which are appropriate for connecting to local and remote JSON-RPC servers.
HTTPProvider
Note that you should create only one HTTPProvider with the same provider URL per python process, as
the HTTPProvider recycles underlying TCP/IP network connections, for better performance. Multiple HTTP-
Providers with different URLs will work as expected.
Under the hood, the HTTPProvider uses the python requests library for making requests. If you would like
to modify how requests are made, you can use the request_kwargs to do so. A common use case for this is
increasing the timeout for each request.
To tune the connection pool size, you can pass your own requests.Session.
IPCProvider
WebsocketProvider
Note: WebsocketProviderV2 is currently in beta and our goal is to fully replace WebsocketProvider with
WebsocketProviderV2 in the next major release of web3.py.
Under the hood, the WebsocketProvider uses the python websockets library for making requests. If you would
like to modify how requests are made, you can use the websocket_kwargs to do so. See the websockets docu-
mentation for available arguments.
Unlike HTTP connections, the timeout for WS connections is controlled by a separate websocket_timeout
argument, as shown below.
2.5. Providers 87
Populus Documentation, Release 6.17.0
• request_information_cache_size is the size of the cache used to store request information so that
when a response is received, the provider knows how to process it based on the original request. Defaults
to 500.
WebsocketProviderV2 (beta)
Warning: This provider is still in beta. However, it is being actively developed and supported and is expected to
be stable in the next major version of web3.py (v7).
Usage
The AsyncWeb3 class may be used as a context manager, utilizing the async with syntax, when connecting via
persistent_websocket() using the WebsocketProviderV2. This will automatically close the connection when
the context manager exits and is the recommended way to initiate a persistent connection to the websocket provider.
A similar example, using the websockets connection as an asynchronous context manager, can be found in the web-
sockets connection docs.
>>> asyncio.run(ws_v2_subscription_context_manager_example())
The AsyncWeb3 class may also be used as an asynchronous iterator, utilizing the async for syntax, when connecting
via persistent_websocket() using the WebsocketProviderV2. This may be used to set up an indefinite websocket
connection and reconnect automatically if the connection is lost. A similar example, using the websockets connection
as an asynchronous iterator, can be found in the websockets connection docs.
If neither of the two init patterns above work for your application, the __await__() method is defined on the
persistent_websocket() connection in a manner that awaits connecting to the websocket. You may also choose to
instantiate and connect via the provider in separate lines. Both of these examples are shown below.
2.5. Providers 89
Populus Documentation, Release 6.17.0
...
... # some code here
...
... # manual cleanup
... await w3.provider.disconnect()
The WebsocketProviderV2 class uses the RequestProcessor class under the hood to sync up the receiving
of responses and response processing for one-to-one and one-to-many request-to-response requests. Refer to the
RequestProcessor documentation for details.
When an AsyncWeb3 class is connected to a persistent websocket connection, via the persistent_websocket()
method, it becomes an instance of the _PersistentConnectionWeb3 class. This class has a few additional methods
and attributes that are not available on the AsyncWeb3 class.
class web3.main._PersistentConnectionWeb3
ws
The public API for interacting with the websocket connection is available via the ws attribute of the
_PersistentConnectionWeb3 class. This attribute is an instance of the WebsocketConnection class
and is the main interface for interacting with the websocket connection.
class web3.providers.websocket.WebsocketConnection
This class handles interactions with a websocket connection. It is available via the ws attribute of the
_PersistentConnectionWeb3 class. The WebsocketConnection class has the following methods and at-
tributes:
subscriptions
This attribute returns the current active subscriptions as a dict mapping the subscription id to a dict of
metadata about the subscription request.
process_subscriptions()
This method is available for listening to websocket subscriptions indefinitely. It is an asynchronous iterator
that yields strictly one-to-many (e.g. eth_subscription responses) request-to-response messages from
the websocket connection. To receive responses for one-to-one request-to-response calls, use the standard
API for making requests via the appropriate module (e.g. block_num = await w3.eth.block_number)
The responses from this method are formatted by web3.py formatters and run through the middlewares that
were present at the time of subscription. An example of its use can be seen above in the Usage section.
recv()
The recv() method can be used to receive the next message from the websocket. The response from this
method is formatted by web3.py formatters and run through the middlewares before being returned. This is
not the recommended way to receive a message as the process_subscriptions() method is available for
listening to websocket subscriptions and the standard API for making requests via the appropriate module
(e.g. block_num = await w3.eth.block_number) is available for receiving responses for one-to-one
request-to-response calls.
send(method: RPCEndpoint, params: Sequence[Any])
This method is available strictly for sending raw requests to the websocket, if desired. It is not recommended
to use this method directly, as the responses will not be formatted by web3.py formatters or run through the
middlewares. Instead, use the methods available on the respective web3 module. For example, use w3.eth.
get_block("latest") instead of w3.ws.send("eth_getBlockByNumber", ["latest", True]).
AutoProvider
AutoProvider is the default used when initializing web3.Web3 without any providers. There’s rarely a reason to use
it explicitly.
AsyncHTTPProvider
>>> w3 = AsyncWeb3(AsyncHTTPProvider(endpoint_uri))
Under the hood, the AsyncHTTPProvider uses the python aiohttp library for making requests.
2.5. Providers 91
Populus Documentation, Release 6.17.0
EthereumTesterProvider
Warning: Experimental: This provider is experimental. There are still significant gaps in functionality. However
it is being actively developed and supported.
class web3.providers.eth_tester.EthereumTesterProvider(eth_tester=None)
This provider integrates with the eth-tester library. The eth_tester constructor argument should be an in-
stance of the EthereumTester or a subclass of BaseChainBackend class provided by the eth-tester library.
If you would like a custom eth-tester instance to test with, see the eth-tester library documentation for details.
Note: To install the needed dependencies to use EthereumTesterProvider, you can install the pip extras package that
has the correct interoperable versions of the eth-tester and py-evm dependencies needed to do testing: e.g. pip
install web3[tester]
Hosted Node
A hosted node is controlled by someone else. When you connect to Infura, you are connected to a hosted node.
See ethereumnodes.com for the list of free and commercial node providers.
Local Node
A local node is started and controlled by you on your computer. For several reasons (e.g., privacy, security), this
is the recommended path, but it requires more resources and work to set up and maintain.
An Ethereum private key is a 256-bit (32 bytes) random integer. For each private key, you get one Ethereum address,
also known as an Externally Owned Account (EOA).
In Python, the private key is expressed as a 32-byte long Python bytes object. When a private key is presented to users
in a hexadecimal format, it may or may not contain a starting 0x hexadecimal prefix.
Local Private Key
A local private key is a locally stored secret you import to your Python application. Please read below how you
can create and import a local private key and use it to sign transactions.
Hosted Private Key
This is a legacy way to use accounts when working with unit test backends like web3.providers.eth_tester.
main.EthereumTesterProvider or Anvil. Calling web3.eth.accounts gives you a predefined list of ac-
counts that have been funded with test ETH. You can use any of these accounts with use send_transaction()
without further configuration.
In the past, around 2015, this was also a way to use private keys in a locally hosted node, but this practice is now
discouraged.
Note: Methods like web3.eth.send_transaction` do not work with modern node providers, because they relied on a
node state and all modern nodes are stateless. You must always use local private keys when working with nodes hosted
by someone else.
A very common reason to work with local private keys is to interact with a hosted node.
Some common things you might want to do with a Local Private Key are:
• Sign a Transaction
• Sign a Contract Transaction
• Sign a Message
• Verify a Message
Using private keys usually involves w3.eth.account in one way or another. Read on for more, or see a full list of
things you can do in the docs for eth_account.Account.
Each Ethereum address has a matching private key. To create a new Ethereum account you can just generate a random
number that acts as a private key.
• A private key is just a random unguessable, or cryptographically safe, 256-bit integer number
• A valid private key is > 0 and < max private key value (a number above the elliptic curve order FFFFFFFF
FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141)
• Private keys do not have checksums.
To create a private key using web3.py and command line you can do:
• Never store private key with your source. Use environment variables to store the key. Read more below.
• You can also import the raw hex private key to MetaMask and any other wallet - the private key can be shared
between your Python code and any number of wallets.
If you create a private key, it comes with its own Ethereum address. By default, the balance of this address is zero.
Before you can send any transactions with your account, you need to top up.
• For a local test environment, any environment is bootstrapped with accounts that have ETH on them. Move ETH
from default accounts to your newly created account.
• For public mainnet, you need to buy ETH in a cryptocurrency exchange
• For a testnet, you need to [use a testnet faucet](https://faucet.paradigm.xyz/)
In this example we pass the private key to our Python application in an environment variable. This private key is then
added to the transaction signing keychain with Signing middleware.
If unfamiliar, note that you can export your private keys from Metamask and other wallets.
Warning:
• Never share your private keys.
• Never put your private keys in source code.
• Never commit private keys to a Git repository.
Example account_test_script.py
import os
from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3 import Web3, EthereumTesterProvider
from web3.middleware import construct_sign_and_send_raw_middleware
w3 = Web3(EthereumTesterProvider())
private_key = os.environ.get("PRIVATE_KEY")
assert private_key is not None, "You must set PRIVATE_KEY environment variable"
assert private_key.startswith("0x"), "Private key must start with 0x hex prefix"
# with your local private key through middleware and you no longer get the error
# "ValueError: The method eth_sendTransaction does not exist/is not available
# Generate a new 256-bit random integer using openssl UNIX command that acts as a␣
˓→private key.
encrypted_key = keyfile.read()
private_key = w3.eth.account.decrypt(encrypted_key, 'correcthorsebatterystaple')
# tip: do not save the key or password anywhere, especially into a shared source file
Warning: There is no single message format that is broadly adopted with community consensus. Keep an eye on
several options, like EIP-683, EIP-712, and EIP-719. Consider the w3.eth.sign() approach be deprecated.
For this example, we will use the same message hashing mechanism that is provided by w3.eth.sign().
r=104389933075820307925104709181714897380569894203213074526835978196648170704563,
s=28205917190874851400050446352651915501321657673772411533993420917949420456142,
v=28,
signature=HexBytes(
˓→'0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb33e5bfbbf4d3e39b1a2fd816a7680c19ebeb
˓→'))
Let’s say you want a contract to validate a signed message, like if you’re making payment channels, and you want to
validate the value in Remix or web3.js.
You might have produced the signed_message locally, as in Sign a Message. If so, this will prepare it for Solidity:
Instead, you might have received a message and a signature encoded to hex. Then this will prepare it for Solidity:
˓→'
contract Recover {
function ecr (bytes32 msgh, uint8 v, bytes32 r, bytes32 s) public pure
returns (address sender) {
return ecrecover(msgh, v, r, s);
}
}
Then call ecr with these arguments from Prepare message for ecrecover in Solidity in
Remix, "0x1476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f750",
28, "0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb3",
"0x3e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce"
The message is verified, because we get the correct sender of the message back in response:
0x5ce9454909639d2d17a3f753ce7d93fa0b9ab12e.
Create a transaction, sign it locally, and then send it to your node for broadcasting, with send_raw_transaction().
>>> transaction = {
... 'to': '0xF0109fC8DF283027b6285cc889F5aA624EaC1F55',
... 'value': 1000000000,
... 'gas': 2000000,
... 'maxFeePerGas': 2000000000,
... 'maxPriorityFeePerGas': 1000000000,
... 'nonce': 0,
... 'chainId': 1,
... 'type': '0x2', # the type is optional and, if omitted, will be interpreted␣
˓→based on the provided transaction parameters
˓→')
>>> signed.hash
HexBytes('0xe85ce7efa52c16cb5c469c7bde54fbd4911639fdfde08003f65525a85076d915')
>>> signed.r
84095564551732371065849105252408326384410939276686534847013731510862163857293
>>> signed.s
32698347985257114675470251181312399332782188326270244072370350491677872459742
>>> signed.v
1
# When you run send_raw_transaction, you get back the hash of the transaction:
>>> w3.eth.send_raw_transaction(signed.rawTransaction)
'0xe85ce7efa52c16cb5c469c7bde54fbd4911639fdfde08003f65525a85076d915'
# When running locally, execute the statements found in the file linked below to load␣
˓→the EIP20_ABI variable.
# See: https://github.com/carver/ethtoken.py/blob/v0.0.1-alpha.4/ethtoken/abi.py
>>> unicorn_txn
{'value': 0,
'chainId': 1,
'gas': 70000,
'maxFeePerGas': 2000000000,
'maxPriorityFeePerGas': 1000000000,
'nonce': 0,
'to': '0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359',
'data':
˓→'0xa9059cbb000000000000000000000000fb6916095ca1df60bb79ce92ce3ea74c37c5d359000000000000000000000000000
˓→'}
>>> signed_txn.r
93522894155654168208483453926995743737629589441154283159505514235904280342434
>>> signed_txn.s
48417310681110102814014302147799665717176259465062324746227758019974374282313
>>> signed_txn.v
1
>>> w3.eth.send_raw_transaction(signed_txn.rawTransaction)
# When you run send_raw_transaction, you get the same result as the hash of the␣
˓→transaction:
>>> w3.to_hex(w3.keccak(signed_txn.rawTransaction))
'0x748db062639a45e519dba934fce09c367c92043867409160c9989673439dc817'
Note: Prefer to view this code in a Jupyter Notebook? View the repo here.
There are two methods for sending transactions using web3.py: send_transaction() and
send_raw_transaction(). A brief guide:
1. Want to sign a transaction offline or send pre-signed transactions?
• use sign_transaction + send_raw_transaction()
2. Are you primarily using the same account for all transactions and would you prefer to save a few lines of code?
• configure construct_sign_and_send_raw_middleware(), then
• use send_transaction()
3. Otherwise:
• load account via eth-account (w3.eth.account.from_key(pk)), then
• use send_transaction()
Interacting with or deploying a contract?
• Option 1: transact() uses send_transaction() under the hood
• Option 2: build_transaction() + sign_transaction + send_raw_transaction()
An example for each can be found below.
Many tutorials use eth-tester (via EthereumTesterProvider) for convenience and speed of conveying ideas/building
a proof of concept. Transactions sent by test accounts are auto-signed.
w3 = Web3(EthereumTesterProvider())
some_address = "0x0000000000000000000000000000000000000000"
tx = w3.eth.get_transaction(tx_hash)
assert tx["from"] == acct1
The send_transaction() method is convenient and to-the-point. If you want to continue using the pattern after
graduating from eth-tester, you can utilize web3.py middleware to sign transactions from a particular account:
# Note: Never commit your key in your code! Use env variables instead:
pk = os.environ.get('PRIVATE_KEY')
# Transactions from `acct2` will then be signed, under the hood, in the middleware:
tx_hash = w3.eth.send_transaction({
(continues on next page)
tx = w3.eth.get_transaction(tx_hash)
assert tx["from"] == acct2.address
# 1. Build a new tx
transaction = {
'from': acct2.address,
'to': some_address,
'value': 1000000000,
'nonce': w3.eth.get_transaction_count(acct2.address),
'gas': 200000,
'maxFeePerGas': 2000000000,
'maxPriorityFeePerGas': 1000000000,
}
The same concepts apply for contract interactions, at least under the hood.
Executing a function on a smart contract requires sending a transaction, which is typically done in one of two ways:
• executing the transact() function, or
• build_transaction(), then signing and sending the raw transaction.
#########################################
#### SMOL CONTRACT FOR THIS EXAMPLE: ####
#########################################
# // SPDX-License-Identifier: MIT
# pragma solidity 0.8.17;
#
# contract Billboard {
# string public message;
#
# constructor(string memory _message) {
# message = _message;
# }
#
# function writeBillboard(string memory _message) public {
# message = _message;
# }
# }
If you’re on this page, you’re likely looking for an answer to this question: How do I know when a specific contract
is used? You have at least three options:
1. Query blocks for transactions that include the contract address in the "to" field. This contrived example is
searching the latest block for any transactions sent to the WETH contract.
WETH_ADDRESS = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'
block = w3.eth.get_block('latest')
for tx_hash in block.transactions:
tx = w3.eth.get_transaction(tx_hash)
if tx['to'] == WETH_ADDRESS:
print(f'Found interaction with WETH contract! {tx}')
2. Query for logs emitted by a contract. After instantiating a web3.py Contract object, you can fetch logs for any
event listed in the ABI. In this example, we query for Transfer events in the latest block and log out the results.
WETH_ADDRESS = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'
WETH_ABI = '[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":
˓→"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant
˓→":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],
˓→"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability
˓→":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply",
˓→"outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type
˓→":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst
˓→","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{
˓→"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":
˓→"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":
˓→"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function
˓→"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}
˓→],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs
˓→":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":
˓→"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant
˓→":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable
˓→":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name
˓→":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs
˓→":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":
˓→"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,
˓→"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"",
˓→"type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"
˓→","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{
˓→"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,
˓→"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy",
˓→"type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval",
˓→"type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":
˓→"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad
˓→","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{
˓→"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":
˓→"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed
˓→":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],
˓→"name":"Withdrawal","type":"event"}]'
Warning: While filters can be a very convenient way to monitor for blocks, transactions, or events, they are
notoriously unreliable. Both remote and locally hosted nodes have a reputation for occasionally dropping filters,
and some remote node providers don’t support filter-related RPC calls at all.
event_filter = mycontract.events.myEvent.create_filter(fromBlock='latest',␣
˓→argument_filters={'arg1':10})
existing_filter = w3.eth.filter(filter_id="0x0")
Note: Creating event filters requires that your Ethereum node has an API support enabled for filters. Note that Infura
support for filters does not offer access to pending filters. To get event logs on other stateless nodes please see web3.
contract.ContractEvents.
Filter.filter_id
The filter_id for this filter as returned by the eth_newFilter RPC method when this filter was created.
Filter.get_new_entries()
Retrieve new entries for this filter.
Logs will be retrieved using the web3.eth.Eth.get_filter_changes() which returns only new entries since
the last poll.
Filter.get_all_entries()
Retrieve all entries for this filter.
Logs will be retrieved using the web3.eth.Eth.get_filter_logs() which returns all entries that match the
given filter.
Filter.format_entry(entry)
Hook for subclasses to modify the format of the log entries this filter returns, or passes to its callback functions.
By default this returns the entry parameter umodified.
Filter.is_valid_entry(entry)
Hook for subclasses to add additional programmatic filtering. The default implementation always returns True.
class web3.utils.filters.BlockFilter(...)
new_block_filter = w3.eth.filter('latest')
new_block_filter.get_new_entries()
Note: "safe" and "finalized" block identifiers are not yet supported for eth_newBlockFilter.
class web3.utils.filters.TransactionFilter(...)
new_transaction_filter = w3.eth.filter('pending')
new_transaction_filter.get_new_entries()
You can set up a filter for event logs using the web3.py contract api: web3.contract.Contract.events.
your_event_name.create_filter(), which provides some conveniences for creating event log filters. Refer to
the following example:
event_filter = myContract.events.<event_name>.create_filter(fromBlock="latest",
˓→ argument_filters={'arg1':10})
event_filter.get_new_entries()
event_signature_hash = web3.keccak(text="eventName(uint32)").hex()
event_filter = web3.eth.filter({
"address": myContract_address,
"topics": [event_signature_hash,
˓→"0x000000000000000000000000000000000000000000000000000000000000000a"],
})
The topics argument is order-dependent. For non-anonymous events, the first item in the topic list is always the
keccack hash of the event signature. Subsequent topic items are the hex encoded values for indexed event arguments.
In the above example, the second item is the arg1 value 10 encoded to its hex string representation.
In addition to being order-dependent, there are a few more points to recognize when specifying topic filters:
Given a transaction log with topics [A, B], the following topic filters will yield a match:
• [] “anything”
• [A] “A in first position (and anything after)”
• [None, B] “anything in first position AND B in second position (and anything after)”
• [A, B] “A in first position AND B in second position (and anything after)”
• [[A, B], [A, B]] “(A OR B) in first position AND (A OR B) in second position (and anything after)”
See the JSON-RPC documentation for eth_newFilter more information on the standard filter parameters.
Note: Though "finalized" and "safe" block identifiers are not yet part of the specifications for
eth_newFilter, they are supported by web3.py and may or may not yield expected results depending
on the node being accessed.
Creating a log filter by either of the above methods will return a LogFilter instance.
class web3.utils.filters.LogFilter(web3, filter_id, log_entry_formatter=None, data_filter_set=None)
The LogFilter class is a subclass of Filter. See the Filter documentation for inherited methods.
LogFilter provides the following additional methods:
LogFilter.set_data_filters(data_filter_set)
Provides a means to filter on the log data, in other words the ability to filter on values from un-indexed event arguments.
The parameter data_filter_set should be a list or set of 32-byte hex encoded values.
Synchronous
def handle_event(event):
print(event)
def main():
block_filter = w3.eth.filter('latest')
log_loop(block_filter, 2)
if __name__ == '__main__':
main()
Starting with web3 version 4, the watch method was taken out of the web3 filter objects. There are many decisions
to be made when designing a system regarding threading and concurrency. Rather than force a decision, web3 leaves
these choices up to the user. Below are some example implementations of asynchronous filter-event handling that can
serve as starting points.
Beginning in python 3.5, the async and await built-in keywords were added. These provide a shared api for coroutines
that can be utilized by modules such as the built-in asyncio. Below is an example event loop using asyncio, that polls
multiple web3 filter object, and passes new entries to a handler.
def handle_event(event):
print(event)
# and whatever
def main():
block_filter = w3.eth.filter('latest')
tx_filter = w3.eth.filter('pending')
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(
asyncio.gather(
log_loop(block_filter, 2),
log_loop(tx_filter, 2)))
finally:
loop.close()
if __name__ == '__main__':
main()
Here is an extended version of above example, where the event loop is run in a separate thread, releasing the main
function for other tasks.
def handle_event(event):
print(event)
# and whatever
def main():
block_filter = w3.eth.filter('latest')
worker = Thread(target=log_loop, args=(block_filter, 5), daemon=True)
worker.start()
# .. do some other stuff
Here are some other libraries that provide frameworks for writing asynchronous python:
• gevent
• twisted
• celery
2.9 Contracts
Smart contracts are programs deployed to the Ethereum network. See the ethereum.org docs for a proper introduction.
To run this example, you will need to install a few extra features:
• The sandbox node provided by eth-tester. You can install it with:
• py-solc-x. This is the supported route to installing the solidity compiler solc. You can install it with:
After py-solc-x is installed, you will need to install a version of solc. You can install the latest version via a new
REPL with:
# get abi
>>> abi = contract_interface['abi']
# web3.py instance
>>> w3 = Web3(Web3.EthereumTesterProvider())
# Wait for the transaction to be mined, and get the transaction receipt
>>> tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
>>> greeter.functions.greet().call()
'Hello'
These factories are not intended to be initialized directly. Instead, create contract objects using the w3.eth.
contract() method. By default, the contract factory is Contract.
class web3.contract.Contract(address)
Contract provides a default interface for deploying and interacting with Ethereum smart contracts.
The address parameter can be a hex address or an ENS name, like mycontract.eth.
2.9.3 Properties
2.9.4 Methods
>>> transaction = {
'gasPrice': w3.eth.gas_price,
'chainId': None
}
>>> contract_data = token_contract.constructor(web3.eth.coinbase, 12345).build_
˓→transaction(transaction)
>>> web3.eth.send_transaction(contract_data)
filter_builder = myContract.events.myEvent.build_filter()
filter_builder.fromBlock = "latest"
filter_builder.args.clientID.match_any(1, 2, 3, 4)
filter_builder.args.region.match_single("UK")
filter_instance = filter_builder.deploy()
The deploy method returns a web3.utils.filters.LogFilter instance from the filter parameters generated
by the filter builder. Defining multiple match values for array arguments can be accomplished easily with the
filter builder:
filter_builder = myContract.events.myEvent.build_filter()
filter_builder.args.clientGroups.match_any((1, 3, 5,), (2, 3, 5), (1, 2, 3))
The filter builder blocks already defined filter parameters from being changed.
filter_builder = myContract.events.myEvent.build_filter()
filter_builder.fromBlock = "latest"
filter_builder.fromBlock = 0 # raises a ValueError
˓→"0xea87152b00000000000000000000000000000000000000000000000000000000000000400000000000000000000000
˓→"
>>> contract.all_functions()
[<Function identity(uint256,bool)>, <Function identity(int256,bool)>]
classmethod Contract.get_function_by_signature(signature)
Searches for a distinct function with matching signature. Returns an instance of ContractFunction upon
finding a match. Raises ValueError if no match is found.
>>> contract.get_function_by_signature('identity(uint256,bool)')
<Function identity(uint256,bool)>
classmethod Contract.find_functions_by_name(name)
Searches for all function with matching name. Returns a list of matching functions where every function is an
instance of ContractFunction. Returns an empty list when no match is found.
>>> contract.find_functions_by_name('identity')
[<Function identity(uint256,bool)>, <Function identity(int256,bool)>]
classmethod Contract.get_function_by_name(name)
Searches for a distinct function with matching name. Returns an instance of ContractFunction upon finding
a match. Raises ValueError if no match is found or if multiple matches are found.
>>> contract.get_function_by_name('unique_name')
<Function unique_name(uint256)>
classmethod Contract.get_function_by_selector(selector)
Searches for a distinct function with matching selector. The selector can be a hexadecimal string, bytes or int.
Returns an instance of ContractFunction upon finding a match. Raises ValueError if no match is found.
>>> contract.get_function_by_selector('0xac37eebb')
<Function identity(uint256)'>
>>> contract.get_function_by_selector(b'\xac7\xee\xbb')
<Function identity(uint256)'>
>>> contract.get_function_by_selector(0xac37eebb)
<Function identity(uint256)'>
classmethod Contract.find_functions_by_args(*args)
Searches for all function with matching args. Returns a list of matching functions where every function is an
instance of ContractFunction. Returns an empty list when no match is found.
classmethod Contract.get_function_by_args(*args)
Searches for a distinct function with matching args. Returns an instance of ContractFunction upon finding a
match. Raises ValueError if no match is found or if multiple matches are found.
>>> contract.get_function_by_args(1)
<Function unique_func_with_args(uint256)>
Note: web3.py rejects the initialization of contracts that have more than one function with the same selector or
signature. eg. blockHashAddendsInexpansible(uint256) and blockHashAskewLimitary(uint256) have the
same selector value equal to 0x00000000. A contract containing both of these functions will be rejected.
Below is an example of a contract that has multiple functions of the same name, and the arguments are ambiguous.
By default, web3 is strict when it comes to hex and bytes values, as of v6. If an abi specifies a byte size, but the value
that gets passed in is not the specified size, web3 will invalidate the value. For example, if an abi specifies a type of
bytes4, web3 will invalidate the following values:
Table 1: Invalid byte and hex strings with strict (default) bytes4 type
checking
Input Reason
'' Needs to be prefixed with a “0x” to be interpreted as an empty hex string
2 Wrong type
'ah' String is not valid hex
'1234' Needs to either be a bytestring (b’1234’) or be a hex value of the right size, prefixed
with 0x (in this case: ‘0x31323334’)
b'' Needs to have exactly 4 bytes
b'ab' Needs to have exactly 4 bytes
'0xab' Needs to have exactly 4 bytes
'0x6162636464' Needs to have exactly 4 bytes
However, you may want to be less strict with acceptable values for bytes types. This may prove useful if you trust
that values coming through are what they are meant to be with respect to the ABI. In this case, the automatic padding
might be convenient for inferred types. For this, you can set the w3.strict_bytes_type_checking() flag to False,
which is available on the Web3 instance. A Web3 instance which has this flag set to False will have a less strict set of
rules on which values are accepted. A bytes type will allow values as a hex string, a bytestring, or a regular Python
string that can be decoded as a hex. 0x-prefixed hex strings are also not required.
• A Python string that is not prefixed with 0x is valid.
• A bytestring whose length is less than the specified byte size is valid.
Table 2: Valid byte and hex strings for a non-strict bytes4 type
Input Normalizes to
'' b'\x00\x00\x00\x00'
'0x' b'\x00\x00\x00\x00'
b'' b'\x00\x00\x00\x00'
b'ab' b'ab\x00\x00'
'0xab' b'\xab\x00\x00\x00'
'1234' b'\x124\x00\x00'
'0x61626364' b'abcd'
'1234' b'1234'
HexBytes('0xcb95151142ea56dbf2753d70388aef202a7bb5a1e323d448bc19f1d2e1fe3dc9')
>>> # check value
>>> arrays_contract.functions.getBytes2Value().call()
[b'aa']
>>> # trying to set value without appropriate size (bytes2) is not valid
>>> arrays_contract.functions.setBytes2Value([b'b']).transact()
Traceback (most recent call last):
...
web3.exceptions.Web3ValidationError:
Could not identify the intended function with name
>>> # check value is still b'aa'
>>> arrays_contract.functions.getBytes2Value().call()
[b'aa']
class web3.contract.ContractFunction
The named functions exposed through the Contract.functions property are of the ContractFunction type. This
class is not to be used directly, but instead through Contract.functions.
For example:
If you have the function name in a variable, you might prefer this alternative:
func_to_call = 'multiply7'
contract_func = myContract.functions[func_to_call]
twentyone = contract_func(3).call()
ContractFunction provides methods to interact with contract functions. Positional and keyword arguments supplied
to the contract function subclass will be used to find the contract function by signature, and forwarded to the contract
function when applicable.
EIP-3668 introduced support for the OffchainLookup revert / CCIP Read support. CCIP Read is set to True for calls
by default, as recommended in EIP-3668. This is done via a global global_ccip_read_enabled flag on the provider.
If raising the OffchainLookup revert is preferred for a specific call, the ccip_read_enabled flag on the call may be
set to False.
*** web3.exceptions.OffchainLookup
Disabling CCIP Read support can be useful if a transaction needs to be sent to the callback function. In such cases,
“preflighting” with an eth_call, handling the OffchainLookup, and sending the data via a transaction may be nec-
essary. See CCIP Read support for offchain lookup in the examples section for how to preflight a transaction with a
contract call.
Similarly, if CCIP Read is globally set to False via the global_ccip_read_enabled flag on the provider, it may
be enabled on a per-call basis - overriding the global flag. This ensures only explicitly enabled calls will handle the
OffchainLookup revert appropriately.
>>> # does not raise the revert since explicitly enabled on the call:
>>> response = myContract.functions.revertsWithOffchainLookup(myData).
˓→call(ccip_read_enabled=True)
If the function called results in a revert error, a ContractLogicError will be raised. If there is an error message
with the error, web3.py attempts to parse the message that comes back and return it to the user as the error string. As
of v6.3.0, the raw data is also returned and can be accessed via the data attribute on ContractLogicError.
Methods
ContractFunction.transact(transaction)
Execute the specified function by sending a new public transaction.
Refer to the following invocation:
myContract.functions.myMethod(*args, **kwargs).transact(transaction)
The first portion of the function call myMethod(*args, **kwargs) selects the appropriate contract function
based on the name and provided argument. Arguments can be provided as positional arguments, keyword argu-
ments, or a mix of the two.
The end portion of this function call transact(transaction) takes a single parameter which should be
a python dictionary conforming to the same format as the web3.eth.send_transaction(transaction)
method. This dictionary may not contain the keys data.
If any of the args or kwargs specified in the ABI are an address type, they will accept ENS names.
If a gas value is not provided, then the gas value for the method transaction will be created using the web3.
eth.estimate_gas() method.
Returns the transaction hash.
ContractFunction.call(transaction, block_identifier='latest')
Call a contract function, executing the transaction locally using the eth_call API. This will not create a new
public transaction.
Refer to the following invocation:
myContract.functions.myMethod(*args, **kwargs).call(transaction)
This method behaves the same as the ContractFunction.transact() method, with transaction details being
passed into the end portion of the function call, and function arguments being passed into the first portion.
Returns the return value of the executed function.
>>> my_contract.functions.multiply7(3).call()
21
>>> token_contract.functions.myBalance().call({'from': web3.eth.coinbase})
12345 # the token balance for `web3.eth.coinbase`
>>> token_contract.functions.myBalance().call({'from': web3.eth.accounts[1]})
54321 # the token balance for the account `web3.eth.accounts[1]`
You can call the method at a historical block using block_identifier. Some examples:
# or a block hash:
>>> token_contract.functions.myBalance().call(block_identifier=
˓→'0x4ff4a38b278ab49f7739d3a4ed4e12714386a9fdf72192f2e8f7da7822f10b4d')
>>> token_contract.functions.myBalance().call(block_identifier=b'O\xf4\xa3\x8b\'\
˓→x8a\xb4\x9fw9\xd3\xa4\xedN\x12qC\x86\xa9\xfd\xf7!\x92\xf2\xe8\xf7\xdax"\xf1\x0bM')
# You can check the state after your pending transactions (if supported by your␣
˓→node):
>>> token_contract.functions.myBalance().call(block_identifier='pending')
Passing the block_identifier parameter for past block numbers requires that your Ethereum API node is
running in the more expensive archive node mode. Normally synced Ethereum nodes will fail with a “missing
trie node” error, because Ethereum node may have purged the past state from its database. More information
about archival nodes here.
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.
Refer to the following invocation:
myContract.functions.myMethod(*args, **kwargs).estimate_gas(transaction)
This method behaves the same as the ContractFunction.transact() method, with transaction details being
passed into the end portion of the function call, and function arguments being passed into the first portion.
Returns the amount of gas consumed which can be used as a gas estimate for executing this transaction publicly.
>>> 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'}
ContractFunction.build_transaction(transaction)
Builds a transaction dictionary based on the contract function call specified.
Refer to the following invocation:
myContract.functions.myMethod(*args, **kwargs).build_transaction(transaction)
This method behaves the same as the Contract.transact() method, with transaction details being passed
into the end portion of the function call, and function arguments being passed into the first portion.
Note: nonce is not returned as part of the transaction dictionary unless it is specified in the first portion of the
function call:
You may use getTransactionCount() to get the current nonce for an account. Therefore a shortcut for pro-
ducing a transaction dictionary with nonce included looks like:
Returns a transaction dictionary. This transaction dictionary can then be sent using send_transaction().
Additionally, the dictionary may be used for offline transaction signing using sign_transaction().
>>> math_contract.functions.increment(5).build_transaction({'maxFeePerGas':␣
˓→2000000000, 'maxPriorityFeePerGas': 1000000000})
{
'to': '0x582AC4D8929f58c217d4a52aDD361AE470a8a4cD',
'data':
˓→'0x7cf5dab00000000000000000000000000000000000000000000000000000000000000005',
'value': 0,
'gas': 43242,
'maxFeePerGas': 2000000000,
'maxPriorityFeePerGas': 1000000000,
'chainId': 1
}
Fallback Function
The Contract Factory also offers an API to interact with the fallback function, which supports four methods
like normal functions:
Contract.fallback.call(transaction)
Call fallback function, executing the transaction locally using the eth_call API. This will not create a new
public transaction.
Contract.fallback.estimate_gas(transaction)
Call fallback function and return the gas estimation.
Contract.fallback.transact(transaction)
Execute fallback function by sending a new public transaction.
Contract.fallback.build_transaction(transaction)
Builds a transaction dictionary based on the contract fallback function call.
2.9.8 Events
class web3.contract.ContractEvents
The named events exposed through the Contract.events property are of the ContractEvents type. This class is not
to be used directly, but instead through Contract.events.
For example:
ContractEvent provides methods to interact with contract events. Positional and keyword arguments supplied to the
contract event subclass will be used to find the contract event by signature.
ContractEvents.myEvent(*args, **kwargs).get_logs(fromBlock=None, toBlock="latest", block_hash=None,
argument_filters={})
Fetches all logs for a given event within the specified block range or block hash.
argument_filters is an optional dictionary argument that can be used to filter for logs where the
event’s argument values match the values provided in the dictionary. The keys must match the event
argument names as they exist in the ABI. The values can either be a single value or a list of values to
match against. If a list is provided, the logs will be filtered for any logs that match any of the values in
the list. Indexed arguments are filtered pre-call by building specific topics to filter for. Non-indexed
arguments are filtered by the library after the logs are fetched from the node.
# get ``myEvent`` logs from block 1337 to block 2337 where the value for the
# event argument "eventArg1" is either 1, 2, or 3
myContract.events.myEvent().get_logs(
argument_filters={"eventArg1": [1, 2, 3]},
fromBlock=1337,
toBlock=2337,
)
If there are errors, the logs will be handled differently depending on the flag that is passed in:
• WARN (default) - logs a warning to the console for the log that has an error, and discards the log. Returns
any logs that are able to be processed.
• STRICT - stops all processing and raises the error encountered.
• IGNORE - returns any raw logs that raised an error with an added “errors” field, along with any other logs
were able to be processed.
• DISCARD - silently discards any logs that have errors, and returns processed logs that don’t have errors.
An event log error flag needs to be imported from web3/logs.py.
'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b',
'blockHash': HexBytes(
˓→'0xd74c3e8bdb19337987b987aee0fa48ed43f8f2318edfc84e3a8643e009592a68'),
'blockNumber': 3
})
)
>>> processed_logs
(
AttributeDict({
'type': 'mined',
'logIndex': 0,
'transactionIndex': 0,
'transactionHash': HexBytes(
˓→'0x01682095d5abb0270d11a31139b9a1f410b363c84add467004e728ec831bd529'),
'blockHash': HexBytes(
˓→'0x92abf9325a3959a911a2581e9ea36cba3060d8b293b50e5738ff959feb95258a'),
'blockNumber': 5,
'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b',
'data': '0x0000000000000000000000000000000000000000000000000000000000003039
˓→',
'topics': [
HexBytes(
˓→'0xf70fe689e290d8ce2b2a388ac28db36fbb0e16a6d89c6804c461f65a1b40bb15')
],
'errors': LogTopicError('Expected 1 log topics. Got 0')})
})
)
>>> processed_logs = contract.events.myEvent().process_receipt(tx_receipt,␣
˓→errors=DISCARD)
ContractEvents.myEvent(*args, **kwargs).process_log(log)
Similar to process_receipt, but only processes one log at a time, instead of a whole transaction receipt. Will
return a single Event Log Object if there are no errors encountered during processing. If an error is encountered
during processing, it will be raised.
'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b',
'blockHash': HexBytes(
˓→'0xd74c3e8bdb19337987b987aee0fa48ed43f8f2318edfc84e3a8643e009592a68'),
'blockNumber': 3
})
The Event Log Object is a python dictionary with the following keys:
• args: Dictionary - The arguments coming from the event.
• event: String - The event name.
• logIndex: Number - integer of the log index position in the block.
• transactionIndex: Number - integer of the transactions index position log was created from.
• transactionHash: String, 32 Bytes - hash of the transactions this log was created from.
• address: String, 32 Bytes - address from which this log originated.
• blockHash: String, 32 Bytes - hash of the block where this log was in. null when it’s pending.
• blockNumber: Number - the block number where this log was in. null when it’s pending.
>>> transfer_filter.get_new_entries()
[AttributeDict({'args': AttributeDict({'from':
˓→'0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'to': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'value': 10}),
'event': 'Transfer',
'logIndex': 0,
(continues on next page)
'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b',
'blockHash': HexBytes('...'),
'blockNumber': 2})]
>>> transfer_filter.get_new_entries()
[]
>>> tx_hash = contract.functions.transfer(alice, 10).transact({'gas': 899000, 'gasPrice
˓→': 1000000000})
'to': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'value': 10}),
'event': 'Transfer',
'logIndex': 0,
'transactionIndex': 0,
'transactionHash': HexBytes('...'),
'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b',
'blockHash': HexBytes('...'),
'blockNumber': 3})]
>>> transfer_filter.get_all_entries()
[AttributeDict({'args': AttributeDict({'from':
˓→'0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'to': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'value': 10}),
'event': 'Transfer',
'logIndex': 0,
'transactionIndex': 0,
'transactionHash': HexBytes('...'),
'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b',
'blockHash': HexBytes('...'),
'blockNumber': 2}),
AttributeDict({'args': AttributeDict({'from':
˓→'0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'to': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'value': 10}),
'event': 'Transfer',
'logIndex': 0,
'transactionIndex': 0,
'transactionHash': HexBytes('...'),
'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b',
'blockHash': HexBytes('...'),
'blockNumber': 3})]
2.9.9 Utils
classmethod Contract.decode_function_input(data)
Decodes the transaction data used to invoke a smart contract function, and returns ContractFunction and
decoded parameters as dict.
>>> transaction.input
'0x612e45a3000000000000000000000000b656b2a9c3b2416437a811e07466ca712f5a5b5a0000000000000000000000
˓→
'
˓→
>>> contract.decode_function_input(transaction.input)
(<Function newProposal(address,uint256,string,bytes,uint256,bool)>,
{'_recipient': '0xB656b2a9c3b2416437A811e07466cA712F5a5b5a',
'_amount': 0,
'_description': b'lonely, so lonely',
'_transactionData': b'',
'_debatingPeriod': 604800,
'_newCurator': True})
2.9.10 ContractCaller
class web3.contract.ContractCaller
The ContractCaller class provides an API to call functions in a contract. This class is not to be used directly, but
instead through Contract.caller.
There are a number of different ways to invoke the ContractCaller.
For example:
And a transaction dictionary, with or without the transaction keyword. You can also optionally include a block
identifier. For example:
Like ContractFunction, ContractCaller provides methods to interact with contract functions. Positional and
keyword arguments supplied to the contract caller subclass will be used to find the contract function by signature, and
forwarded to the contract function when applicable.
web3.py accepts struct arguments as dictionaries. This format also supports nested structs. Let’s take a look at a quick
example. Given the following Solidity contract:
contract Example {
address addr;
struct S1 {
address a1;
address a2;
}
struct S2 {
bytes32 b1;
bytes32 b2;
}
struct X {
S1 s1;
S2 s2;
address[] users;
}
>>> deployed_contract.functions.retrieve().call()
'0x0000000000000000000000000000000000000000'
>>> deployed_contract.functions.update({'s1': [
(continues on next page)
˓→transact()
>>> deployed_contract.functions.retrieve().call()
'0x0000000000000000000000000000000000000002'
There is a boolean flag on the Web3 class and the ENS class that will disable strict bytes type checking. This
allows bytes values of Python strings and allows byte strings less than the specified byte size, appropriately
padding values that need padding. To disable stricter checks, set the w3.strict_bytes_type_checking (or ns.
strict_bytes_type_checking) flag to False. This will no longer cause the Web3 / ENS instance to raise an error if
a Python string is passed in without a “0x” prefix. It will also render valid byte strings or hex strings that are below the
exact number of bytes specified by the ABI type by padding the value appropriately, according to the ABI type. See
the Disabling Strict Checks for Bytes Types section for an example on using the flag and more details.
Note: If a standalone ENS instance is instantiated from a Web3 instance, i.e. ns = ENS.from_web3(w3), it will
inherit the value of the w3.strict_bytes_type_checking flag from the Web3 instance at the time of instantiation.
Also of note, all modules on the Web3 class will inherit the value of this flag, since all modules use the parent w3 object
reference under the hood. This means that w3.eth.w3.strict_bytes_type_checking will always have the same
value as w3.strict_bytes_type_checking.
For more details on the ABI specification, refer to the Solidity ABI Spec.
contract ManyTypes {
// booleans
bool public b;
// unsigned ints
uint8 public u8;
uint256 public u256;
uint256[] public u256s;
// signed ints
int8 public i8;
// addresses
address public addr;
address[] public addrs;
// bytes
bytes1 public b1;
// structs
struct S {
address sa;
bytes32 sb;
}
mapping(address => S) addrStructs;
Booleans
contract_instance.functions.updateBool(True).transact()
Unsigned Integers
contract_instance.functions.updateUint8(255).transact()
contract_instance.functions.updateUint256(2**256 - 1).transact()
contract_instance.functions.updateUintArray([1, 2, 3]).transact()
Signed Integers
contract_instance.functions.updateInt8(-128).transact()
Addresses
contract_instance.functions.updateAddr("0x0000000000000000000000000000000000000000").
˓→transact()
Bytes
contract_instance.functions.updateBytes1(HexBytes(255)).transact()
Structs
contract_instance.functions.updateMapping({"sa":
˓→"0x0000000000000000000000000000000000000000", "sb": HexBytes(123)}).transact()
2.11 Middleware
Web3 manages layers of middlewares by default. They sit between the public Web3 methods and the Providers, which
handle native communication with the Ethereum client. Each layer can modify the request and/or response. Some
middlewares are enabled by default, and others are available for optional use.
Each middleware layer gets invoked before the request reaches the provider, and then processes the result after the
provider returns, in reverse order. However, it is possible for a middleware to return early from a call without the
request ever getting to the provider (or even reaching the middlewares that are in deeper layers).
When integrating middleware with your provider, please ensure you’re choosing the right version. For AsyncWeb3
users, select the version prefixed with async, such as async_attrdict_middleware. On the other hand, Web3 users
should opt for versions lacking the async prefix. If an async version isn’t listed, it implies it hasn’t been made available
yet.
More information is available in the “Internals: Middlewares” section.
AttributeDict
web3.middleware.attrdict_middleware()
web3.middleware.async_attrdict_middleware()
This middleware recursively converts any dictionary type in the result of a call to an AttributeDict.
This enables dot-syntax access, like eth.get_block('latest').number in addition to eth.
get_block('latest')['number'].
Note: Accessing a property via attribute breaks type hinting. For this reason, this feature is available as a
middleware, which may be removed if desired.
web3.middleware.name_to_address_middleware()
web3.middleware.async_name_to_address_middleware()
This middleware converts Ethereum Name Service (ENS) names into the address that the name points to. For
example w3.eth.send_transaction will accept .eth names in the ‘from’ and ‘to’ fields.
Note: This middleware only converts ENS names on chains where the proper ENS contracts are deployed to
support this functionality. All other cases will result in a NameNotFound error.
web3.middleware.gas_price_strategy_middleware()
web3.middleware.async_gas_price_strategy_middleware()
Warning: Gas price strategy is only supported for legacy transactions. The London fork introduced
maxFeePerGas and maxPriorityFeePerGas transaction parameters which should be used over gasPrice
whenever possible.
This adds a gasPrice to transactions if applicable and when a gas price strategy has been set. See Gas Price
API for information about how gas price is derived.
web3.middleware.buffered_gas_estimate_middleware()
web3.middleware.async_buffered_gas_estimate_middleware()
This adds a gas estimate to transactions if gas is not present in the transaction parameters. Sets gas to: min(w3.
eth.estimate_gas + gas_buffer, gas_limit) where the gas_buffer default is 100,000
HTTPRequestRetry
web3.middleware.http_retry_request_middleware()
web3.middleware.async_http_retry_request_middleware()
This middleware is a default specifically for HTTPProvider that retries failed requests that return the follow-
ing errors: ConnectionError, HTTPError, Timeout, TooManyRedirects. Additionally there is a whitelist
that only allows certain methods to be retried in order to not resend transactions, excluded methods are:
eth_sendTransaction, personal_signAndSendTransaction, personal_sendTransaction.
Validation
web3.middleware.validation_middleware()
web3.middleware.async_validation_middleware()
This middleware includes block and transaction validators which perform validations for transaction parameters.
Middleware can be added, removed, replaced, and cleared at runtime. To make that easier, you can name the middleware
for later reference. Alternatively, you can use a reference to the middleware itself.
Middleware Order
Think of the middleware as being layered in an onion, where you initiate a web3.py request at the outermost layer of the
onion, and the Ethereum node (like geth) receives and responds to the request inside the innermost layer of the onion.
Here is a (simplified) diagram:
|
|
v
`````Layer 2``````
``````` ```````
````` | ````
```` v ````
``` ```
`. ````````Layer 1``````` `.`
`` ```` ````` .`
`. ``` | ``` `.`
.` ``` v ``` `.
`. `.` ``` .`
`` .` `Layer 0` `` .`
`` `. ````` `````` . .`
`. `` ``` | ``` .` .
. `` `.` | `` . .
. `. `` JSON-RPC call .` . .`
. . `` | . `` .
`` . . v . . .
. .` . . . ``
. . . Ethereum node .` . .
. . . . . .
. `` `. | . . .
. . .` | .` . .
`. .` .` Response .` .` .
. . `.` | `.` `. .
`. . ``` | ```` `. .
. `. ````` v ```` `. ``
. .` ```Layer 0`` `` `.
. `. `.` `.
. `. | `.` `.
.` ``` | ``` .`
`. ``` v ```` `.`
`` `````` ````` .`
`` `````Layer 1````` `.`
``` ```
```` | ```
````` v ````
`````` `````
`````````Layer 2``````````
|
v
(continues on next page)
The middlewares are maintained in Web3.middleware_onion. See below for the API.
When specifying middlewares in a list, or retrieving the list of middlewares, they will be returned in the order of outer-
most layer first and innermost layer last. In the above example, that means that w3.middleware_onion.middlewares
would return the middlewares in the order of: [2, 1, 0].
See “Internals: Middlewares” for a deeper dive to how middlewares work.
>>> w3 = Web3(...)
>>> w3.middleware_onion.add(web3.middleware.gas_price_strategy_middleware)
# or
>>> w3.middleware_onion.add(web3.middleware.gas_price_strategy_middleware, 'gas_
˓→price_strategy')
# or
>>> async_w3 = AsyncWeb3(...)
>>> async_w3.middleware_onion.add(web3.middleware.async_gas_price_strategy_
˓→middleware, 'gas_price_strategy')
# Either of these will put the gas_price_strategy middleware at the innermost layer
>>> w3 = Web3(...)
>>> w3.middleware_onion.inject(web3.middleware.gas_price_strategy_middleware,␣
˓→layer=0)
# or
>>> w3.middleware_onion.inject(web3.middleware.gas_price_strategy_middleware, 'gas_
˓→price_strategy', layer=0)
# or
>>> async_w3 = AsyncWeb3(...)
>>> async_w3.middleware_onion.inject(web3.middleware.async_gas_price_strategy_
˓→middleware, 'gas_price_strategy', layer=0)
Web3.middleware_onion.remove(middleware)
Middleware will be removed from whatever layer it was in. If you added the middleware with a name, use the
name to remove it. If you added the middleware as an object, use the object again later to remove it:
>>> w3 = Web3(...)
>>> w3.middleware_onion.remove(web3.middleware.gas_price_strategy_middleware)
(continues on next page)
Web3.middleware_onion.replace(old_middleware, new_middleware)
Middleware will be replaced from whatever layer it was in. If the middleware was named, it will continue to
have the same name. If it was un-named, then you will now reference it with the new middleware object.
Web3.middleware_onion.clear()
Empty all the middlewares, including the default ones.
>>> w3 = Web3(...)
>>> w3.middleware_onion.clear()
>>> assert len(w3.middleware_onion) == 0
Web3.middleware_onion.middlewares
Return all the current middlewares for the Web3 instance in the appropriate order for importing into a new Web3
instance.
Web3 ships with non-default middleware, for your custom use. In addition to the other ways of Configuring Middleware,
you can specify a list of middleware when initializing Web3, with:
Web3(middlewares=[my_middleware1, my_middleware2])
Warning: This will replace the default middlewares. To keep the default functionality, either use
middleware_onion.add() from above, or add the default middlewares to your list of new middlewares.
Stalecheck
web3.middleware.make_stalecheck_middleware(allowable_delay)
web3.middleware.async_make_stalecheck_middleware(allowable_delay)
This middleware checks how stale the blockchain is, and interrupts calls with a failure if the blockchain is too
old.
• allowable_delay is the length in seconds that the blockchain is allowed to be behind of time.time()
Because this middleware takes an argument, you must create the middleware with a method call.
two_day_stalecheck = make_stalecheck_middleware(60 * 60 * 24 * 2)
web3.middleware_onion.add(two_day_stalecheck)
If the latest block in the blockchain is older than 2 days in this example, then the middleware will raise a
StaleBlockchain exception on every call except web3.eth.get_block().
Cache
web3.middleware.construct_time_based_cache_middleware(cache_class, cache_expire_seconds,
rpc_whitelist, should_cache_fn)
The time-based cache constructor method accepts the following arguments:
Parameters
• cache_class – Must be a callable which returns an object which implements the dictionary
API.
• rpc_whitelist – Must be an iterable, preferably a set, of the RPC methods that may be
cached. A default list is used if none is provided.
• should_cache_fn – Must be a callable with the signature fn(method, params,
response) which returns whether the response should be cached.
Warning: The cache_class argument is slated to change to the cache argument with web3.utils.
caching.SimpleCache instance in web3.py v7, as is the current state of the simple cache middleware above.
Constructs a middleware which will cache the return values for any RPC method in the rpc_whitelist for an
amount of time defined by cache_expire_seconds.
• cache_expire_seconds should be the number of seconds a value may remain in the cache before being
evicted.
A ready to use version of this middleware can be found at web3.middleware.
time_based_cache_middleware.
web3.middleware.construct_latest_block_based_cache_middleware(cache_class,
average_block_time_sample_size,
default_average_block_time,
rpc_whitelist, should_cache_fn)
The latest-block-based cache constructor method accepts the following arguments:
Parameters
• cache_class – Must be a callable which returns an object which implements the dictionary
API.
• rpc_whitelist – Must be an iterable, preferably a set, of the RPC methods that may be
cached. A default list is used if none is provided.
• should_cache_fn – Must be a callable with the signature fn(method, params,
response) which returns whether the response should be cached.
Warning: The cache_class argument is slated to change to the cache argument with web3.utils.
caching.SimpleCache instance in web3.py v7, as is the current state of the simple cache middleware above.
Constructs a middleware which will cache the return values for any RPC method in the rpc_whitelist for the
latest block. It avoids re-fetching the current latest block for each request by tracking the current average block
time and only requesting a new block when the last seen latest block is older than the average block time.
• average_block_time_sample_size The number of blocks which should be sampled to determine the
average block time.
• default_average_block_time The initial average block time value to use for cases where there is not
enough chain history to determine the average block time.
A ready to use version of this middleware can be found at web3.middleware.
latest_block_based_cache_middleware.
Proof of Authority
web3.middleware.geth_poa_middleware()
web3.middleware.async_geth_poa_middleware()
Note: It’s important to inject the middleware at the 0th layer of the middleware onion: w3.middleware_onion.
inject(geth_poa_middleware, layer=0)
The geth_poa_middleware is required to connect to geth --dev or the Goerli public network. It may also be needed
for other EVM compatible blockchains like Polygon or BNB Chain (Binance Smart Chain).
If the middleware is not injected at the 0th layer of the middleware onion, you may get errors like the example below
when interacting with your EVM node.
The easiest way to connect to a default geth --dev instance which loads the middleware is:
This example connects to a local geth --dev instance on Linux with a unique IPC location and loads the middleware:
# connect to the IPC location started with 'geth --dev --datadir ~/mynode'
>>> w3 = Web3(IPCProvider('~/mynode/geth.ipc'))
# inject the poa compatibility middleware to the innermost layer (0th layer)
>>> w3.middleware_onion.inject(geth_poa_middleware, layer=0)
There is no strong community consensus on a single Proof-of-Authority (PoA) standard yet. Some nodes have suc-
cessful experiments running though. One is go-ethereum (geth), which uses a prototype PoA for its development mode
and the Goerli test network.
Unfortunately, it does deviate from the yellow paper specification, which constrains the extraData field in each block
to a maximum of 32-bytes. Geth’s PoA uses more than 32 bytes, so this middleware modifies the block data a bit before
returning it.
web3.middleware.local_filter_middleware()
web3.middleware.async_local_filter_middleware()
This middleware provides an alternative to ethereum node managed filters. When used, Log and Block filter logic are
handled locally while using the same web3 filter api. Filter results are retrieved using JSON-RPC endpoints that don’t
rely on server state.
Signing
web3.middleware.construct_sign_and_send_raw_middleware(private_key_or_account)
web3.middleware.async_construct_sign_and_send_raw_middleware(private_key_or_account)
This middleware automatically captures transactions, signs them, and sends them as raw transactions. The from field
on the transaction, or w3.eth.default_account must be set to the address of the private key for this middleware to
have any effect.
• private_key_or_account A single private key or a tuple, list or set of private keys.
Keys can be in any of the following formats:
– An eth_account.LocalAccount object
– An eth_keys.PrivateKey object
– A raw private key as a hex string or byte string
Hosted nodes (like Infura or Alchemy) only support signed transactions. This often results in
send_raw_transaction being used repeatedly. Instead, we can automate this process with
construct_sign_and_send_raw_middleware(private_key_or_account).
>>> # use `eth_sendTransaction` to automatically sign and send the raw transaction
>>> w3.eth.send_transaction(tx_dict)
HexBytes('0x09511acf75918fd03de58141d2fd409af4fd6d3dce48eb3aa1656c8f3c2c5c21')
>>> # use `eth_sendTransaction` to automatically sign and send the raw transaction
>>> await async_w3.eth.send_transaction(tx_dict)
HexBytes('0x09511acf75918fd03de58141d2fd409af4fd6d3dce48eb3aa1656c8f3c2c5c21')
Now you can send a transaction from acct.address without having to build and sign each raw transaction.
When making use of this signing middleware, when sending dynamic fee transactions (recommended over legacy trans-
actions), the transaction type of 2 (or '0x2') is necessary. This is because transaction signing is validated based on
the transaction type parameter. This value defaults to '0x2' when maxFeePerGas and / or maxPriorityFeePerGas
are present as parameters in the transaction as these params imply a dynamic fee transaction. Since these values effec-
tively replace the legacy gasPrice value, do not set a gasPrice for dynamic fee transactions. Doing so will lead to
validation issues.
A legacy transaction still works in the same way as it did before EIP-1559 was introduced:
>>> legacy_transaction = {
... 'to': receiving_account_address,
... 'value': 22,
... 'gasPrice': 123456, # optional - if not provided, gas_price_strategy (if␣
˓→exists) or eth_gasPrice is used
... }
>>> w3.eth.send_transaction(legacy_transaction)
Warning: This section of the documentation is for advanced users. You should probably stay away from these
APIs if you don’t know what you are doing.
The Web3 library has multiple layers of abstraction between the public api exposed by the web3 object and the backend
or node that web3 is connecting to.
• Providers are responsible for the actual communication with the blockchain such as sending JSON-RPC requests
over HTTP or an IPC socket.
• Middlewares provide hooks for monitoring and modifying requests and responses to and from the provider.
These can be global operating on all providers or specific to one provider.
• Managers provide thread safety and primitives to allow for asynchronous usage of web3.
Here are some common things you might want to do with these APIs.
• Redirect certain RPC requests to different providers such as sending all read operations to a provider backed by
Infura and all write operations to a go-ethereum node that you control.
• Transparently intercept transactions sent over eth_sendTransaction, sign them locally, and then send them
through eth_sendRawTransaction.
• Modify the response from an RPC request so that it is returned in different format such as converting all integer
values to their hexadecimal representation.
• Validate the inputs to RPC requests
Each web3 RPC call passes through these layers in the following manner.
*********** ************
| Request | | Response |
*********** ************
| ^
v |
+-----------------------------+
| Manager |
+-----------------------------+
| ^
v |
(continues on next page)
You can visualize this relationship like an onion, with the Provider at the center. The request originates from the
Manager, outside of the onion, passing down through each layer of the onion until it reaches the Provider at the center.
The Provider then handles the request, producing a response which will then pass back out from the center of the onion,
through each layer until it is finally returned by the Manager.
2.12.2 Providers
A provider is responsible for all direct blockchain interactions. In most cases this means interacting with the JSON-
RPC server for an ethereum node over HTTP or an IPC socket. There is however nothing which requires providers to
be RPC based, allowing for providers designed for testing purposes which use an in-memory EVM to fulfill requests.
Writing your own provider requires implementing two required methods as well as setting the middlewares the provider
should use.
BaseProvider.make_request(method, params)
Each provider class must implement this method. This method should return a JSON object with either a
'result' key in the case of success, or an 'error' key in the case of failure.
• method This will be a string representing the JSON-RPC method that is being called such as
'eth_sendTransaction'.
• params This will be a list or other iterable of the parameters for the JSON-RPC method being called.
BaseProvider.is_connected(show_traceback=False)
This function should return True or False depending on whether the provider should be considered connected.
For example, an IPC socket based provider should return True if the socket is open and False if the socket is
closed.
If set to True, the optional show_traceback boolean will raise a ProviderConnectionError and provide
information on why the provider should not be considered connected.
BaseProvider.middlewares
This should be an iterable of middlewares.
You can set a new list of middlewares by assigning to provider.middlewares, with the first middleware that processes
the request at the beginning of the list.
2.12.3 Middlewares
Note: The Middleware API in web3 borrows heavily from the Django middleware API introduced in version 1.10.0
Middlewares provide a simple yet powerful api for implementing layers of business logic for web3 requests. Writing
middleware is simple.
# do post-processing here
class SimpleMiddleware:
def __init__(self, make_request, w3):
self.w3 = w3
self.make_request = make_request
# do post-processing here
The make_request parameter is a callable which takes two positional arguments, method and params which corre-
spond to the RPC method that is being called. There is no requirement that the make_request function be called. For
example, if you were writing a middleware which cached responses for certain methods your middleware would likely
not call the make_request method, but instead get the response from some local cache.
The RequestManager object exposes the middleware_onion object to manage middlewares. It is also exposed on
the Web3 object for convenience. That API is detailed in Configuring Middleware.
2.12.4 Managers
The Manager acts as a gatekeeper for the request/response lifecycle. It is unlikely that you will need to change the
Manager as most functionality can be implemented in the Middleware layer.
class web3.providers.websocket.request_processor.RequestProcessor
The RequestProcessor class is responsible for the storing and syncing up of asynchronous requests to responses for a
PersistentConnectionProvider. The best example of one such provider is the WebsocketProviderV2. In order
to send a websocket message and receive a response to that particular request, PersistentConnectionProvider
instances have to match request id values to response id values coming back from the websocket connec-
tion. Any provider that does not adhere to the JSON-RPC 2.0 specification in this way will not work with
PersistentConnectionProvider instances. The specifics of how the request processor handles this are outlined
below.
Implementations of the PersistentConnectionProvider class have a message listener background task that is
called when the websocket connection is established. This task is responsible for listening for any and all mes-
sages coming in over the websocket connection and storing them in the RequestProcessor instance internal to the
PersistentConnectionProvider instance. The RequestProcessor instance is responsible for storing the mes-
sages in the correct cache, either the one-to-one cache or the one-to-many (subscriptions) queue, depending on whether
the message has a JSON-RPC id value or not.
One-To-One Requests
One-to-one requests can be summarized as any request that expects only one response back. An example is using the
eth module API to request the latest block number.
>>> asyncio.run(wsV2_one_to_one_example())
With websockets we have to call send() and asynchronously receive responses via another means, gener-
ally by calling recv() or by iterating on the websocket connection for messages. As outlined above, the
PersistentConnectionProvider class has a message listener background task that handles the receiving of mes-
sages.
Due to this asynchronous nature of sending and receiving, in order to make one-to-one request-to-response calls work,
we have to save the request information somewhere so that, when the response is received, we can match it to the
original request that was made (i.e. the request with a matching id to the response that was received). The stored
request information is then used to process the response when it is received, piping it through the response formatters
and middlewares internal to the web3.py library.
In order to store the request information, the RequestProcessor class has an internal RequestInformation cache.
The RequestInformation class saves important information about a request.
class web3._utils.caching.RequestInformation
method
The name of the method - e.g. “eth_subscribe”.
params
The params used when the call was made - e.g. (“newPendingTransactions”, True).
response_formatters
The formatters that will be used to process the response.
middleware_response_processors
Any middleware that processes responses that is present on the instance at the time of the request is appended
here, in order, so the response may be piped through that logic when it comes in.
subscription_id
If the request is an eth_subscribe request, rather than popping this information from the cache when
the response to the subscription call comes in (i.e. the subscription id), we save the subscription id with
the request information so that we can correctly process all subscription messages that come in with that
subscription id. For one-to-one request-to-response calls, this value is always None.
One-to-one responses, those that include a JSON-RPC id in the response object, are stored in an internal SimpleCache
class, isolated from any one-to-many responses. When the PersistentConnectionProvider is looking for a re-
sponse internally, it will expect the message listener task to store the response in this cache. Since the request id is used
in the cache key generation, it will then look for a cache key that matches the response id with that of the request id. If
the cache key is found, the response is processed and returned to the user. If the cache key is not found, the operation
will time out and raise a TimeExhausted exception. This timeout can be configured by the user when instantiating the
PersistentConnectionProvider instance via the response_timeout keyword argument.
One-To-Many Requests
One-to-many requests can be summarized by any request that expects many responses as a result of the initial request.
The only current example is the eth_subscribe request. The initial eth_subscribe request expects only one re-
sponse, the subscription id value, but it also expects to receive many eth_subscription messages if and when the
request is successful. For this reason, the original request is considered a one-to-one request so that a subscription id can
be returned to the user on the same line, but the process_subscriptions() method on the WebsocketConnection
class, the public API for interacting with the active websocket connection, is set up to receive eth_subscription
responses over an asynchronous interator pattern.
>>> asyncio.run(ws_v2_subscription_example())
One-to-many responses, those that do not include a JSON-RPC id in the response object, are stored in an internal
asyncio.Queue instance, isolated from any one-to-one responses. When the PersistentConnectionProvider is
looking for one-to-many responses internally, it will expect the message listener task to store these messages in this
queue. Since the order of the messages is important, the queue is a FIFO queue. The process_subscriptions()
method on the WebsocketConnection class is set up to pop messages from this queue as FIFO over an asynchronous
iterator pattern.
If the stream of messages from the websocket is not being interrupted by any other tasks, the queue will generally be in
sync with the messages coming in over the websocket. That is, the message listener will put a message in the queue and
the process_subscriptions() method will pop that message from the queue and yield control of the loop back to
the listener. This will continue until the websocket connection is closed or the user unsubscribes from the subscription.
If the stream of messages lags a bit, or the provider is not consuming messages but has subscribed to a subscription,
this internal queue may fill up with messages until it reaches its max size and then trigger a waiting asyncio.Event
until the provider begins consuming messages from the queue again. For this reason, it’s important to begin consuming
messages from the queue, via the process_subscriptions() method, as soon as a subscription is made.
2.13 ethPM
Warning: The ethPM module is no longer being maintained and will be deprecated with web3.py version 7.
2.13.1 Overview
This is a Python implementation of the Ethereum Smart Contract Packaging Specification V3, driven by discussions
in ERC 190, ERC 1123, ERC 1319.
Py-EthPM is being built as a low-level library to help developers leverage the ethPM spec. Including . . .
• Parse and validate packages.
• Construct and publish new packages.
• Provide access to contract factory classes.
• Provide access to all of a package’s deployments.
• Validate package bytecode matches compilation output.
• Validate deployed bytecode matches compilation output.
• Access to package’s dependencies.
• Native integration with compilation metadata.
2.13.2 Package
The Package object will function much like the Contract class provided by web3. Rather than instantiating the
base class provided by ethpm, you will instead use a classmethod which generates a new Package class for a given
package.
Package objects must be instantiated with a valid web3 object.
>>> w3 = Web3(Web3.EthereumTesterProvider())
>>> ethpm_spec_dir = get_ethpm_spec_dir()
>>> owned_manifest_path = ethpm_spec_dir / 'examples' / 'owned' / 'v3.json'
>>> OwnedPackage = Package.from_file(owned_manifest_path, w3)
>>> assert isinstance(OwnedPackage, Package)
For a closer look at how to interact with EthPM packages using web3, check out the examples page.
Properties
__repr__() → str
String readable representation of the Package.
>>> OwnedPackage.__repr__()
'<Package owned==1.0.0>'
>>> OwnedPackage.name
'owned'
>>> OwnedPackage.version
'1.0.0'
>>> OwnedPackage.manifest_version
'ethpm/3'
build_dependencies
Return Dependencies instance containing the build dependencies available on this Package.
The Package class should provide access to the full dependency tree.
>>> owned_package.build_dependencies['zeppelin']
<ZeppelinPackage>
deployments
Returns a Deployments object containing all the deployment data and contract instances of a Package’s
contract_types. Automatically filters deployments to only expose those available on the current Package.
w3 instance.
package.deployments.get_instance("ContractType")
Package.w3
The Web3 instance currently set on this Package. The deployments available on a package are automatically
filtered to only contain those belonging to the currently set w3 instance.
Package.manifest
The manifest dict used to instantiate a Package.
Methods
OwnedPackage = Package.from_uri('ipfs://
˓→QmbeVyFLSuEUxiXKwSsEjef7icpdTdA4kGG9BcrJXKNKUW', w3) # noqa: E501
Owned = OwnedPackage.get_contract_factory('owned')
In cases where a contract uses a library, the contract factory will have unlinked bytecode. The ethpm pack-
age ships with its own subclass of web3.contract.Contract, ethpm.contract.LinkableContract
with a few extra methods and properties related to bytecode linking.
Validation
2.13.3 LinkableContract
Py-EthPM uses a custom subclass of Web3.contract.Contract to manage contract factories and instances
which might require bytecode linking. To create a deployable contract factory, both the contract type’s abi and
deploymentBytecode must be available in the Package’s manifest.
>>> w3 = Web3(Web3.EthereumTesterProvider())
>>> escrow_manifest_path = ASSETS_DIR / 'escrow' / 'with_bytecode_v3.json'
Properties
LinkableContract.unlinked_references
A list of link reference data for the deployment bytecode, if present in the manifest data used to generate a
LinkableContract factory. Deployment bytecode link reference data must be present in a manifest in order to
generate a factory for a contract which requires bytecode linking.
LinkableContract.linked_references
A list of link reference data for the runtime bytecode, if present in the manifest data used to generate a
LinkableContract factory. If you want to use the web3 Deployer tool for a contract, then runtime bytecode
link reference data must be present in a manifest.
LinkableContract.needs_bytecode_linking
A boolean attribute used to indicate whether a contract factory has unresolved link references, which must be
resolved before a new contract instance can be deployed or instantiated at a given address.
Methods
classmethod LinkableContract.link_bytecode(attr_dict)
This method returns a newly created contract factory with the applied link references defined in the attr_dict.
This method expects attr_dict to be of the type Dict[`contract_name`: `address`] for all link refer-
ences that are unlinked.
BaseURIBackend
Py-EthPM uses the BaseURIBackend as the parent class for all of its URI backends. To write your own backend, it
must implement the following methods.
BaseURIBackend.can_resolve_uri(uri)
Return a bool indicating whether or not this backend is capable of resolving the given URI to a manifest. A
content-addressed URI pointing to valid manifest is said to be capable of “resolving”.
BaseURIBackend.can_translate_uri(uri)
Return a bool indicating whether this backend class can translate the given URI to a corresponding content-
addressed URI. A registry URI is said to be capable of “translating” if it points to another content-addressed
URI in its respective on-chain registry.
BaseURIBackend.fetch_uri_contents(uri)
Fetch the contents stored at the provided uri, if an available backend is capable of resolving the URI. Validates
that contents stored at uri match the content hash suffixing the uri.
IPFS
Py-EthPM has multiple backends available to fetch/pin files to IPFS. The IPFS backends rely on the now-unmaintained
ipfshttpclient library. Because of this, they are opt-in and may be installed via the ipfs web3 install extra.
The desired backend can be set via the environment variable: ETHPM_IPFS_BACKEND_CLASS.
• InfuraIPFSBackend (default)
– https://ipfs.infura.io
• IPFSGatewayBackend (temporarily deprecated)
– https://ipfs.io/ipfs/
• LocalIPFSBacked
– Connect to a local IPFS API gateway running on port 5001.
• DummyIPFSBackend
– Won’t pin/fetch files to an actual IPFS node, but mocks out this behavior.
BaseIPFSBackend.pin_assets(file_or_directory_path)
Pin asset(s) found at the given path and returns the pinned asset data.
HTTPS
https://api.github.com/repos/:owner/:repo/git/blobs/:file_sha
create_content_addressed_github_uri(uri)
This util function will return a content-addressed URI, as defined by Github’s blob scheme. To generate a content-
addressed URI for any manifest stored on github, this function requires accepts a Github API uri that follows the
following scheme.
https://api.github.com/repos/:owner/:repo/contents/:path/:to/manifest.json
Registry URIs
The URI to lookup a package from a registry should follow the following format. (subject to change as the Registry
Contract Standard makes its way through the EIP process)
scheme://address:chain_id/package_name@version
2.13.5 Builder
The manifest Builder is a tool designed to help construct custom manifests. The builder is still under active development,
and can only handle simple use-cases for now.
build(
{},
package_name(str),
version(str),
manifest_version(str), ...,
)
# Or
build(
init_manifest(package_name: str, version: str, manifest_version: str="ethpm/3")
...,
)
The builder (i.e. build()) expects a dict as the first argument. This dict can be empty, or populated if you want to
extend an existing manifest.
>>> expected_manifest = {
... "name": "owned",
... "version": "1.0.0",
... "manifest": "ethpm/3"
... }
>>> base_manifest = {"name": "owned"}
>>> built_manifest = build(
... {},
... package_name("owned"),
... manifest_version("ethpm/3"),
... version("1.0.0"),
... )
>>> extended_manifest = build(
... base_manifest,
... manifest_version("ethpm/3"),
... version("1.0.0"),
... )
>>> assert built_manifest == expected_manifest
>>> assert extended_manifest == expected_manifest
With init_manifest(), which populates “manifest” with “ethpm/3” (the only supported EthPM specification ver-
sion), unless provided with an alternative “version”.
>>> build(
... init_manifest("owned", "1.0.0"),
... )
{'name': 'owned', 'version': '1.0.0', 'manifest': 'ethpm/3'}
To return a Package
build(
...,
as_package(w3: Web3),
)
By default, the manifest builder returns a dict representing the manifest. To return a Package instance (instantiated
with the generated manifest) from the builder, add the as_package() builder function with a valid web3 instance to
the end of the builder.
>>> w3 = Web3(Web3.EthereumTesterProvider())
>>> built_package = build(
... {},
... package_name("owned"),
... manifest_version("ethpm/3"),
(continues on next page)
To validate a manifest
build(
...,
validate(),
)
By default, the manifest builder does not perform any validation that the generated fields are correctly
formatted. There are two ways to validate that the built manifest conforms to the EthPM V3 Specification.
• Return a Package, which automatically runs validation.
• Add the validate() function to the end of the manifest builder.
build(
...,
write_to_disk(
manifest_root_dir: Optional[Path],
manifest_name: Optional[str],
prettify: Optional[bool],
),
)
Writes the active manifest to disk. Will not overwrite an existing manifest with the same name and root directory.
Defaults - Writes manifest to current working directory (as returned by os.getcwd()) unless a Path is provided as
manifest_root_dir. - Writes manifest with a filename of <version>.json unless desired manifest name (which must
end in “.json”) is provided as manifest_name. - Writes the minified manifest version to disk unless prettify is set to
True
build(
...,
pin_to_ipfs(
backend: BaseIPFSBackend,
prettify: Optional[bool],
),
)
Pins the active manifest to disk. Must be the concluding function in a builder set since it returns the IPFS pin data
rather than returning the manifest for further processing.
build(
...,
description(str),
license(str),
authors(*args: str),
keywords(*args: str),
links(*kwargs: str),
...,
)
... )
>>> assert expected_manifest == built_manifest
Compiler Output
To build a more complex manifest for solidity contracts, it is required that you provide standard-json output from the
solidity compiler. Or for a more convenient experience, use the EthPM CLI.
Here is an example of how to compile the contracts and generate the standard-json output. More information can be
found in the Solidity Compiler docs.
Sample standard-json-input.json
{
"language": "Solidity",
"sources": {
"Contract.sol": {
"urls": ["<path-to-contract>"]
}
},
"settings": {
"outputSelection": {
"*": {
"*": ["abi", "evm.bytecode.object"]
(continues on next page)
The compiler_output as used in the following examples is the entire value of the contracts key of the solc output,
which contains compilation data for all compiled contracts.
To add a source
# To inline a source
build(
...,
inline_source(
contract_name: str,
compiler_output: Dict[str, Any],
package_root_dir: Optional[Path]
),
...,
)
# To pin a source
build(
...,
pin_source(
contract_name: str,
compiler_output: Dict[str, Any],
ipfs_backend: BaseIPFSBackend,
package_root_dir: Optional[Path]
),
...,
)
Note: output_v3.json below is expected to be the standard-json output generated by the solidity compiler as
described here. The output must contain the abi and bytecode objects from compilation.
To include the source as a content-addressed URI, Py-EthPM can pin your source via the Infura IPFS API. As well
as the contract name and compiler output, this function requires that you provide the desired IPFS backend to pin the
contract sources.
build(
...,
contract_type(
contract_name: str,
compiler_output: Dict[str, Any],
alias: Optional[str],
abi: Optional[bool],
compiler: Optional[bool],
contract_type: Optional[bool],
deployment_bytecode: Optional[bool],
devdoc: Optional[bool],
userdoc: Optional[bool],
source_id: Optional[bool],
runtime_bytecode: Optional[bool]
),
...,
)
The default behavior of the manifest builder’s contract_type() function is to populate the manifest with all of the
contract type data found in the compiler_output.
>>> expected_manifest = {
... 'name': 'owned',
... 'manifest': 'ethpm/3',
... 'version': '1.0.0',
... 'compilers': [
... {'name': 'solc', 'version': '0.6.8+commit.0bbfe453', 'settings': {'optimize':␣
˓→True}, 'contractTypes': ['Owned']}
... ],
... 'contractTypes': {
... 'Owned': {
(continues on next page)
... 'deploymentBytecode': {
... 'bytecode':
˓→'0x6080604052348015600f57600080fd5b50600080546001600160a01b03191633179055603f80602f6000396000f3fe60806
˓→'
... },
... 'sourceId': 'Owned.sol',
... 'devdoc': {'methods': {}},
... 'userdoc': {'methods': {}}
... }
... }
... }
>>> built_manifest = build(
... BASE_MANIFEST,
... contract_type("Owned", compiler_output)
... )
>>> assert expected_manifest == built_manifest
To select only certain contract type data to be included in your manifest, provide the desired fields as True
keyword arguments. The following fields can be specified for inclusion in the manifest . . .
• abi
• compiler
• deployment_bytecode
• runtime_bytecode
• devdoc
• userdoc
• source_id
>>> expected_manifest = {
... 'name': 'owned',
... 'manifest': 'ethpm/3',
... 'version': '1.0.0',
... 'contractTypes': {
... 'Owned': {
... 'abi': [{'inputs': [], 'stateMutability': 'nonpayable', 'type': 'constructor'}
˓→],
... }
... }
... }
>>> built_manifest = build(
... BASE_MANIFEST,
... contract_type("Owned", compiler_output, abi=True)
... )
>>> assert expected_manifest == built_manifest
If you would like to alias your contract type, provide the desired alias as a kwarg. This will automatically include
the original contract type in a contractType field. Unless specific contract type fields are provided as kwargs,
contractType will still default to including all available contract type data found in the compiler output.
>>> expected_manifest = {
... 'name': 'owned',
... 'manifest': 'ethpm/3',
... 'version': '1.0.0',
... 'contractTypes': {
... 'OwnedAlias': {
... 'abi': [{'inputs': [], 'stateMutability': 'nonpayable', 'type': 'constructor'}
˓→],
To add a deployment
build(
...,
deployment(
block_uri,
contract_instance,
contract_type,
address,
transaction=None,
block=None,
deployment_bytecode=None,
runtime_bytecode=None,
compiler=None,
),
...,
)
This is the simplest builder function for adding a deployment to a manifest. All arguments require keywords. This
builder function requires a valid block_uri, it’s up to the user to be sure that multiple chain URIs representing the
same blockchain are not included in the “deployments” object keys.
runtime_bytecode, deployment_bytecode and compiler must all be validly formatted dicts according to the
EthPM Spec. If your contract has link dependencies, be sure to include them in the bytecode objects.
>>> expected_manifest = {
... 'name': 'owned',
... 'manifest': 'ethpm/3',
... 'version': '1.0.0',
... 'deployments': {
(continues on next page)
... 'Owned': {
... 'contractType': 'Owned',
... 'address': '0x582AC4D8929f58c217d4a52aDD361AE470a8a4cD',
... }
... }
... }
... }
>>> built_manifest = build(
... BASE_MANIFEST,
... deployment(
... block_uri='blockchain://
˓→1234567890123456789012345678901234567890123456789012345678901234/block/
˓→1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
... contract_instance='Owned',
... contract_type='Owned',
... address='0x582AC4D8929f58c217d4a52aDD361AE470a8a4cD',
... ),
... )
>>> assert expected_manifest == built_manifest
This builder function simplifies adding the same contract type deployment across multiple chains. It requires both
a contract_instance and contract_type argument (in many cases these are the same, though contract_type
must always match its correspondent in the manifest’s “contract_types”) and all arguments require keywords.
runtime_bytecode, deployment_bytecode and compiler must all be validly formatted dicts according to the
EthPM Spec. If your contract has link dependencies, be sure to include them in the bytecode objects.
˓→"
},
runtime_bytecode = {
"bytecode":
˓→"0x6080604052600436106100775763ffffffff7c0100000000000000000000000000000000000000000000000000000000600
˓→"
},
compiler = {
"name": "solc",
"version": "0.4.24+commit.e67f0147.Emscripten.clang",
"settings": {
"optimize": True
}
}
(continues on next page)
˓→1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
address=owned_testnet_address,
),
owned_type(
block_uri='blockchain://
˓→1234567890123456789012345678901234567890123456789012345678901234/block/
˓→1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
address=owned_mainnet_address,
transaction=owned_mainnet_transaction,
block=owned_mainnet_block,
),
escrow_type(
block_uri='blockchain://
˓→abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd/block/
˓→1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
address=escrow_testnet_address,
),
escrow_type(
block_uri='blockchain://
˓→1234567890123456789012345678901234567890123456789012345678901234/block/
˓→1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
address=escrow_mainnet_address,
transaction=escrow_mainnet_transaction,
),
)
build(
...,
build_dependency(
package_name,
uri,
),
...,
)
build_dependency(package_name, uri)
To add a build dependency to your manifest, just provide the package’s name and a supported, content-addressed URI.
>>> expected_manifest = {
... 'name': 'owned',
(continues on next page)
... )
>>> assert expected_manifest == built_manifest
2.13.6 Checker
The manifest Checker is a tool designed to help validate manifests according to the natural language spec (link).
To validate a manifest
˓→"Manifest does not contain any 'contractTypes'. Packages should only include contract␣
˓→types that can be found in the source files for this package. Packages should not␣
˓→include contract types from dependencies. Packages should not include abstract␣
The Ethereum Name Service (ENS) is analogous to the Domain Name Service. It enables users and developers to use
human-friendly names in place of error-prone hexadecimal addresses, content hashes, and more.
The ens module is included with web3.py. It provides an interface to look up domains and addresses, add resolver
records, or get and set metadata.
Note: web3.py v6.6.0 introduced ENS name normalization standard ENSIP-15. This update to ENS name validation
and normalization won’t affect ~99% of names but may prevent invalid names from being created and from interacting
with the ENS contracts via web3.py. We feel strongly that this change, though breaking, is in the best interest of our
users as it ensures compatibility with the latest ENS standards.
2.14.1 Setup
# automatic detection
from ens.auto import ns
provider = IPCProvider(...)
ns = ENS(provider)
# It also inherits the provider and codec from the w3 instance, as well as the ``strict_
˓→bytes_type_checking`` flag value.
ns = AsyncENS(provider)
Note that an ens module instance is also available on the w3 instance. The first time it’s used, web3.py will create the
ens instance using ENS.from_web3(w3) or AsyncENS.from_web3(w3) as appropriate.
# instantiate w3 instance
from web3 import Web3, IPCProvider
w3 = Web3(IPCProvider(...))
ens.strict_bytes_type_checking
The ENS instance has a strict_bytes_type_checking flag that toggles the flag with the same name on the
Web3 instance attached to the ENS instance. You may disable the stricter bytes type checking that is loaded by
default using this flag. For more examples, see Disabling Strict Checks for Bytes Types
If instantiating a standalone ENS instance using ENS.from_web3(), the ENS instance will inherit the value of
the flag on the Web3 instance at time of instantiation.
>>> ns = ENS.from_web3(w3)
>>> # assert inherited from w3 at time of instantiation via ENS.from_web3()
>>> assert ns.strict_bytes_type_checking is False
>>> ns.w3.is_encodable('bytes2', b'1')
True
However, if accessing the ENS class via the Web3 instance as a module (w3.ens), since all modules use the same
Web3 object reference under the hood (the parent w3 object), changing the strict_bytes_type_checking flag
value on w3 also changes the flag state for w3.ens.w3 and all modules.
2.14.2 Usage
Name Info
The ENS module has no opinion as to which TLD (Top Level Domain) you can use, but will not infer a TLD if it is
not provided with the name.
ENSIP-9 introduced multichain address resolution, allowing users to resolve addresses from different chains, specified
by the coin type index from SLIP44. The address() method on the ENS class supports multichain address resolution
via the coin_type keyword argument.
domain = ns.name('0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7')
# confirm that the name resolves back to the address that you looked up:
assert ns.address(domain) == '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7'
Note: For accuracy, and as a recommendation from the ENS documentation on reverse resolution, the ENS module
now verifies that the forward resolution matches the address with every call to get the name() for an address. This is the
only sure way to know whether the reverse resolution is correct. Anyone can claim any name, only forward resolution
implies that the owner of the name gave their stamp of approval.
eth_address = ns.owner('exchange.eth')
You can set up your name so that address() will show the address it points to. In order to do so, you must already be
the owner of the domain (or its parent).
ns.setup_address('ens.eth', '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7')
In the common case where you want to point the name to the owning address, you can skip the address.
ns.setup_address('ens.eth')
ns.setup_address('supreme.executive.power.derives.from.a.mandate.from.the.masses.ens.eth
˓→')
ENSIP-9 introduced multichain address resolution, allowing users to resolve addresses from different chains, specified
by the coin type index from SLIP44. The setup_address() method on the ENS class supports multichain address
setup via the coin_type keyword argument.
You can set up your address so that name() will show the name that points to it.
This is like Caller ID. It enables you and others to take an account and determine what name points to it. Sometimes
this is referred to as “reverse” resolution. The ENS Reverse Resolver is used for this functionality.
ns.setup_name('ens.eth', '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7')
If you don’t supply the address, setup_name() will assume you want the address returned by address().
ns.setup_name('ens.eth')
If the name doesn’t already point to an address, setup_name() will call setup_address() for you.
Wait for the transaction to be mined, then:
Text Records
As the owner of an ENS record, you can add text metadata. A list of supported fields can be found in the ENS docu-
mentation. You’ll need to setup the address first, and then the text can be set:
ns.setup_address('ens.eth', '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7')
ns.set_text('ens.eth', 'url', 'https://example.com')
If the transaction dictionary is not passed, sensible defaults will be used, and if a transaction dictionary is passed but
does not have a from value, the default will be the owner.
You can get the resolver for an ENS name via the resolver() method.
The ENS module supports Wildcard Resolution for resolvers that implement the ExtendedResolver interface as de-
scribed in ENSIP-10. Resolvers that implement the extended resolver interface should return True when calling the
supportsInterface() function with the extended resolver interface id "0x9061b923" and should resolve subdo-
mains to a unique address.
2.15 Examples
• Looking up blocks
• Getting the latest block
• Checking the balance of an account
• Converting currency denominations
• Sending transactions
• Looking up transactions
• Looking up receipts
• Working with Contracts
– Interacting with existing contracts
– Deploying new contracts
• Working with Contracts via ethPM
• Working with an ERC20 Token Contract
– Creating the contract factory
– Querying token metadata
– Query account balances
– Sending tokens
– Creating an approval for external transfers
– Performing an external transfer
• CCIP Read support for offchain lookup
• Contract Unit Tests in Python
• Using Infura Goerli Node
• Adjusting log levels
• Advanced example: Fetching all token transfer events
– eth_getLogs limitations
– Example code
Here are some common things you might want to do with web3.
Blocks can be looked up by either their number or hash using the web3.eth.get_block API. Block hashes should be
in their hexadecimal representation. Block numbers
˓→',
'miner': '0xad5C1768e5974C231b2148169da064e61910f31a',
'mixHash': '0x31d9ec7e3855aeba37fd92aa1639845e70b360a60f77f12eff530429ef8cfcba',
'nonce': '0x549f882c5f356f85',
'number': 12345,
'parentHash': '0x4b3c1d7e65a507b62734feca1ee9f27a5379e318bd52ae62de7ba67dbeac66a3',
'receiptsRoot': '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
'sealFields': ['0x31d9ec7e3855aeba37fd92aa1639845e70b360a60f77f12eff530429ef8cfcba',
'0x549f882c5f356f85'],
'sha3Uncles': '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
'size': 539,
'stateRoot': '0xca495e22ed6b88c61714d129dbc8c94f5bf966ac581c09a57c0a72d0e55e7286',
'timestamp': 1438367030,
'totalDifficulty': 3862140487204603,
'transactions': [],
'transactionsRoot':
˓→'0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
'uncles': [],
}
{...}
You can also retrieve the latest block using the string 'latest' in the web3.eth.get_block API.
>>> web3.eth.get_block('latest')
{...}
If you want to know the latest block number you can use the web3.eth.block_number property.
>>> web3.eth.block_number
4194803
To find the amount of ether owned by an account, use the get_balance() method. At the time of writing, the account
with the most ether has a public address of 0x742d35Cc6634C0532925a3b844Bc454e4438f44e.
>>> web3.eth.get_balance('0x742d35Cc6634C0532925a3b844Bc454e4438f44e')
3841357360894980500000001
Note that this number is not denominated in ether, but instead in the smallest unit of value in Ethereum, wei. Read on
to learn how to convert that number to ether.
Web3 can help you convert between denominations. The following denominations are supported.
Picking up from the previous example, the largest account contained 3841357360894980500000001 wei. You can use
the from_wei() method to convert that balance to ether (or another denomination).
To convert back to wei, you can use the inverse function, to_wei(). Note that Python’s default floating point precision
is insufficient for this use case, so it’s necessary to cast the value to a Decimal if it isn’t already.
Best practice: If you need to work with multiple currency denominations, default to wei. A typical workflow may
require a conversion from some denomination to wei, then from wei to whatever you need.
>>> web3.eth.get_transaction(
˓→'0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060')
{
'blockHash': '0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd',
'blockNumber': 46147,
'condition': None,
'creates': None,
'from': '0xA1E4380A3B1f749673E270229993eE55F35663b4',
'gas': 21000,
'gasPrice': None,
'hash': '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
'input': '0x',
'maxFeePerGas': 2000000000,
'maxPriorityFeePerGas': 1000000000,
'networkId': None,
'nonce': 0,
'publicKey':
˓→'0x376fc429acc35e610f75b14bc96242b13623833569a5bb3d72c17be7e51da0bb58e48e2462a59897cead8ab88e78709f9d2
˓→',
'r': '0x88ff6cf0fefd94db46111149ae4bfc179e9b94721fffd821d38d16464b3f71d0',
'raw':
˓→'0xf86780862d79883d2000825208945df9b87991262f6ba471f09758cde1c0fc1de734827a69801ca088ff6cf0fefd94db461
˓→',
's': '0x45e0aff800961cfce805daef7016b9b675c137a6a41a548f7b60a3484c06a33a',
'standardV': '0x1',
'to': '0x5DF9B87991262F6BA471F09758CDE1c0FC1De734',
'transactionIndex': 0,
'v': '0x1c',
(continues on next page)
If no transaction for the given hash can be found, this method will throw web3.exceptions.TransactionNotFound.
>>> web3.eth.get_transaction_receipt(
˓→'0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060')
{
'blockHash': '0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd',
'blockNumber': 46147,
'contractAddress': None,
'cumulativeGasUsed': 21000,
'gasUsed': 21000,
'logs': [],
'logsBloom':
˓→'0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
˓→',
'root': '0x96a8e009d2b88b1483e6941e6812e32263b05683fac202abc622a3e31aed1957',
'transactionHash':
˓→'0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
'transactionIndex': 0,
}
If no transaction for the given hash can be found, this method will throw web3.exceptions.TransactionNotFound.
In order to use an existing contract, you’ll need its deployed address and its ABI. Both can be found using block
explorers, like Etherscan. Once you instantiate a contract instance, you can read data and execute transactions.
# read state:
contract_instance.functions.storedValue().call()
# 42
# update state:
tx_hash = contract_instance.functions.updateValue(43).transact()
def compile_source_file(file_path):
with open(file_path, 'r') as f:
source = f.read()
return compile_source(source,output_values=['abi','bin'])
address = w3.eth.get_transaction_receipt(tx_hash)['contractAddress']
return address
w3 = Web3(EthereumTesterProvider(PyEVMBackend()))
(continues on next page)
contract_source_path = 'contract.sol'
compiled_sol = compile_source_file('contract.sol')
gas_estimate = store_var_contract.functions.setVar(255).estimate_gas()
print(f'Gas estimate to transact with setVar: {gas_estimate}')
Output:
'blockNumber': 2,
'contractAddress': None,
'cumulativeGasUsed': 43488,
'gasUsed': 43488,
'logs': [AttributeDict({'type': 'mined', 'logIndex': 0, 'transactionIndex': 0,
˓→'transactionHash': HexBytes(
˓→'0x50aa3ba0673243f1e60f546a12ab364fc2f6603b1654052ebec2b83d4524c6d0'), 'blockHash':␣
˓→HexBytes('0x837609ad0a404718c131ac5157373662944b778250a507783349d4e78bd8ac84'),
˓→'0x6c2b4666ba8da5a95717621d879a77de725f3d816709b9cbe9f059b8f875e284'), HexBytes(
˓→'0x00000000000000000000000000000000000000000000000000000000000000ff')]})],
'status': 1,
'transactionHash': HexBytes(
˓→'0x50aa3ba0673243f1e60f546a12ab364fc2f6603b1654052ebec2b83d4524c6d0'),
'transactionIndex': 0}
(continues on next page)
Warning: The ethPM module is no longer being maintained and will be deprecated with web3.py version 7.
ethPM packages contain configured contracts ready for use. Web3’s ethpm module (web3.pm) extends Web3’s native
Contract module, with a few modifications for how you instantiate Contract factories and instances.
All you need is the package name, version and ethPM registry address for the package you wish to use. An ethPM
registry is an on-chain datastore for the release data associated with an ethPM package. You can find some sample
registries to explore in the ethPM registry. Remember, you should only use packages from registries whose maintainer
you trust not to inject malicious code!
In this example we will use the [email protected] package sourced from the ens.snakecharmers.eth registry.
web3.pm uses the Package class to represent an ethPM package. This object houses all of the contract assets within a
package, and exposes them via an API. So, before we can interact with our package, we need to generate it as a Package
instance.
# Note. To use the web3.pm module, you will need to instantiate your w3 instance
# with a web3 provider connected to the chain on which your registry lives.
from web3 import Web3, IPCProvider
w3 = Web3(IPCProvider(...))
Now that we have a Package representation of our target ethPM package, we can generate contract factories and
instances from this Package. However, it’s important to note that some packages might be missing the necessary
contract assets needed to generate an instance or a factory. You can use the ethPM CLI to figure out the available
contract types and deployments within an ethPM package.
# To interact with a deployment located in an ethPM package.
# Note. This will only expose deployments located on the
# chain of the connected provider (in this example, mainnet)
mainnet_registrar = ens_package.deployments.get_instance("BaseRegistrarImplementation")
# Now you can treat mainnet_registrar like any other Web3 Contract instance!
mainnet_registrar.caller.balanceOf("0x123...")
> 0
(continues on next page)
mainnet_registrar.functions.approve("0x123", 100000).transact()
> 0x123abc... # tx_hash
# Now you can treat registrar_factory like any other Web3 Contract factory to deploy new␣
˓→instances!
# Note. This will deploy new instances to the chain of the connected provider (in this␣
˓→example, mainnet)
registrar_factory.constructor(...).transact()
> 0x456def... # tx_hash
# To connect your Package to a new chain - simply pass it a new Web3 instance
# connected to your provider of choice. Now your factories will automatically
# deploy to this new chain, and the deployments available on a package will
# be automatically filtered to those located on the new chain.
goerli_registrar = ens_package.update_w3(goerli_w3_instance)
Most fungible tokens on the Ethereum blockchain conform to the ERC20 standard. This section of the guide covers
interacting with an existing token contract which conforms to this standard.
In this guide we will interact with an existing token contract that we have already deployed to a local testing chain. This
guide assumes:
1. An existing token contract at a known address.
2. Access to the proper ABI for the given contract.
3. A web3.main.Web3 instance connected to a provider with an unlocked account which can send transactions.
First we need to create a contract instance with the address of our token contract and the ERC20 ABI.
Each token will have a total supply which represents the total number of tokens in circulation. In this example we’ve
initialized the token contract to have 1 million tokens. Since this token contract is setup to have 18 decimal places, the
raw total supply returned by the contract is going to have 18 additional decimal places.
>>> contract.functions.name().call()
'TestToken'
>>> contract.functions.symbol().call()
(continues on next page)
Next we can query some account balances using the contract’s balanceOf function. The token contract we are using
starts with a single account which we’ll refer to as alice holding all of the tokens.
Sending tokens
Next we can transfer some tokens from alice to bob using the contract’s transfer function.
Alice could also approve someone else to spend tokens from her account using the approve function. We can also
query how many tokens we’re approved to spend using the allowance function.
When someone has an allowance they can transfer those tokens using the transferFrom function.
Contract calls support CCIP Read by default, via a ccip_read_enabled flag on the call and, more globally,
a global_ccip_read_enabled flag on the provider. The following should work by default without raising an
OffchainLookup and instead handling it appropriately as per the specification outlined in EIP-3668.
myContract.functions.revertsWithOffchainLookup(myData).call()
If the offchain lookup requires the user to send a transaction rather than make a call, this may be handled appropriately
in the following way:
w3 = Web3(WebsocketProvider(...))
myContract = w3.eth.contract(address=...)
myData = b'data for offchain lookup function call'
# send the built transaction with `eth_sendTransaction` or sign and send with `eth_
˓→sendRawTransaction`
tx_hash = w3.eth.send_transaction(tx)
Here is an example of how one can use the pytest framework in python, web3.py, eth-tester, and PyEVM to perform
unit tests entirely in python without any additional need for a full featured ethereum node/client. To install needed
dependencies you can use the pinned extra for eth_tester in web3 and pytest:
Once you have an environment set up for testing, you can then write your tests like so:
# of how to write unit tests with web3.py
import pytest
import pytest_asyncio
@pytest.fixture
def tester_provider():
return EthereumTesterProvider()
@pytest.fixture
def eth_tester(tester_provider):
return tester_provider.ethereum_tester
@pytest.fixture
def w3(tester_provider):
return Web3(tester_provider)
@pytest.fixture
def foo_contract(eth_tester, w3):
# For simplicity of this example we statically define the
# contract code here. You might read your contracts from a
# file, or something else to test with in your own code
#
# pragma solidity^0.5.3;
#
# contract Foo {
#
# string public bar;
# event barred(string _bar);
(continues on next page)
deploy_address = eth_tester.get_accounts()[0]
abi = """[{"anonymous":false,"inputs":[{"indexed":false,"name":"_bar","type":"string
˓→"}],"name":"barred","type":"event"},{"constant":false,"inputs":[{"name":"_bar","type":
˓→"string"}],"name":"setBar","outputs":[],"payable":false,"stateMutability":"nonpayable",
˓→"type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":
˓→"constructor"},{"constant":true,"inputs":[],"name":"bar","outputs":[{"name":"","type":
˓→"string"}],"payable":false,"stateMutability":"view","type":"function"}]""" # noqa:␣
˓→E501
def test_initial_greeting(foo_contract):
hw = foo_contract.caller.bar()
assert hw == "hello world"
@pytest.fixture
def async_eth_tester():
return AsyncEthereumTesterProvider().ethereum_tester
@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_foo_contract(async_w3):
# For simplicity of this example we statically define the
# contract code here. You might read your contracts from a
# file, or something else to test with in your own code
#
# pragma solidity^0.5.3;
#
# contract Foo {
#
# string public bar;
# event barred(string _bar);
(continues on next page)
abi = """[{"anonymous":false,"inputs":[{"indexed":false,"name":"_bar","type":"string
˓→"}],"name":"barred","type":"event"},{"constant":false,"inputs":[{"name":"_bar","type":
˓→"string"}],"name":"setBar","outputs":[],"payable":false,"stateMutability":"nonpayable",
˓→"type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":
˓→"constructor"},{"constant":true,"inputs":[],"name":"bar","outputs":[{"name":"","type":
˓→"string"}],"payable":false,"stateMutability":"view","type":"function"}]""" # noqa:␣
˓→E501
@pytest.mark.asyncio
async def test_async_initial_greeting(async_foo_contract):
hw = await async_foo_contract.caller.bar()
assert hw == "hello world"
@pytest.mark.asyncio
async def test_async_can_update_greeting(async_w3, async_foo_contract):
async_eth_tester_accounts = await async_w3.eth.accounts
# send transaction that updates the greeting
(continues on next page)
@pytest.mark.asyncio
async def test_async_updating_greeting_emits_event(async_w3, async_foo_contract):
async_eth_tester_accounts = await async_w3.eth.accounts
# send transaction that updates the greeting
tx_hash = await async_foo_contract.functions.setBar(
"testing contracts is easy",
).transact(
{
"from": async_eth_tester_accounts[1],
}
)
receipt = await async_w3.eth.wait_for_transaction_receipt(tx_hash, 180)
w3 = Web3(Web3.HTTPProvider("https://goerli.infura.io/v3/YOUR_INFURA_KEY"))
Just remember that you have to sign all transactions locally, as infura does not handle any keys from your wallet ( refer
to this )
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)
P.S : the two updates are done to the transaction dictionary, since a raw transaction might not contain gas & nonce
amounts, so you have to add them manually.
And finally, send the transaction
txn_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
txn_receipt = w3.eth.wait_for_transaction_receipt(txn_hash)
Tip : afterwards you can use the value stored in txn_hash, in an explorer like etherscan to view the transaction’s details
import logging
import coloredlogs
def setup_logging(log_level=logging.DEBUG):
"""Setup root logger and quiet some levels."""
logger = logging.getLogger()
# Set log format to display the logger name to hunt down verbose logging modules
fmt = "%(name)-25s %(levelname)-8s %(message)s"
# Use colored logging output for console with the coloredlogs package
# https://pypi.org/project/coloredlogs/
coloredlogs.install(level=log_level, fmt=fmt, logger=logger)
return logger
In this example, we show how to fetch all events of a certain event type from the Ethereum blockchain. There are three
challenges when working with a large set of events:
• How to incrementally update an existing database of fetched events
• How to deal with interruptions in long running processes
• How to deal with eth_getLogs JSON-RPC call query limitations
• How to handle Ethereum minor chain reorganisations in (near) real-time data
eth_getLogs limitations
Ethereum JSON-RPC API servers, like Geth, do not provide easy to paginate over events, only over blocks. There’s no
request that can find the first block with an event or how many events occur within a range of blocks. The only feedback
the JSON-RPC service will give you is whether the eth_getLogs call failed.
In this example script, we provide two kinds of heuristics to deal with this issue. The script scans events in a chunk of
blocks (start block number - end block number). Then it uses two methods to find how many events there are likely to
be in a block window:
• Dynamically set the block range window size, while never exceeding a threshold (e.g., 10,000 blocks).
• In the case eth_getLogs JSON-PRC call gives a timeout error, decrease the end block number and try again with
a smaller block range window.
Example code
The following example code is divided into a reusable EventScanner class and then a demo script that:
• fetches all transfer events for RCC token,
• can incrementally run again to check if there are new events,
• handles interruptions (e.g., CTRL+C abort) gracefully,
• writes all Transfer events in a single file JSON database, so that other process can consume them,
• uses the tqdm library for progress bar output in a console,
• only supports HTTPS providers, because JSON-RPC retry logic depends on the implementation details of the
underlying protocol,
• disables the standard http_retry_request_middleware because it does not know how to handle the shrinking
block range window for eth_getLogs, and
• consumes around 20k JSON-RPC API calls.
The script can be run with: python ./eventscanner.py <your JSON-RPC API URL>.
With the stateful mechanism, you can do one batch scan or incremental scans,
where events are added wherever the scanner left off.
"""
import datetime
import time
(continues on next page)
logger = logging.getLogger(__name__)
class EventScannerState(ABC):
"""Application state that remembers what blocks we have scanned in the case of crash.
"""
@abstractmethod
def get_last_scanned_block(self) -> int:
"""Number of the last block we have scanned on the previous cycle.
@abstractmethod
def start_chunk(self, block_number: int):
"""Scanner is about to ask data of multiple blocks over JSON-RPC.
@abstractmethod
def end_chunk(self, block_number: int):
"""Scanner finished a number of blocks.
@abstractmethod
def process_event(self, block_when: datetime.datetime, event: AttributeDict) ->␣
˓→object:
This function takes raw events from Web3, transforms them to your application␣
˓→internal
format, then saves them in a database or some other state.
(continues on next page)
@abstractmethod
def delete_data(self, since_block: int) -> int:
"""Delete any data since this block was scanned.
class EventScanner:
"""Scan blockchain for events and try not to abuse JSON-RPC API too much.
Can be used for real-time scans, as it detects minor chain reorganisation and␣
˓→rescans.
Unlike the easy web3.contract.Contract, this scanner can scan events from multiple␣
˓→contracts at once.
For example, you can get all transfers from all tokens in the same scan.
"""
"""
:param contract: Contract
:param events: List of web3 Event we scan
:param filters: Filters passed to get_logs
:param max_chunk_scan_size: JSON-RPC API limit in the number of blocks we query.␣
˓→(Recommendation: 10,000 for mainnet, 500,000 for testnets)
"""
self.logger = logger
self.contract = contract
self.w3 = w3
self.state = state
self.events = events
(continues on next page)
# Factor how fast we increase the chunk size if results are found
# # (slow down scan after starting to get hits)
self.chunk_size_decrease = 0.5
@property
def address(self):
return self.token_address
def get_suggested_scan_start_block(self):
"""Get where we should start to scan for new token events.
These heuristics could be made more robust, but this is for the sake of simple␣
˓→reference implementation.
"""
end_block = self.get_last_scanned_block()
if end_block:
return max(1, end_block - self.NUM_BLOCKS_RESCAN_FOR_FORKS)
return 1
def get_suggested_scan_end_block(self):
"""Get the last mined block on Ethereum chain we are following."""
Dynamically decrease the size of the chunk if the case JSON-RPC server pukes out.
:return: tuple(actual end block number, when this block was mined, processed␣
˓→events)
"""
block_timestamps = {}
get_block_timestamp = self.get_block_timestamp
all_processed = []
block_number = evt["blockNumber"]
# Get UTC time when this event happened (block mined timestamp)
# from our in-memory cache
block_when = get_block_when(block_number)
end_block_timestamp = get_block_when(end_block)
return end_block, end_block_timestamp, all_processed
Our scanner might need to scan the whole blockchain for all events
* We want to make sure that one scan chunk does not try to process too many␣
˓→entries once, as we try to control commit buffer size and potentially asynchronous␣
˓→busy loop
* Do not overload node serving JSON-RPC API by asking data for too many events␣
at a time
˓→
Currently Ethereum JSON-API does not have an API to tell when a first event␣
˓→occurred in a blockchain
and our heuristics try to accelerate block fetching (chunk size) until we see␣
˓→the first event.
These heuristics exponentially increase the scan chunk size depending on if we␣
˓→are seeing events or not.
When any transfers are encountered, we are back to scanning only a few blocks at␣
˓→a time.
It does not make sense to do a full chain scan starting from block 1, doing one␣
˓→JSON-RPC call per 20 blocks.
"""
if event_found_count > 0:
# When we encounter first events, reset the chunk size window
current_chuck_size = self.min_scan_chunk_size
else:
current_chuck_size *= self.chunk_size_increase
Assumes all balances in the database are valid before start_block (no forks␣
˓→sneaked in).
:param start_chunk_size: How many blocks we try to fetch over JSON-RPC on the␣
˓→first attempt
current_block = start_block
self.state.start_chunk(current_block, chunk_size)
# Print some diagnostics to logs to try to fiddle with real world JSON-RPC␣
˓→API performance
estimated_end_block = current_block + chunk_size
logger.debug(
f"Scanning token transfers for blocks: {current_block} - {estimated_end_
˓→block}, chunk size {chunk_size}, last chunk scan took {last_scan_duration}, last logs␣
˓→found {last_logs_found}"
start = time.time()
actual_end_block, end_block_timestamp, new_entries = self.scan_chunk(current_
(continues on next page)
# Where does our current chunk scan ends - are we out of chain yet?
current_end = actual_end_block
# Try to guess how many blocks to fetch over `eth_getLogs` API next time
chunk_size = self.estimate_next_chunk_size(chunk_size, len(new_entries))
If our JSON-RPC server cannot serve all incoming `eth_getLogs` in a single request,
we retry and throttle down block range for every retry.
For example, Go Ethereum does not indicate what is an acceptable response size.
It just fails on the server-side with a "context was cancelled" warning.
# from Go Ethereum. This translates to the error "context was cancelled" on␣
˓→the server side:
# https://github.com/ethereum/go-ethereum/issues/20426
if i < retries - 1:
# Give some more verbose info than the default middleware
logger.warning(
(continues on next page)
def _fetch_events_for_all_contracts(
w3,
event,
argument_filters: Dict[str, Any],
from_block: int,
to_block: int) -> Iterable:
"""Get events using eth_getLogs API.
"""
if from_block is None:
raise TypeError("Missing mandatory keyword argument to get_logs: from_block")
if __name__ == "__main__":
# Simple demo that scans all the token transfers of RCC token (11k).
# The demo supports persistent state by using a JSON file.
# You will need an Ethereum node for this.
# Running this script will consume around 20k JSON-RPC calls.
# With locally running Geth, the script takes 10 minutes.
# The resulting JSON state file is 2.9 MB.
import sys
import json
from web3.providers.rpc import HTTPProvider
class JSONifiedState(EventScannerState):
"""Store the state of scanned blocks and all events.
def __init__(self):
self.state = None
self.fname = "test-state.json"
# How many second ago we saved the JSON file
self.last_save = 0
def reset(self):
"""Create initial state of nothing scanned."""
self.state = {
"last_scanned_block": 0,
"blocks": {},
}
def restore(self):
"""Restore the last scan state from a file."""
try:
self.state = json.load(open(self.fname, "rt"))
print(f"Restored the state, previously {self.state['last_scanned_block']}
˓→ blocks have been scanned")
except (IOError, json.decoder.JSONDecodeError):
print("State starting from scratch")
self.reset()
def save(self):
(continues on next page)
#
# EventScannerState methods implemented below
#
def get_last_scanned_block(self):
"""The number of the last block we have stored."""
return self.state["last_scanned_block"]
# Next time the scanner is started we will resume from this block
self.state["last_scanned_block"] = block_number
# Create empty dict as the block that contains all transactions by txhash
if block_number not in self.state["blocks"]:
self.state["blocks"][block_number] = {}
block = self.state["blocks"][block_number]
if txhash not in block:
# We have not yet recorded any transfers in this transaction
# (One transaction may contain multiple events if executed by a smart␣
˓→contract).
def run():
if len(sys.argv) < 2:
print("Usage: eventscanner.py http://your-node-url")
sys.exit(1)
api_url = sys.argv[1]
provider = HTTPProvider(api_url)
w3 = Web3(provider)
# chain_id: int, w3: Web3, abi: Dict, state: EventScannerState, events: List,␣
˓→filters: Dict, max_chunk_scan_size: int=10000
(continues on next page)
max_chunk_scan_size=10000
)
# Assume we might have scanned the blocks all the way to the last Ethereum block
# that mined a few seconds before the previous scan run ended.
# Because there might have been a minor Ethereum chain reorganisations
# since the last scan ended, we need to discard
# the last few blocks from the previous scan results.
chain_reorg_safety_blocks = 10
scanner.delete_potentially_forked_block_data(state.get_last_scanned_block() -␣
˓→chain_reorg_safety_blocks)
if current_block_timestamp:
formatted_time = current_block_timestamp.strftime("%d-%m-%Y")
else:
formatted_time = "no block time available"
progress_bar.set_description(f"Current block: {current} ({formatted_time}
˓→), blocks in a scan batch: {chunk_size}, events processed in a batch {events_count}")
progress_bar.update(chunk_size)
state.save()
duration = time.time() - start
print(f"Scanned total {len(result)} Transfer events, in {duration} seconds,␣
˓→total {total_chunks_scanned} chunk scans performed")
run()
2.16 Troubleshooting
Many things can cause a broken environment. You might be on an unsupported version of Python. Another package
might be installed that has a name or version conflict. Often, the best way to guarantee a correct environment is with
virtualenv, like:
# *If* the above command displays an error, you can try installing as root:
$ sudo pip install virtualenv
# With virtualenv active, make sure you have the latest packaging tools
$ pip install --upgrade pip setuptools
Note: Remember that each new terminal session requires you to reactivate your virtualenv, like: $ source ~/.
venv-py3/bin/activate
Note that a web3.py instance must be configured before you can use most of its capabilities. One symptom of not
configuring the instance first is an error that looks something like this: AttributeError: type object 'Web3'
has no attribute 'eth'.
To properly configure your web3.py instance, specify which provider you’re using to connect to the Ethereum network.
An example configuration, if you’re connecting to a locally run node, might be:
You can check that your instance is connected via the is_connected method:
>>> w3.is_connected()
False
There are a variety of explanations for why you may see False here. To help you diagnose the problem, is_connected
has an optional show_traceback argument:
>>> w3.is_connected(show_traceback=True)
# this is an example, your error may differ
If you’re running a local node, such as Geth, double-check that you’ve indeed started the binary and that you’ve started
it from the intended directory - particularly if you’ve specified a relative path to its ipc file.
If that does not address your issue, it’s probable that you still have a Provider configuration issue. There are several
options for configuring a Provider, detailed here.
Often you don’t need to do this, just make a new account in web3.py, and transfer funds from your MetaMask account
into it. But if you must. . .
Export your private key from MetaMask, and use the local private key tools in web3.py to sign and send transactions.
See how to export your private key and Working with Local Private Keys.
Test networks usually have something called a “faucet” to help get test ether to people who want to use it. The faucet
simply sends you test ether when you visit a web page, or ping a chat bot, etc.
Each test network has its own version of test ether, so each one must maintain its own faucet. If you’re not sure which
test network to use, see Which network should I connect to?
Faucet mechanisms tend to come and go, so if any information here is out of date, try the Ethereum Stackexchange.
Here are some links to testnet ether instructions (in no particular order):
• Goerli (different faucet links on top menu bar)
• Sepolia
If you’re seeing the error The method personal_newAccount does not exist/is not available, you may
be trying to create an account while connected to a remote node provider, like Infura. As a matter of security, remote
nodes cannot create accounts.
If you are in fact running a local node, make sure that it’s properly configured to accept personal methods. For Geth,
that looks something like: --http.api personal,eth,<etc> or --ws.api personal,eth,<etc> depending on
your configuration. Note that the IPC configuration is most secure and includes the personal API by default.
In general, your options for accounts are:
• Run a node (e.g., Geth) locally, connect to it via the local port, then use the personal API.
• Import a keystore file for an account and extract the private key.
• Create an account via the eth-account API, e.g., new_acct = w3.eth.account.create().
• Use an external service (e.g., MyCrypto) to generate a new account, then securely import its private key.
Warning: Don’t store real value in an account until you are familiar with security best practices. If you lose your
private key, you lose your account!
Your Ethereum node JSON-RPC API might be slow when fetching multiple and large requests, especially when running
batch jobs. Here are some tips for how to speed up your web3.py application.
• Run your client locally, e.g., Go Ethereum or TurboGeth. The network latency and speed are the major limiting
factors for fast API access.
• Use IPC communication instead of HTTP/WebSockets. See Choosing How to Connect to Your Node.
• Use an optimised JSON decoder. A future iteration of web3.py may change the default decoder or provide an
API to configure one, but for now, you may patch the provider class to use ujson.
import ujson
Some Windows users that do not have Microsoft Visual C++ version 14.0 or greater installed may see an error message
when installing web3.py as shown below:
error: Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++␣
˓→Build Tools": https://visualstudio.microsoft.com/visual-cpp-build-tools/
To fix this error, download and install Microsoft Visual C++ from here :
Microsoft Visual C++ Redistributable for Visual Studio
• x64 Visual C++
• x86 Visual C++
• ARM64 Visual C++
web3.py follows Semantic Versioning, which means that version 6 introduced backwards-incompatible changes. If
your project depends on web3.py v6, then you’ll probably need to make some changes.
Breaking Changes:
web3.py v6 moved to requiring strict bytes checking by default. This means that if an ABI specifies a bytes4 argument,
web3.py will invalidate any entry that is not encodable as a bytes type with length of 4. This means only 0x-prefixed
hex strings with a length of 4 and bytes types with a length of 4 will be considered valid. This removes doubt that
comes from inferring values and assuming they should be padded.
This behavior was previously available in via the w3.enable_strict_bytes_checking() method. This is now,
however, a toggleable flag on the Web3 instance via the w3.strict_bytes_type_checking property. As outlined
above, this property is set to True by default but can be toggled on and off via the property’s setter (e.g. w3.
strict_bytes_type_checking = False).
web3.py v6 moved to the more Pythonic convention of snake_casing wherever possible. There are some exceptions to
this pattern:
• Contract methods and events use whatever is listed in the ABI. If the smart contract convention is to use camel-
Case for method and event names, web3.py won’t do any magic to convert it to snake_casing.
• Arguments to JSON-RPC methods. For example: transaction and filter parameters still use camelCasing. The
reason for this is primarily due to error messaging. It would be confusing to pass in a snake_cased parameter
and get an error message with a camelCased parameter.
• Data that is returned from JSON-RPC methods. For example: The keys in a transaction receipt will still be
returned as camelCase.
Support for Python 3.10 and 3.11 is here. In order to support Python 3.10, we had to update the Websockets dependency
to v10+.
2.17.4 Exceptions
ValidationError
The Python dev tooling ecosystem is moving towards standardizing ValidationError, so users know that they’re
catching the correct ValidationError. The base ValidationError is imported from eth_utils. However, we also
wanted to empower users to catch all errors emitted by a particular module. So we now have a Web3ValidationError,
EthPMValidationError, and an ENSValidationError that all inherit from the generic eth_utils.exceptions.
ValidationError.
The Web3 class previously contained both sync and async methods. We’ve separated Web3 and AsyncWeb3 function-
ality to tighten up typing. For example:
w3 = Web3(Web3.HTTPProvider(<provider.url>))
async_w3 = AsyncWeb3(AsyncWeb3.AsyncHTTPProvider(<provider.url>))
Eth module data returned as key-value pairs was previously automatically converted to an AttributeDict by result for-
matters, which could cause problems with typing. This conversion has been moved to a default attrdict_middleware
where it can be easily removed if necessary. See the Eth module docs for more detail.
2.17.5 Removals
• The ipfshttpclient library is now opt-in via a web3 install extra. This only affects the ethpm ipfs backends,
which rely on the library.
Web3.py follows Semantic Versioning, which means that version 5 introduced backwards-incompatible changes. If
your project depends on Web3.py v4, then you’ll probably need to make some changes.
Here are the most common required updates:
JSON-RPC Updates
In v4, JSON-RPC calls that looked up transactions or blocks and didn’t find them, returned None. Now if a transaction
or block is not found, a BlockNotFound or a TransactionNotFound error will be thrown as appropriate. This applies
to the following web3 methods:
• getTransaction() will throw a TransactionNotFound error
• getTransactionReceipt() will throw a TransactionNotFound error
• getTransactionByBlock() will throw a TransactionNotFound error
• getTransactionCount() will throw a BlockNotFound error
• getBlock() will throw a BlockNotFound error
• getUncleCount() will throw a BlockNotFound error
• getUncleByBlock() will throw a BlockNotFound error
Removed Methods
Deprecated Methods
The ConciseContract and ImplicitContract have been deprecated and will be removed in v6.
ImplicitContract instances will need to use the verbose syntax. For example:
contract.functions.<function name>.transact({})
ConciseContract has been replaced with the ContractCaller API. Instead of using the ConciseContract factory, you can
now use:
contract.caller.<function_name>
or the classic contract syntax:
contract.functions.<function name>.call().
Some more concrete examples can be found in the ContractCaller docs
Manager Provider
In v5, only a single provider will be allowed. While allowing multiple providers is a feature we’d like to support in
the future, the way that multiple providers was handled in v4 wasn’t ideal. The only thing they could do was fall back.
There was no mechanism for any round robin, nor was there any control around which provider was chosen. Eventually,
the idea is to expand the Manager API to support injecting custom logic into the provider selection process.
For now, manager.providers has changed to manager.provider. Similarly, instances of web3.providers have
been changed to web3.provider.
Testnet Changes
2.18.4 ENS
Web3.py has stopped inferring the .eth TLD on domain names. If a domain name is used instead of an address, you’ll
need to specify the TLD. An InvalidTLD error will be thrown if the TLD is missing.
In order to interact with Infura after March 27, 2019, you’ll need to set an environment variable called
WEB3_INFURA_PROJECT_ID. You can get a project id by visiting https://infura.io/register.
Web3.py follows Semantic Versioning, which means that version 4 introduced backwards-incompatible changes. If
your project depends on Web3.py v3, then you’ll probably need to make some changes.
Here are the most common required updates:
Only Python 3 is supported in v4. If you are running in Python 2, it’s time to upgrade. We recommend using 2to3
which can make most of your code compatible with Python 3, automatically.
The most important update, relevant to Web3.py, is the new bytes type. It is used regularly, throughout the library,
whenever dealing with data that is not guaranteed to be text.
Many different methods in Web3.py accept text or binary data, like contract methods, transaction details, and crypto-
graphic functions. The following example uses sha3(), but the same pattern applies elsewhere.
In v3 & Python 2, you might have calculated the hash of binary data this way:
>>> Web3.sha3('I\xe2\x99\xa5SF')
'0x50a826df121f4d076a3686d74558f40082a8e70b3469d8e9a16ceb2a79102e5e'
Or, you might have calculated the hash of text data this way:
>>> Web3.sha3(text=u'ISF')
'0x50a826df121f4d076a3686d74558f40082a8e70b3469d8e9a16ceb2a79102e5e'
>>> Web3.sha3(b'I\xe2\x99\xa5SF')
HexBytes('0x50a826df121f4d076a3686d74558f40082a8e70b3469d8e9a16ceb2a79102e5e')
>>> Web3.sha3(text='ISF')
HexBytes('0x50a826df121f4d076a3686d74558f40082a8e70b3469d8e9a16ceb2a79102e5e')
Note that the return value is different too: you can treat hexbytes.main.HexBytes like any other bytes value, but the
representation on the console shows you the hex encoding of those bytes, for easier visual comparison.
It takes a little getting used to, but the new py3 types are much better. We promise.
2.19.2 Filters
Filters usually don’t work quite the way that people want them to.
The first step toward fixing them was to simplify them by removing the polling logic. Now, you must request an update
on your filters explicitly. That means that any exceptions during the request will bubble up into your code.
In v3, those exceptions (like “filter is not found”) were swallowed silently in the automated polling logic. Here was the
invocation for printing out new block hashes as they appear:
The caller is responsible for polling the results from get_new_entries(). See Asynchronous Filter Polling for ex-
amples of filter-event handling with web3 v4.
These providers are fairly uncommon. If you don’t recognize the names, you can probably skip the section.
However, if you were using web3.py for testing contracts, you might have been using TestRPCProvider or
EthereumTesterProvider.
In v4 there is a new EthereumTesterProvider, and the old v3 implementation has been removed. Web3.py v4 uses
eth_tester.main.EthereumTester under the hood, instead of eth-testrpc. While eth-tester is still in beta, many
parts are already in better shape than testrpc, so we decided to replace it in v4.
If you were using TestRPC, or were explicitly importing EthereumTesterProvider, like: from web3.providers.
tester import EthereumTesterProvider, then you will need to update.
With v4 you should import with from web3 import EthereumTesterProvider. As before, you’ll need to install
Web3.py with the tester extra to get these features, like:
Web3.toDecimal()
In v4 Web3.toDecimal() is renamed: toInt() for improved clarity. It does not return a decimal.Decimal, it
returns an int.
Removed Methods
Provider Access
There are a number of places where an arbitrary string input might be either a byte-string that has been hex-encoded,
or unicode characters in text. These are named hexstr and text in Web3.py. You specify which kind of str you have
by using the appropriate keyword argument. See examples in Encoding and Decoding Helpers.
In v3, some methods accepted a str as the first positional argument. In v4, you must pass strings as one of hexstr or
text keyword arguments.
Notable methods that no longer accept ambiguous strings:
• sha3()
• toBytes()
2.19.5 Contracts
• When a contract returns the ABI type string, Web3.py v4 now returns a str value by decoding the underlying
bytes using UTF-8.
• When a contract returns the ABI type bytes (of any length), Web3.py v4 now returns a bytes value
• Providers
• Attributes
• Encoding and Decoding Helpers
• Currency Conversions
• Addresses
• Cryptographic Hashing
• Check Encodability
• RPC API Modules
• Custom Methods
• External Modules
class web3.Web3(provider)
2.20.1 Providers
Web3.HTTPProvider
Convenience API to access web3.providers.rpc.HTTPProvider
Web3.IPCProvider
Convenience API to access web3.providers.ipc.IPCProvider
2.20.2 Attributes
Web3.api
Returns the current Web3 version.
>>> web3.api
"4.7.0"
Web3.client_version
>>> web3.client_version
'Geth/v1.4.11-stable-fed692f6/darwin/go1.7'
>>> Web3.to_hex(0)
'0x0'
>>> Web3.to_hex(1)
'0x1'
>>> Web3.to_hex(0x0)
'0x0'
>>> Web3.to_hex(0x000F)
'0xf'
>>> Web3.to_hex(b'')
'0x'
>>> Web3.to_hex(b'\x00\x0F')
'0x000f'
>>> Web3.to_hex(False)
'0x0'
>>> Web3.to_hex(True)
'0x1'
>>> Web3.to_hex(hexstr='0x000F')
'0x000f'
>>> Web3.to_hex(hexstr='000F')
'0x000f'
>>> Web3.to_hex(text='')
'0x'
>>> Web3.to_hex(text='cowmö')
'0x636f776dc3b6'
>>> Web3.to_text(0x636f776dc3b6)
'cowmö'
>>> Web3.to_text(b'cowm\xc3\xb6')
'cowmö'
>>> Web3.to_text(hexstr='0x636f776dc3b6')
'cowmö'
>>> Web3.to_text(hexstr='636f776dc3b6')
'cowmö'
>>> Web3.to_text(text='cowmö')
'cowmö'
>>> Web3.to_bytes(0)
b'\x00'
>>> Web3.to_bytes(0x000F)
b'\x0f'
>>> Web3.to_bytes(b'')
(continues on next page)
>>> Web3.to_int(0)
0
>>> Web3.to_int(0x000F)
15
>>> Web3.to_int(b'\x00\x0F')
15
>>> Web3.to_int(False)
0
>>> Web3.to_int(True)
1
>>> Web3.to_int(hexstr='0x000F')
15
>>> Web3.to_int(hexstr='000F')
15
Web3.to_json(obj)
Takes a variety of inputs and returns its JSON equivalent.
>>> Web3.to_json(3)
'3'
>>> Web3.to_json({'one': 1})
'{"one": 1}'
Web3.to_wei(value, currency)
Returns the value in the denomination specified by the currency argument converted to wei.
Web3.from_wei(value, currency)
Returns the value in wei converted to the given currency. The value is returned as a Decimal to ensure precision
down to the wei.
2.20.5 Addresses
Web3.is_address(value)
Returns True if the value is one of the recognized address formats.
• Allows for both 0x prefixed and non-prefixed values.
• If the address contains mixed upper and lower cased characters this function also checks if the address
checksum is valid according to EIP55
>>> Web3.is_address('0xd3CdA913deB6f67967B99D67aCDFa1712C293601')
True
Web3.is_checksum_address(value)
Returns True if the value is a valid EIP55 checksummed address
>>> Web3.is_checksum_address('0xd3CdA913deB6f67967B99D67aCDFa1712C293601')
True
>>> Web3.is_checksum_address('0xd3cda913deb6f67967b99d67acdfa1712c293601')
False
Web3.to_checksum_address(value)
Returns the given address with an EIP55 checksum.
>>> Web3.to_checksum_address('0xd3cda913deb6f67967b99d67acdfa1712c293601')
'0xd3CdA913deB6f67967B99D67aCDFa1712C293601'
>>> Web3.keccak(0x747874)
>>> Web3.keccak(b'\x74\x78\x74')
>>> Web3.keccak(hexstr='0x747874')
(continues on next page)
HexBytes("0x2ff37b5607484cd4eecf6d13292e22bd6e5401eaffcc07e279583bc742c68882")
w3.is_encodable(_type, value)
Returns True if a value can be encoded as the given type. Otherwise returns False.
False
>>> w3.is_encodable('bytes2', b'1') # does not match specified bytes size
False
>>> w3.is_encodable('bytes2', b'123') # does not match specified bytes size
False
w3.strict_bytes_type_checking
Disable the stricter bytes type checking that is loaded by default. For more examples, see Disabling Strict Checks
for Bytes Types
>>> # re-enable it
>>> w3.strict_bytes_type_checking = True
>>> w3.is_encodable('bytes2', b'1')
False
You may add or overwrite methods within any module using the attach_methods function. To create a property
instead, set is_property to True.
>>> w3.eth.attach_methods({
... 'example_method': Method(
... 'eth_example',
... mungers=[...],
... request_formatters=[...],
(continues on next page)
External modules can be used to introduce custom or third-party APIs to your Web3 instance. External modules are
simply classes whose methods and properties can be made available within the Web3 instance. Optionally, the external
module may make use of the parent Web3 instance by accepting it as the first argument within the __init__ function:
Warning: Given the flexibility of external modules, use caution and only import modules from trusted third parties
and open source code you’ve vetted!
Configuring external modules can occur either at instantiation of the Web3 instance or by making use of the
attach_modules() method. To instantiate the Web3 instance with external modules use the external_modules
keyword argument:
... })
... })
... }
... )
w3.attach_modules(modules)
The attach_modules() method can be used to attach external modules after the Web3 instance has been in-
stantiated.
Modules are attached via a dict with module names as the keys. The values can either be the module classes
themselves, if there are no submodules, or two-item tuples with the module class as the 0th index and a similarly
built dict containing the submodule information as the 1st index. This pattern may be repeated as necessary.
>>> w3.attach_modules({
... 'module1': ModuleClass1, # the module class itself may be used for a␣
˓→single module with no submodules
Warning: Whoa there, Binance Smart Chain user! web3.py is an Ethereum-specific library, which now defaults to
“type 2” transactions as of the London network upgrade. BSC apparently does not support these newer transaction
types.
From issues opened, it seems BSC transactions must include gasPrice, but not type, maxFeePerGas, or
maxPriorityFeePerGas. If you have trouble beyond that, please find an appropriate BSC forum to raise your
question.
class web3.eth.Eth
The web3.eth object exposes the following properties and methods to interact with the RPC APIs under the eth_
namespace.
By default, when a property or method returns a mapping of keys to values, it will return an AttributeDict which
acts like a dict but you can access the keys as attributes and cannot modify its fields. For example, you can find the
latest block number in these two ways:
>>> block['number']
4022281
>>> block.number
4022281
Note: Accessing an AttributeDict property via attribute will break type hinting. If typing is crucial for your
application, accessing via key / value, as well as removing the attrdict_middleware altogether, may be desired.
2.21.1 Properties
Eth.syncing
>>> web3.eth.syncing
AttributeDict({
'currentBlock': 2177557,
'highestBlock': 2211611,
'knownStates': 0,
'pulledStates': 0,
'startingBlock': 2177365,
})
Eth.coinbase
>>> web3.eth.coinbase
'0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E'
Eth.mining
>>> web3.eth.mining
False
Eth.hashrate
>>> web3.eth.hashrate
906
Eth.max_priority_fee
>>> web3.eth.max_priority_fee
2000000000
Eth.gas_price
>>> web3.eth.gas_price
20000000000
Eth.accounts
>>> web3.eth.accounts
['0x582AC4D8929f58c217d4a52aDD361AE470a8a4cD']
Eth.block_number
>>> web3.eth.block_number
2206939
Eth.chain_id
>>> web3.eth.chain_id
61
Note: This property gets called frequently in validation middleware, but chain_id is added to the
simple_cache_middleware by default. Add the simple_cache_middleware to the middleware_onion
to increase performance:
2.21.2 Methods
>>> web3.eth.get_balance('0xd3CdA913deB6f67967B99D67aCDFa1712C293601')
77320681768999138915
Eth.get_block_number()
>>> web3.eth.get_block_number()
2206939
˓→',
˓→'0xf90151a097b17a89fd2c03ee98cb6459c08f51b269da5cee46650e84470f62bf83b43efe80a03b269d284a4c3cf8f8
˓→',
˓→'0xf869a020d13b52a61d3c1325ce3626a51418adebd6323d4840f1bdd93906359d11c933b846f8440180a01ab7c0b0a2
˓→'
],
'balance': 0,
'codeHash': '0x551332d96d085185ab4019ad8bcf89c45321e136c261eb6271e574a2edf1461f
˓→',
'nonce': 1,
'storageHash':
˓→'0x1ab7c0b0a2a4bbb5a1495da8c142150891fc64e0c321e1feb70bd5f881951f7e',
'storageProof': [
AttributeDict({
'key': '0x00',
'value':
˓→'0x48656c6c6f00000000000000000000000000000000000000000000000000000a',
'proof': [
˓→'0xf9019180a01ace80e7bed79fbadbe390876bd1a7d9770edf9462049ef8f4b555d05715d53ea049347a3c2eac6525a3
˓→',
˓→'0xf891808080a0c7d094301e0c54da37b696d85f72de5520b224ab2cf4f045d8db1a3374caf0488080a0fc5581783bfe
˓→',
˓→'0xf843a0200decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563a1a048656c6c6f0000000000
˓→'
(continues on next page)
The following example verifies that the values returned in the AttributeDict are included in the state of given
trie root.
from eth_utils import (
keccak,
)
import rlp
from rlp.sedes import (
Binary,
big_endian_int,
)
from trie import (
HexaryTrie,
)
from web3._utils.encoding import (
pad_bytes,
)
def format_proof_nodes(proof):
trie_proof = []
for rlp_node in proof:
trie_proof.append(rlp.decode(bytes(rlp_node)))
return trie_proof
class _Account(rlp.Serializable):
fields = [
('nonce', big_endian_int),
('balance', big_endian_int),
('storage', trie_root),
('code_hash', hash32)
]
acc = _Account(
proof.nonce, proof.balance, proof.storageHash, proof.codeHash
)
rlp_account = rlp.encode(acc)
trie_key = keccak(bytes.fromhex(proof.address[2:]))
return True
block = w3.eth.get_block(3391)
proof = w3.eth.get_proof('0x6C8f2A135f6ed072DE4503Bd7C4999a1a17F824B', [0, 1], 3391)
assert verify_eth_get_proof(proof, block.stateRoot)
Eth.get_code(account, block_identifier=eth.default_block)
Eth.get_block(block_identifier=eth.default_block, full_transactions=False)
>>> web3.eth.get_block(2000000)
AttributeDict({
'difficulty': 49824742724615,
'extraData': '0xe4b883e5bda9e7a59ee4bb99e9b1bc',
'gasLimit': 4712388,
'gasUsed': 21000,
'hash': '0xc0f4906fea23cf6f3cce98cb44e8e1449e455b28d684dfa9ff65426495584de6',
'logsBloom':
˓→'0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
˓→',
'receiptsRoot':
˓→'0x84aea4a7aad5c5899bd5cfc7f309cc379009d30179316a2a7baa4a2ea4a438ac',
'sha3Uncles':
˓→'0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
'size': 650,
'stateRoot': '0x96dbad955b166f5119793815c36f11ffa909859bbfeb64b735cca37cbf10bef1
˓→',
'timestamp': 1470173578,
'totalDifficulty': 44010101827705409388,
'transactions': [
˓→'0xc55e2b90168af6972193c1f86fa4d7d7b31a29c156665d15b9cd48618b5177ef'],
'transactionsRoot':
˓→'0xb31f174d27b99cdae8e746bd138a01ce60d8dd7b224f7c60845914def05ecc58',
'uncles': [],
})
Eth.get_block_transaction_count(block_identifier)
>>> web3.eth.get_block_transaction_count(46147)
1
>>> web3.eth.get_block_transaction_count(
˓→'0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd') # block␣
˓→46147
Eth.get_uncle_by_block(block_identifier, uncle_index)
>>> web3.eth.get_uncle_by_block(56160, 0)
AttributeDict({
'author': '0xbe4532e1b1db5c913cf553be76180c1777055403',
'difficulty': '0x17dd9ca0afe',
'extraData': '0x476574682f686261722f76312e302e312f6c696e75782f676f312e342e32',
'gasLimit': '0x2fefd8',
(continues on next page)
˓→',
'miner': '0xbe4532e1b1db5c913cf553be76180c1777055403',
'mixHash': '0x041e14603f35a82f6023802fec96ef760433292434a39787514f140950597e5e',
'nonce': '0x5d2b7e3f1af09995',
'number': '0xdb5e',
'parentHash': '0xcc30e8a9b15c548d5bf113c834143a8f0e1909fbfea96b2a208dc154293a78cf
˓→',
'receiptsRoot':
˓→'0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
'sealFields': [
˓→'0xa0041e14603f35a82f6023802fec96ef760433292434a39787514f140950597e5e',
˓→'0x885d2b7e3f1af09995'],
'sha3Uncles': '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347
˓→',
'timestamp': '0x55c6a972',
'totalDifficulty': '0xce4c4f0a0b810b',
'transactions': [],
'transactionsRoot':
˓→'0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
'uncles': []
})
AttributeDict({
...
})
Eth.get_uncle_count(block_identifier)
>>> web3.eth.get_uncle_count(56160)
1
Eth.get_transaction(transaction_hash)
>>> web3.eth.get_transaction(
˓→'0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060')
AttributeDict({'blockHash': HexBytes(
˓→'0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd'),
'blockNumber': 46147,
'from': '0xA1E4380A3B1f749673E270229993eE55F35663b4',
'gas': 21000,
'gasPrice': 50000000000000,
'hash': HexBytes(
˓→'0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060'),
'input': HexBytes('0x'),
'nonce': 0,
'r': HexBytes(
˓→'0x88ff6cf0fefd94db46111149ae4bfc179e9b94721fffd821d38d16464b3f71d0'),
's': HexBytes(
˓→'0x45e0aff800961cfce805daef7016b9b675c137a6a41a548f7b60a3484c06a33a'),
'to': '0x5DF9B87991262F6BA471F09758CDE1c0FC1De734',
'transactionIndex': 0,
'type': 0,
'v': 28,
'value': 31337
})
Eth.get_raw_transaction(transaction_hash)
>>> web3.eth.get_raw_transaction(
˓→'0x86fbfe56cce542ff0a2a2716c31675a0c9c43701725c4a751d20ee2ddf8a733d')
HexBytes(
˓→'0xf86907843b9aca0082520894dc544d1aa88ff8bbd2f2aec754b1f1e99e1812fd018086eecac466e115a0f9db4e2548
˓→')
Eth.get_transaction_by_block(block_identifier, transaction_index)
>>> web3.eth.get_transaction_by_block(46147, 0)
AttributeDict({
'blockHash': '0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd
(continues on next page)
AttributeDict({
'blockHash': '0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd
˓→',
'blockNumber': 46147,
'from': '0xA1E4380A3B1f749673E270229993eE55F35663b4',
'gas': 21000,
'gasPrice': None,
'hash': '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
'input': '0x',
'maxFeePerGas': 2000000000,
'maxPriorityFeePerGas': 1000000000,
'nonce': 0,
'to': '0x5DF9B87991262F6BA471F09758CDE1c0FC1De734',
'transactionIndex': 0,
'value': 31337,
})
Eth.get_raw_transaction_by_block(block_identifier, transaction_index)
• Delegates to eth_getRawTransactionByBlockNumberAndIndex or
eth_getRawTransactionByBlockHashAndIndex RPC Methods
Returns the raw transaction at the index specified by transaction_index from the block spec-
ified by block_identifier. Delegates to eth_getRawTransactionByBlockNumberAndIndex
if block_identifier is an integer or one of the predefined block parameters
'latest', 'earliest', 'pending', 'safe', 'finalized', otherwise delegates to
eth_getRawTransactionByBlockHashAndIndex. If a transaction is not found at specified arguments,
throws web3.exceptions.TransactionNotFound.
>>> web3.eth.get_raw_transaction_by_block('latest', 0)
HexBytes(
˓→'0x02f87582053901843b9aca00843b9aca008301d8a894e2dfcfa89a45abdc3de91f7a2844b276b8451d2e888ac72304
˓→')
>>> web3.eth.get_raw_transaction_by_block(2, 0)
HexBytes(
˓→'0x02f87582053901843b9aca00843b9aca008301d8a894e2dfcfa89a45abdc3de91f7a2844b276b8451d2e888ac72304
˓→')
HexBytes(
˓→'0x02f87582053901843b9aca00843b9aca008301d8a894e2dfcfa89a45abdc3de91f7a2844b276b8451d2e888ac72304
˓→')
>>> web3.eth.wait_for_transaction_receipt(
˓→'0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060')
# If transaction is not yet in a block, time passes, while the thread sleeps...
# ...
# Then when the transaction is added to a block, its receipt is returned:
AttributeDict({
'blockHash': '0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd
˓→',
'blockNumber': 46147,
'contractAddress': None,
'cumulativeGasUsed': 21000,
'from': '0xA1E4380A3B1f749673E270229993eE55F35663b4',
'gasUsed': 21000,
'logs': [],
'logsBloom': '0x000000000000000000000000000000000000000000000000...0000',
'status': 1,
'to': '0x5DF9B87991262F6BA471F09758CDE1c0FC1De734',
'transactionHash':
˓→'0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
'transactionIndex': 0,
})
Eth.get_transaction_receipt(transaction_hash)
>>> web3.eth.get_transaction_receipt(
˓→'0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060') # not yet␣
˓→mined
'blockNumber': 46147,
'contractAddress': None,
'cumulativeGasUsed': 21000,
'from': '0xA1E4380A3B1f749673E270229993eE55F35663b4',
'gasUsed': 21000,
'logs': [],
'logsBloom': '0x000000000000000000000000000000000000000000000000...0000',
'status': 1, # 0 or 1
'to': '0x5DF9B87991262F6BA471F09758CDE1c0FC1De734',
'transactionHash':
˓→'0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
'transactionIndex': 0,
})
Eth.get_transaction_count(account, block_identifier=web3.eth.default_block)
>>> web3.eth.get_transaction_count('0xd3CdA913deB6f67967B99D67aCDFa1712C293601')
340
Eth.send_transaction(transaction)
• nonce: integer - (optional) Integer of a nonce. This allows to overwrite your own pending transactions
that use the same nonce.
If the transaction specifies a data value but does not specify gas then the gas value will be populated using
the estimate_gas() function with an additional buffer of 100000 gas up to the gasLimit of the latest block.
In the event that the value returned by estimate_gas() method is greater than the gasLimit a ValueError
will be raised.
# simple example (web3.py and / or client determines gas and fees, typically␣
˓→defaults to a dynamic fee transaction post London fork)
>>> web3.eth.send_transaction({
'to': '0x582AC4D8929f58c217d4a52aDD361AE470a8a4cD',
'from': web3.eth.coinbase,
'value': 12345
})
Eth.sign_transaction(transaction)
˓→x0en\xb5\x99\xed;\xf6\x8f\xb3\xf1\xe6,\x82\xdf\xe5\x97lF|\x97%;\x15\xa04P\xb7=*\
Eth.send_raw_transaction(raw_transaction)
chainId=1,
),
private_key_for_senders_account,
)
>>> w3.eth.send_raw_transaction(signed_txn.rawTransaction)
HexBytes('0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331')
Eth.replace_transaction(transaction_hash, new_transaction)
• If a gas price strategy is set, the gasPrice value from the gas price strategy(See Gas Price API) will be
used.
• If none of the above, the client will ultimately decide appropriate values for maxFeePerGas and
maxPriorityFeePerGas. These will likely be default values and may result in an unsuccessful replace-
ment of the pending transaction.
This method returns the transaction hash of the replacement transaction as a HexBytes object.
>>> tx = web3.eth.send_transaction({
'to': '0x582AC4D8929f58c217d4a52aDD361AE470a8a4cD',
'from': web3.eth.coinbase,
'value': 1000
})
HexBytes('0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331')
>>> web3.eth.replace_transaction(
˓→'0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331', {
'to': '0x582AC4D8929f58c217d4a52aDD361AE470a8a4cD',
'from': web3.eth.coinbase,
'value': 2000
})
HexBytes('0x4177e670ec6431606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1528989')
Eth.modify_transaction(transaction_hash, **transaction_params)
>>> tx = web3.eth.send_transaction({
'to': '0x582AC4D8929f58c217d4a52aDD361AE470a8a4cD',
'from': web3.eth.coinbase,
'value': 1000
})
HexBytes('0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331')
>>> web3.eth.modify_transaction(
˓→'0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331', value=2000)
HexBytes('0xec6434e6701771606e55d6b4ca35a1a6b75ee3d73315145a921026d15299d05')
>>> web3.eth.sign(
'0x582AC4D8929f58c217d4a52aDD361AE470a8a4cD',
(continues on next page)
˓→'0x1a8bbe6eab8c72a219385681efefe565afd3accee35f516f8edf5ae82208fbd45a58f9f9116d8d88ba40fcd29076d6
˓→'
>>> web3.eth.sign(
'0x582AC4D8929f58c217d4a52aDD361AE470a8a4cD',
data=b'some-text-t\xc3\xb6-sign')
˓→'0x1a8bbe6eab8c72a219385681efefe565afd3accee35f516f8edf5ae82208fbd45a58f9f9116d8d88ba40fcd29076d6
˓→'
>>> web3.eth.sign(
'0xd3CdA913deB6f67967B99D67aCDFa1712C293601',
hexstr='0x736f6d652d746578742d74c3b62d7369676e')
˓→'0x1a8bbe6eab8c72a219385681efefe565afd3accee35f516f8edf5ae82208fbd45a58f9f9116d8d88ba40fcd29076d6
˓→'
Eth.sign_typed_data(account, jsonMessage)
Note: eth_signTypedData is not currently supported by any major client (Besu, Erigon, Geth, or Nethermind)
Please note that the jsonMessage argument is the loaded JSON Object and NOT the JSON String itself.
Signs the Structured Data (or Typed Data) with the private key of the given account. The account must
be unlocked.
account may be a checksum address or an ENS name
Eth.call(transaction, block_identifier=web3.eth.default_block, state_override=None, ccip_read_enabled=True)
>>> myContract.functions.setVar(1).transact()
HexBytes('0x79af0c7688afba7588c32a61565fd488c422da7b5773f95b242ea66d3d20afda')
>>> myContract.functions.getVar().call()
1
# The above call equivalent to the raw call:
>>> web3.eth.call({'value': 0, 'gas': 21736, 'maxFeePerGas': 2000000000,
˓→'maxPriorityFeePerGas': 1000000000, 'to':
HexBytes('0x0000000000000000000000000000000000000000000000000000000000000001')
In most cases it is better to make contract function call through the web3.contract.Contract interface.
Overriding state is a debugging feature available in Geth clients. View their usage documentation for a list of
possible parameters.
EIP-3668 introduced support for the OffchainLookup revert / CCIP Read support. In order to properly han-
dle a call to a contract function that reverts with an OffchainLookup error for offchain data retrieval, the
ccip_read_enabled flag has been added to the eth_call method. ccip_read_enabled is optional, yielding
the default value for CCIP Read on calls to a global global_ccip_read_enabled flag on the provider which
is set to True by default. This means CCIP Read is enabled by default for calls, as is recommended in EIP-
3668. Therefore, calls to contract functions that revert with an OffchainLookup will be handled appropriately
by default.
The ccip_read_enabled flag on the call will always override the value of the global flag on the provider for
explicit control over specific calls. If the flag on the call is set to False, the call will raise the OffchainLookup
instead of properly handling the exception according to EIP-3668. This may be useful for “preflighting” a trans-
action with a call (see CCIP Read support for offchain lookup within the examples section).
If the function called results in a revert error, a ContractLogicError will be raised. If there is an error
message with the error, web3.py attempts to parse the message that comes back and return it to the user as
the error string. As of v6.3.0, the raw data is also returned and can be accessed via the data attribute on
ContractLogicError.
Eth.create_access_list(transaction, block_identifier=web3.eth.default_block)
>>> w3.eth.create_access_list(
... {
... "to": to_checksum_address("0xF0109fC8DF283027b6285cc889F5aA624EaC1F55"),
... "gasPrice": 10**11,
... "value": 0,
... "data": "0x608060806080608155",
... },
... "pending",
... )
AttributeDict({
'accessList': [
AttributeDict({
'address': '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe',
'storageKeys': [
HexBytes(
˓→'0x0000000000000000000000000000000000000000000000000000000000000003'),
HexBytes(
˓→'0x0000000000000000000000000000000000000000000000000000000000000007'),
]
}),
AttributeDict({
'address': '0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413',
'storageKeys': []
}),
],
"gasUsed": 21000
(continues on next page)
The method eth_createAccessList returns a list of addresses and storage keys used by the transaction, plus
the gas consumed when the accessList is included. Like eth_estimateGas, this is an estimation; the list
could change when the transaction is actually finalized. Adding an accessList to your transaction does not
necessarily result in lower gas usage compared to a transaction without an accessList.
Eth.fee_history(block_count, newest_block, reward_percentiles=None)
• oldestBlock (int) – The oldest, lowest-numbered, block in the range requested as a BlockNumber type with
int value.
• baseFeePerGas (List[Wei]) – An array of block base fees per gas. This includes the next block after the
newest of the returned range, because this value can be derived from the newest block. Zeroes are returned
for pre-EIP-1559 blocks.
• gasUsedRatio (List[float]) – An array of gasUsed/gasLimit float values for the requested blocks.
• reward (List[List[Wei]]) – (optional) A two-dimensional array of effective priority fees per gas at the
requested block percentiles.
})
The transaction and block_identifier parameters are handled in the same manner as the
send_transaction() method.
The state_override is useful when there is a chain of transaction calls. It overrides state so that the gas
estimate of a transaction is accurate in cases where prior calls produce side effects.
21000
Eth.generate_gas_price(transaction_params=None)
Uses the selected gas price strategy to calculate a gas price. This method returns the gas price denominated in
wei.
The transaction_params argument is optional however some gas price strategies may require it to be able to
produce a gas price.
>>> web3.eth.generate_gas_price()
20000000000
Note: For information about how gas price can be customized in web3 see Gas Price API.
Eth.set_gas_price_strategy(gas_price_strategy)
Set the selected gas price strategy. It must be a method of the signature (web3, transaction_params) and
return a gas price denominated in wei.
2.21.3 Filters
The following methods are available on the web3.eth object for interacting with the filtering API.
Eth.filter(filter_params)
• address: string or list of strings, each 20 Bytes - (optional) Contract address or a list of addresses
from which logs should originate.
• topics: list of 32 byte strings or null - (optional) Array of topics that should be used for filtering.
Topics are order-dependent. This parameter can also be a list of topic lists in which case filtering will
match any of the provided topic arrays.
Note: Though "latest" and "safe" block identifiers are not yet part of the specifications for eth_newFilter,
they are supported by web3.py and may or may not yield expected results depending on the node being accessed.
>>> web3.eth.filter('latest')
<BlockFilter at 0x10b72dc28>
>>> web3.eth.filter('pending')
<TransactionFilter at 0x10b780340>
>>> web3.eth.filter({'fromBlock': 1000000, 'toBlock': 1000100, 'address':
˓→'0x6C8f2A135f6ed072DE4503Bd7C4999a1a17F824B'})
<LogFilter at 0x10b7803d8>
Eth.get_filter_changes(self , filter_id)
'blockNumber': 2217196,
'data': '0x0000000000000000000000000000000000000000000000000000000000000001
˓→',
'logIndex': 0,
'topics': [
˓→'0xe65b00b698ba37c614af350761c735c5f4a82b4ab365a1f1022d49d9dfc8e930',
'0x000000000000000000000000754c50465885f1ed1fa1a55b95ee8ecf3f1f4324',
'0x296c7fb6ccafa3e689950b947c2895b07357c95b066d5cdccd58c301f41359a3'],
'transactionHash':
˓→'0xfe1289fd3915794b99702202f65eea2e424b2f083a12749d29b4dd51f6dce40d',
'transactionIndex': 1,
},
...
]
Eth.get_filter_logs(self , filter_id)
'blockNumber': 2217196,
'data': '0x0000000000000000000000000000000000000000000000000000000000000001
˓→',
'logIndex': 0,
'topics': [
˓→'0xe65b00b698ba37c614af350761c735c5f4a82b4ab365a1f1022d49d9dfc8e930',
'0x000000000000000000000000754c50465885f1ed1fa1a55b95ee8ecf3f1f4324',
'0x296c7fb6ccafa3e689950b947c2895b07357c95b066d5cdccd58c301f41359a3'],
'transactionHash':
˓→'0xfe1289fd3915794b99702202f65eea2e424b2f083a12749d29b4dd51f6dce40d',
'transactionIndex': 1,
},
...
]
Eth.uninstall_filter(self , filter_id)
Eth.get_logs(filter_params)
This is the equivalent of: creating a new filter, running get_filter_logs(), and then uninstalling the filter.
See filter() for details on allowed filter parameters.
Eth.submit_hashrate(hashrate, nodeid)
>>> web3.eth.submit_work(
1,
'0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
'0xD1FE5700000000000000000000000000D1FE5700000000000000000000000000',
(continues on next page)
2.21.4 Contracts
w3 = Web3(...)
contract = w3.eth.contract(address='0x000000000000000000000000000000000000dEaD',␣
˓→abi=...)
# alternatively:
contract = w3.eth.contract(address='mycontract.eth', abi=...)
Note: If you use an ENS name to initialize a contract, the contract will be looked up by name on each use. If the
name could ever change maliciously, first Get the Address for an ENS Name, and then create the contract with
the checksum address.
If address is not provided, the newly created contract class will be returned. That class will then be initialized
by supplying the address.
w3 = Web3(...)
Contract = w3.eth.contract(abi=...)
contract_name will be used as the name of the contract class. If it is None then the name of the
ContractFactoryClass will be used.
ContractFactoryClass will be used as the base Contract class.
The following arguments are accepted for contract class creation.
Parameters
• abi (ABI) – Application Binary Interface. Usually provided since an abi is required to
interact with any contract.
• asm – Asssembly code generated by the compiler
• ast – Abstract Syntax Tree of the contract generated by the compiler
Warning: This API Is experimental. Client support is incomplete and the API itself is still evolving.
To use this API, you’ll need a beacon node running locally or remotely. To set that up, refer to the documentation of
your specific client.
Once you have a running beacon node, import and configure your beacon instance:
2.22.1 Methods
Beacon.get_genesis()
>>> beacon.get_genesis()
{
'data': {
'genesis_time': '1605700807',
'genesis_validators_root':
˓→'0x9436e8a630e3162b7ed4f449b12b8a5a368a4b95bc46b941ae65c11613bfa4c1',
'genesis_fork_version': '0x00002009'
}
}
Beacon.get_hash_root(state_id='head')
>>> beacon.get_hash_root()
{
"data": {
"root":"0xbb399fda70617a6f198b3d9f1c1cdbd70077677231b84f34e58568c9dc903558"
}
}
Beacon.get_fork_data(state_id='head')
>>> beacon.get_fork_data()
{
'data': {
'previous_version': '0x00002009',
'current_version': '0x00002009',
'epoch': '0'
}
}
Beacon.get_finality_checkpoint(state_id='head')
>>> beacon.get_finality_checkpoint()
{
'data': {
'previous_justified': {
'epoch': '5024',
'root': '0x499ba555e8e8be639dd84be1be6d54409738facefc662f37d97065aa91a1a8d4'
},
'current_justified': {
'epoch': '5025',
'root': '0x34e8a230f11536ab2ec56a0956e1f3b3fd703861f96d4695877eaa48fbacc241'
},
'finalized': {
'epoch': '5024',
'root': '0x499ba555e8e8be639dd84be1be6d54409738facefc662f37d97065aa91a1a8d4'
}
}
}
Beacon.get_validators(state_id='head')
>>> beacon.get_validators()
{
'data': [
{
'index': '110280',
'balance': '32000000000',
'status': 'pending_queued',
'validator': {
'pubkey':
˓→'0x99d37d1f7dd15859995330f75c158346f86d298e2ffeedfbf1b38dcf3df89a7dbd1b34815f3bcd1b2a5588592a35b7
˓→',
'withdrawal_credentials':
˓→'0x00f338cfdb0c22bb85beed9042bd19fff58ad6421c8a833f8bc902b7cca06f5f',
'effective_balance': '32000000000',
'slashed': False,
'activation_eligibility_epoch': '5029',
'activation_epoch': '18446744073709551615',
'exit_epoch': '18446744073709551615',
'withdrawable_epoch': '18446744073709551615'
}
},
...
]
}
Beacon.get_validator(validator_id, state_id='head')
>>> beacon.get_validator(110280)
{
'data': {
'index': '110280',
'balance': '32000000000',
'status': 'pending_queued',
'validator': {
'pubkey':
˓→'0x99d37d1f7dd15859995330f75c158346f86d298e2ffeedfbf1b38dcf3df89a7dbd1b34815f3bcd1b2a5588592a35b7
˓→',
'withdrawal_credentials':
˓→'0x00f338cfdb0c22bb85beed9042bd19fff58ad6421c8a833f8bc902b7cca06f5f',
'effective_balance': '32000000000',
'slashed': False,
'activation_eligibility_epoch': '5029',
'activation_epoch': '18446744073709551615',
'exit_epoch': '18446744073709551615',
'withdrawable_epoch': '18446744073709551615'
}
}
}
Beacon.get_validator_balances(state_id='head')
>>> beacon.get_validator_balances()
{
'data': [
{
'index': '110278',
'balance': '32000000000'
},
...
]
}
Beacon.get_epoch_committees(state_id='head')
>>> beacon.get_epoch_committees()
{
'data': [
{
'slot': '162367',
'index': '25',
'validators': ['50233', '36829', '84635', ...],
},
...
]
}
Beacon.get_block_headers()
>>> beacon.get_block_headers()
{
'data': [
{
'root': '0xa3873e7b1e0bcc7c59013340cfea59dff16e42e79825e7b8ab6c243dbafd4fe0',
'canonical': True,
'header': {
'message': {
'slot': '163587',
'proposer_index': '69198',
'parent_root':
˓→'0xc32558881dbb791ef045c48e3709a0978dc445abee4ae34d30df600eb5fbbb3d',
'state_root':
˓→'0x4dc0a72959803a84ee0231160b05dda76a91b8f8b77220b4cfc7db160840b8a8',
'body_root':
˓→'0xa3873e7b1e0bcc7c59013340cfea59dff16e42e79825e7b8ab6c243dbafd4fe0'
},
'signature':
˓→'0x87b549448d36e5e8b1783944b5511a05f34bb78ad3fcbf71a1adb346eed363d46e50d51ac53cd23bd03d0107d064e0
˓→'
}
}
]
}
Beacon.get_block_header(block_id)
>>> beacon.get_block_header(1)
{
'data': {
root': '0x30c04689dd4f6cd4d56eb78f72727d2d16d8b6346724e4a88f546875f11b750d',
'canonical': True,
'header': {
'message': {
'slot': '1',
'proposer_index': '61090',
'parent_root':
˓→'0x6a89af5df908893eedbed10ba4c13fc13d5653ce57db637e3bfded73a987bb87',
'state_root':
˓→'0x7773ed5a7e944c6238cd0a5c32170663ef2be9efc594fb43ad0f07ecf4c09d2b',
'body_root':
˓→'0x30c04689dd4f6cd4d56eb78f72727d2d16d8b6346724e4a88f546875f11b750d'
},
'signature':
˓→'0xa30d70b3e62ff776fe97f7f8b3472194af66849238a958880510e698ec3b8a470916680b1a82f9d4753c023153fbe6
˓→'
}
}
}
Beacon.get_block(block_id)
>>> beacon.get_block(1)
{
'data': {
'message': {
'slot': '1',
'proposer_index': '61090',
'parent_root':
˓→'0x6a89af5df908893eedbed10ba4c13fc13d5653ce57db637e3bfded73a987bb87',
'state_root':
˓→'0x7773ed5a7e944c6238cd0a5c32170663ef2be9efc594fb43ad0f07ecf4c09d2b',
'body': {
'randao_reveal':
˓→'0x8e245a52a0a680fcfe789013e123880c321f237de10cad108dc55dd47290d7cfe50cdaa003c6f783405efdac48cef4
˓→',
'eth1_data': {
'deposit_root':
˓→'0x4e910ac762815c13e316e72506141f5b6b441d58af8e0a049cd3341c25728752',
'deposit_count': '100596',
'block_hash':
˓→'0x89cb78044843805fb4dab8abd743fc96c2b8e955c58f9b7224d468d85ef57130'
},
'graffiti':
˓→'0x74656b752f76302e31322e31342b34342d673863656562663600000000000000',
'proposer_slashings': [],
'attester_slashings': [],
'attestations': [
{
'aggregation_bits': '0x0080020004000000008208000102000905',
(continues on next page)
'source': {
'epoch': '0',
'root':
˓→'0x0000000000000000000000000000000000000000000000000000000000000000'
},
'target': {
'epoch': '0',
'root':
˓→'0x6a89af5df908893eedbed10ba4c13fc13d5653ce57db637e3bfded73a987bb87'
}
},
'signature':
˓→'0x967dd2946358db7e426ed19d4576bc75123520ef6a489ca50002222070ee4611f9cef394e5e3071236a93b825f18a4
˓→'
}
],
'deposits': [],
'voluntary_exits': []
}
},
'signature':
˓→'0xa30d70b3e62ff776fe97f7f8b3472194af66849238a958880510e698ec3b8a470916680b1a82f9d4753c023153fbe6
˓→'
}
}
Beacon.get_block_root(block_id)
>>> beacon.get_block_root(1)
{
'data': {
'root': '0x30c04689dd4f6cd4d56eb78f72727d2d16d8b6346724e4a88f546875f11b750d'
}
}
Beacon.get_block_attestations(block_id)
>>> beacon.get_block_attestations(1)
{
'data': [
{
'aggregation_bits': '0x0080020004000000008208000102000905',
'data': {
'slot': '0',
'index': '7',
'beacon_block_root':
˓→'0x6a89af5df908893eedbed10ba4c13fc13d5653ce57db637e3bfded73a987bb87',
},
'target': {
'epoch': '0',
'root':
˓→'0x6a89af5df908893eedbed10ba4c13fc13d5653ce57db637e3bfded73a987bb87'
}
},
'signature':
˓→'0x967dd2946358db7e426ed19d4576bc75123520ef6a489ca50002222070ee4611f9cef394e5e3071236a93b825f18a4
˓→'
},
...
]
}
Beacon.get_attestations()
>>> beacon.get_attestations()
{'data': []}
Beacon.get_attester_slashings()
>>> beacon.get_attester_slashings()
{'data': []}
Beacon.get_proposer_slashings()
>>> beacon.get_proposer_slashings()
{'data': []}
Beacon.get_voluntary_exits()
>>> beacon.get_voluntary_exits()
{'data': []}
Beacon.get_fork_schedule()
>>> beacon.get_fork_schedule()
{
'data': [
{
'previous_version': '0x00002009',
'current_version': '0x00002009',
'epoch': '0'
}
]
}
Beacon.get_spec()
>>> beacon.get_spec()
{
'data': {
'DEPOSIT_CONTRACT_ADDRESS': '0x8c5fecdC472E27Bc447696F431E425D02dd46a8c',
'MIN_ATTESTATION_INCLUSION_DELAY': '1',
'SLOTS_PER_EPOCH': '32',
'SHUFFLE_ROUND_COUNT': '90',
'MAX_EFFECTIVE_BALANCE': '32000000000',
'DOMAIN_BEACON_PROPOSER': '0x00000000',
'MAX_ATTESTER_SLASHINGS': '2',
'DOMAIN_SELECTION_PROOF': '0x05000000',
...
}
}
Beacon.get_deposit_contract()
>>> beacon.get_deposit_contract()
{
'data': {
'chain_id': '5',
'address': '0x8c5fecdC472E27Bc447696F431E425D02dd46a8c'
}
}
Beacon.get_beacon_state(state_id='head')
>>> beacon.get_beacon_state()
{
'data': {
'genesis_time': '1',
'genesis_validators_root':
˓→'0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2',
'slot': '1',
'fork': {
'previous_version': '0x00000000',
'current_version': '0x00000000',
'epoch': '1'
},
'latest_block_header': {
'slot': '1',
'proposer_index': '1',
'parent_root':
˓→'0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2',
'state_root':
˓→'0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2',
'body_root':
˓→'0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2'
},
'block_roots': [
˓→'0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2'],
'historical_roots': [
˓→'0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2'],
'eth1_data': {
'deposit_root':
˓→'0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2',
'deposit_count': '1',
'block_hash':
˓→'0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2'
},
'eth1_data_votes': [...],
'eth1_deposit_index': '1',
'validators': [...],
'balances': [...],
'randao_mixes': [...],
'slashings': [...],
'previous_epoch_attestations': [...],
'current_epoch_attestations': [...],
'justification_bits': '0x0f',
'previous_justified_checkpoint': {
'epoch': '5736',
'root': '0xec7ef54f1fd81bada8170dd0cb6be8216f8ee2f445e6936f95f5c6894a4a3b38'
},
'current_justified_checkpoint': {
'epoch': '5737',
'root': '0x781f0166e34c361ce2c88070c1389145abba2836edcb446338a2ca2b0054826e'
},
'finalized_checkpoint': {
'epoch': '5736',
'root': '0xec7ef54f1fd81bada8170dd0cb6be8216f8ee2f445e6936f95f5c6894a4a3b38'
}
}
}
Beacon.get_beacon_heads()
>>> beacon.get_beacon_heads()
{
'data': [
{
'slot': '221600',
'root': '0x9987754077fe6100a60c75d81a51b1ef457d019404d1546a66f4f5d6c23fae45'
}
]
}
Beacon.get_node_identity()
>>> beacon.get_node_identity()
{
'data': {
(continues on next page)
˓→6TKMx1BpGlAhGV0aDKQOwiHlQAAIAn__________4JpZIJ2NIJpcIR_
˓→AAABiXNlY3AyNTZrMaEDdVT4g1gw86BfbrtLCq2fRBlG0AnMxsXtAQgA327S5FeDdGNwgiMog3VkcIIjKA
˓→',
'p2p_addresses': ['/ip4/127.0.0.1/tcp/9000/p2p/
˓→16Uiu2HAmLZ1CYVFKpa3wwn4cnknZqosum8HX3GHDhUpEULQc9ixE'],
'discovery_addresses': ['/ip4/127.0.0.1/udp/9000/p2p/
˓→16Uiu2HAmLZ1CYVFKpa3wwn4cnknZqosum8HX3GHDhUpEULQc9ixE'],
Beacon.get_peers()
>>> beacon.get_peers()
{
'data': [
{
'peer_id': '16Uiu2HAkw1yVqF3RtMCBHMbkLZbNhfGcTUdD6Uo4X3wfzPhGVnqv',
'address': '/ip4/3.127.23.51/tcp/9000',
'state': 'connected',
'direction': 'outbound'
},
{
'peer_id': '16Uiu2HAmEJHiCzgS8GwiEYLyM3d148mzvZ9iZzsz8yqayWVPANMG',
'address': '/ip4/3.88.7.240/tcp/9000',
'state': 'connected',
'direction': 'outbound'
}
]
}
Beacon.get_peer(peer_id)
>>> beacon.get_peer('16Uiu2HAkw1yVqF3RtMCBHMbkLZbNhfGcTUdD6Uo4X3wfzPhGVnqv')
{
'data': {
'peer_id': '16Uiu2HAkw1yVqF3RtMCBHMbkLZbNhfGcTUdD6Uo4X3wfzPhGVnqv',
'address': '/ip4/3.127.23.51/tcp/9000',
'state': 'connected',
'direction': 'outbound'
}
}
Beacon.get_health()
>>> beacon.get_health()
200
Beacon.get_version()
>>> beacon.get_version()
{
'data': {
'version': 'teku/v20.12.0+9-g9392008/osx-x86_64/adoptopenjdk-java-15'
}
}
Beacon.get_syncing()
>>> beacon.get_syncing()
{
'data': {
'head_slot': '222270',
'sync_distance': '190861'
}
}
The web3.pm object exposes methods to interact with Packages as defined by ERC 1123.
• To learn more about the EthPM spec, visit the spec or the documentation.
Warning: The web3.pm API is still under development and likely to change quickly.
Now is a great time to get familiar with the API, and test out writing code that uses some of the great upcoming
features.
By default, access to this module has been turned off in the stable version of web3.py:
>>> from web3 import Web3, IPCProvider
>>> w3 = Web3(IPCProvider(...))
>>> w3.pm
...
AttributeError: The Package Management feature is disabled by default ...
2.23.1 Methods
w3.ens.setup_address(ens_name, w3.pm.registry.address)
If you want to implement your own registry and use it with web3.pm, you must create a subclass that inher-
its from ERC1319Registry, and implements all the ERC 1319 standard methods prefixed with an underscore in
ERC1319Registry. Then, you have to manually set it as the registry attribute on web3.pm.
One reason a user might want to create their own Registry class is if they build a custom Package Registry smart
contract that has features beyond those specified in ERC 1319. For example, the ability to delete a release or some
micropayment feature. Rather than accessing those functions directly on the contract instance, they can create a custom
ERC1319Registry subclass to easily call both the standard & custom methods.
The web3.net object exposes methods to interact with the RPC APIs under the net_ namespace.
2.24.1 Properties
>>> web3.net.listening
True
web3.net.peer_count()
..py:property::
>>> web3.net.peer_count
1
web3.net.version()
..py:property::
>>> web3.net.version
'8996'
The web3.geth.miner object exposes methods to interact with the RPC APIs under the miner_ namespace that are
supported by the Geth client.
Warning: Deprecated: The Geth client deprecated the miner namespace because mining was switched off during
the proof-of-stake transition.
2.25.1 Methods
>>> web3.geth.miner.make_dag(10000)
GethMiner.set_extra(extra)
>>> web3.geth.miner.set_extra('abcdefghijklmnopqrstuvwxyzABCDEF')
GethMiner.set_gas_price(gas_price)
>>> web3.geth.miner.set_gas_price(19999999999)
GethMiner.start(num_threads)
>>> web3.geth.miner.start(2)
GethMiner.stop()
>>> web3.geth.miner.stop()
GethMiner.start_auto_dag()
>>> web3.geth.miner.start_auto_dag()
GethMiner.stop_auto_dag()
>>> web3.geth.miner.stop_auto_dag()
The web3.geth object exposes modules that enable you to interact with the JSON-RPC endpoints supported by Geth
that are not defined in the standard set of Ethereum JSONRPC endpoints according to EIP 1474.
>>> web3.geth.admin.datadir()
'/Users/snakecharmers/Library/Ethereum'
web3.geth.admin.node_info()
>>> web3.geth.admin.node_info()
{
'enode': 'enode://
˓→e54eebad24dce1f6d246bea455ffa756d97801582420b9ed681a2ea84bf376d0bd87ae8dd6dc06cdb862a2ca89ecabe1b
˓→',
'id':
˓→'e54eebad24dce1f6d246bea455ffa756d97801582420b9ed681a2ea84bf376d0bd87ae8dd6dc06cdb862a2ca89ecabe1
˓→',
'ip': '::',
'listenAddr': '[::]:30303',
'name': 'Geth/v1.4.11-stable-fed692f6/darwin/go1.7',
'ports': {'discovery': 30303, 'listener': 30303},
'protocols': {
'eth': {
'difficulty': 57631175724744612603,
'genesis':
˓→'0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3',
'head':
˓→'0xaaef6b9dd0d34088915f4c62b6c166379da2ad250a88f76955508f7cc81fb796',
'network': 1,
},
},
}
web3.geth.admin.peers()
>>> web3.geth.admin.peers()
[
{
'caps': ['eth/63'],
'id':
˓→'146e8e3e2460f1e18939a5da37c4a79f149c8b9837240d49c7d94c122f30064e07e4a42ae2c2992d0f8e7e6f68a30e7e
˓→',
'name': 'Geth/v1.4.10-stable/windows/go1.6.2',
'network': {
'localAddress': '10.0.3.115:64478',
'remoteAddress': '72.208.167.127:30303',
},
'protocols': {
'eth': {
'difficulty': 17179869184,
'head':
˓→'0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3',
'version': 63,
},
(continues on next page)
˓→',
'name': 'Geth/v1.4.10-stable-5f55d95a/linux/go1.5.1',
'network': {
'localAddress': '10.0.3.115:64784',
'remoteAddress': '60.205.92.119:30303',
},
'protocols': {
'eth': {
'difficulty': 57631175724744612603,
'head':
˓→'0xaaef6b9dd0d34088915f4c62b6c166379da2ad250a88f76955508f7cc81fb796',
'version': 63,
},
},
},
...
]
web3.geth.admin.add_peer(node_url)
>>> web3.geth.admin.add_peer('enode://
˓→e54eebad24dce1f6d246bea455ffa756d97801582420b9ed681a2ea84bf376d0bd87ae8dd6dc06cdb862a2ca89ecabe1b
˓→71.255.237:30303')
True
>>> web3.geth.admin.start_http()
True
>>> web3.geth.admin.start_ws()
True
web3.geth.admin.stop_http()
>>> web3.geth.admin.stop_http()
True
web3.geth.admin.stop_ws()
>>> web3.geth.admin.stop_ws()
True
˓→ '0x8eb502165dec388af1c45c4bc835fd1852eaf358316ae5d248a40af8cd8dd7dc6373a6e606d8b411f788718b8b09a6
˓→ '
>>> web3.geth.personal.ec_recover('snakesnax',
˓→'0x8eb502165dec388af1c45c4bc835fd1852eaf358316ae5d248a40af8cd8dd7dc6373a6e606d8b411f788718b8b09a6
˓→')
'0x9ad3c920dce5cea9a31d69467bb8d7c954e5acff'
web3.geth.personal.import_raw_key(private_key, passphrase)
web3.geth.personal.list_accounts()
>>> web3.geth.personal.list_accounts()
['0x582AC4D8929f58c217d4a52aDD361AE470a8a4cD']
web3.geth.personal.list_wallets()
>>> web3.geth.personal.list_wallets()
[{
accounts: [{
address: "0x44f705f3c31017856777f2931c2f09f240dd800b",
url: "keystore:///path/to/keystore/UTC--2020-03-30T23-24-43.133883000Z--
˓→44f705f3c31017856777f2931c2f09f240dd800b"
}],
status: "Unlocked",
url: "keystore:///path/to/keystore/UTC--2020-03-30T23-24-43.133883000Z--
˓→44f705f3c31017856777f2931c2f09f240dd800b"
}]
web3.geth.personal.lock_account(account)
>>> web3.geth.personal.lock_account('0x582AC4D8929f58c217d4a52aDD361AE470a8a4cD')
True
web3.geth.personal.new_account(passphrase)
>>> web3.geth.personal.new_account('the-passphrase')
'0x582AC4D8929f58c217d4a52aDD361AE470a8a4cD'
web3.geth.personal.send_transaction(transaction, passphrase)
˓→'0x8eb502165dec388af1c45c4bc835fd1852eaf358316ae5d248a40af8cd8dd7dc6373a6e606d8b411f788718b8b09a6
˓→'
>>> web3.geth.personal.unlock_account('0x582AC4D8929f58c217d4a52aDD361AE470a8a4cD',
˓→'wrong-passphrase')
False
>>> web3.geth.personal.unlock_account('0x582AC4D8929f58c217d4a52aDD361AE470a8a4cD',
˓→'the-passphrase')
True
The web3.geth.txpool object exposes methods to interact with the RPC APIs under the txpool_ namespace. These
methods are only exposed under the geth namespace since they are not standard.
The following methods are available on the web3.geth.txpool namespace.
TxPool.inspect()
>>> web3.geth.txpool.inspect()
{
'pending': {
'0x26588a9301b0428d95e6Fc3A5024fcE8BEc12D51': {
31813: ["0x3375Ee30428b2A71c428afa5E89e427905F95F7e: 0 wei + 500000 ×␣
˓→20000000000 gas"]
},
'0x2a65Aca4D5fC5B5C859090a6c34d164135398226': {
563662: ["0x958c1Fa64B34db746925c6F8a3Dd81128e40355E: 1051546810000000000␣
˓→wei + 90000 × 20000000000 gas"],
},
'0xb18F9d01323e150096650ab989CfecD39D757Aec': {
777: ["0xcD79c72690750F079ae6AB6ccd7e7aEDC03c7720: 0 wei + 1000000 ×␣
˓→20000000000 gas"]
},
'0xB2916C870Cf66967B6510B76c07E9d13a5D23514': {
2: ["0x576f25199D60982A8f31A8DfF4da8aCB982e6ABa: 26000000000000000000 wei␣
˓→+ 90000 × 20000000000 gas"]
},
'0xBc0CA4f217E052753614d6B019948824d0d8688B': {
0: ["0x2910543Af39abA0Cd09dBb2D50200b3E800A63D2: 1000000000000000000 wei␣
˓→+ 50000 × 1171602790622 gas"]
},
'0xea674fdde714fd979de3edf0f56aa9716b898ec8': {
70148: ["0xe39c55ead9f997f7fa20ebe40fb4649943d7db66: 1000767667434026200␣
˓→wei + 90000 × 20000000000 gas"]
}
},
'queued': {
'0x0F6000De1578619320aBA5e392706b131FB1dE6f': {
6: ["0x8383534d0bcd0186d326C993031311c0Ac0D9B2d: 9000000000000000000 wei␣
˓→+ 21000 × 20000000000 gas"]
},
'0x5b30608c678e1ac464A8994C3B33E5CdF3497112': {
6: ["0x9773547e27f8303C87089dc42D9288aa2B9d8F06: 50000000000000000000 wei␣
˓→+ 90000 × 50000000000 gas"]
},
'0x976A3Fc5d6f7d259EBfb4cc2Ae75115475E9867C': {
3: ["0x346FB27dE7E7370008f5da379f74dd49F5f2F80F: 140000000000000000 wei +␣
˓→90000 × 20000000000 gas"]
},
'0x9B11bF0459b0c4b2f87f8CEBca4cfc26f294B63A': {
2: ["0x24a461f25eE6a318BDef7F33De634A67bb67Ac9D: 17000000000000000000 wei␣
˓→+ 90000 × 50000000000 gas"],
}
}
}
TxPool.status()
{
pending: 10,
queued: 7,
}
TxPool.content()
>>> web3.geth.txpool.content()
{
'pending': {
'0x0216D5032f356960Cd3749C31Ab34eEFF21B3395': {
806: [{
'blockHash':
˓→"0x0000000000000000000000000000000000000000000000000000000000000000",
'blockNumber': None,
'from': "0x0216D5032f356960Cd3749C31Ab34eEFF21B3395",
'gas': "0x5208",
'gasPrice': None,
'hash': "0xaf953a2d01f55cfe080c0c94150a60105e8ac3d51153058a1f03dd239dd08586
˓→",
'input': "0x",
'maxFeePerGas': '0x77359400',
'maxPriorityFeePerGas': '0x3b9aca00',
'nonce': "0x326",
'to': "0x7f69a91A3CF4bE60020fB58B893b7cbb65376db8",
'transactionIndex': None,
'value': "0x19a99f0cf456000"
}]
},
'0x24d407e5A0B506E1Cb2fae163100B5DE01F5193C': {
34: [{
'blockHash':
˓→"0x0000000000000000000000000000000000000000000000000000000000000000",
'blockNumber': None,
'from': "0x24d407e5A0B506E1Cb2fae163100B5DE01F5193C",
'gas': "0x44c72",
'gasPrice': None,
'hash': "0xb5b8b853af32226755a65ba0602f7ed0e8be2211516153b75e9ed640a7d359fe
˓→",
'input':
˓→"0xb61d27f600000000000000000000000024d407e5a0b506e1cb2fae163100b5de01f5193c0000000000000000000000
˓→",
'maxFeePerGas': '0x77359400',
'maxPriorityFeePerGas': '0x3b9aca00',
'nonce': "0x22",
'to': "0x7320785200f74861B69C49e4ab32399a71b34f1a",
'transactionIndex': None,
'value': "0x0"
}]
}
(continues on next page)
'blockNumber': None,
'from': "0x976A3Fc5d6f7d259EBfb4cc2Ae75115475E9867C",
'gas': "0x15f90",
'gasPrice': None,
'hash': "0x57b30c59fc39a50e1cba90e3099286dfa5aaf60294a629240b5bbec6e2e66576
˓→",
'input': "0x",
'maxFeePerGas': '0x77359400',
'maxPriorityFeePerGas': '0x3b9aca00',
'nonce': "0x3",
'to': "0x346FB27dE7E7370008f5da379f74dd49F5f2F80F",
'transactionIndex': None,
'value': "0x1f161421c8e0000"
}]
},
'0x9B11bF0459b0c4b2f87f8CEBca4cfc26f294B63A': {
2: [{
'blockHash':
˓→"0x0000000000000000000000000000000000000000000000000000000000000000",
'blockNumber': None,
'from': "0x9B11bF0459b0c4b2f87f8CEBca4cfc26f294B63A",
'gas': "0x15f90",
'gasPrice': None,
'hash': "0x3a3c0698552eec2455ed3190eac3996feccc806970a4a056106deaf6ceb1e5e3
˓→",
'input': "0x",
'maxFeePerGas': '0x77359400',
'maxPriorityFeePerGas': '0x3b9aca00',
'nonce': "0x2",
'to': "0x24a461f25eE6a318BDef7F33De634A67bb67Ac9D",
'transactionIndex': None,
'value': "0xebec21ee1da40000"
}],
6: [{
'blockHash':
˓→"0x0000000000000000000000000000000000000000000000000000000000000000",
'blockNumber': None,
'from': "0x9B11bF0459b0c4b2f87f8CEBca4cfc26f294B63A",
'gas': "0x15f90",
'gasPrice': None,
'hash': "0xbbcd1e45eae3b859203a04be7d6e1d7b03b222ec1d66dfcc8011dd39794b147e
˓→",
'input': "0x",
'maxFeePerGas': '0x77359400',
'maxPriorityFeePerGas': '0x3b9aca00',
'nonce': "0x6",
(continues on next page)
'blockNumber': None,
'from': "0x9B11bF0459b0c4b2f87f8CEBca4cfc26f294B63A",
'gas': "0x15f90",
'gasPrice': None,
'hash': "0x60803251d43f072904dc3a2d6a084701cd35b4985790baaf8a8f76696041b272
˓→",
'input': "0x",
'maxFeePerGas': '0x77359400',
'maxPriorityFeePerGas': '0x3b9aca00',
'nonce': "0x6",
'to': "0x8DB7b4e0ECB095FBD01Dffa62010801296a9ac78",
'transactionIndex': None,
'value': "0xebe866f5f0a06000"
}],
}
}
}
The web3.tracing object exposes modules that enable you to interact with the JSON-RPC trace_ endpoints sup-
ported by Erigon and Nethermind.
The following methods are available on the web3.tracing namespace:
web3.tracing.trace_replay_transaction()
web3.tracing.trace_replay_block_transactions()
web3.tracing.trace_filter()
web3.tracing.trace_block()
web3.tracing.trace_transaction()
web3.tracing.trace_call()
web3.tracing.trace_raw_transaction()
2.28 Utils
2.28.1 ABI
utils.get_abi_input_names(abi)
Return the input names for an ABI function or event.
utils.get_abi_output_names(abi)
Return the output names an ABI function or event.
2.28.2 Address
utils.get_create_address(sender, nonce)
Return the checksummed contract address generated by using the CREATE opcode by a sender address with a
given nonce.
utils.get_create2_address(sender, salt, init_code)
Return the checksummed contract address generated by using the CREATE2 opcode by a sender address with a
given salt and contract bytecode. See EIP-1014.
2.28.3 Caching
class utils.SimpleCache
The main cache class being used internally by web3.py. In some cases, it may prove useful to set your own cache
size and pass in your own instance of this class where supported.
utils.handle_offchain_lookup(offchain_lookup_payload, transaction)
Handle OffchainLookup reverts on contract function calls manually. For an example, see CCIP Read support
for offchain lookup within the examples section.
utils.async_handle_offchain_lookup(offchain_lookup_payload, transaction)
The async version of the handle_offchain_lookup() utility method described above.
Warning: Gas price strategy is only supported for legacy transactions. The London fork introduced
maxFeePerGas and maxPriorityFeePerGas transaction parameters which should be used over gasPrice when-
ever possible.
For Ethereum (legacy) transactions, gas price is a delicate property. For this reason, Web3 includes an API for config-
uring it.
The Gas Price API allows you to define Web3’s behaviour for populating the gas price. This is done using a “Gas Price
Strategy” - a method which takes the Web3 object and a transaction dictionary and returns a gas price (denominated in
wei).
To retrieve the gas price using the selected strategy simply call generate_gas_price()
>>> web3.eth.generate_gas_price()
20000000000
A gas price strategy is implemented as a python method with the following signature:
The method must return a positive integer representing the gas price in wei.
To demonstrate, here is a rudimentary example of a gas price strategy that returns a higher gas price when the value of
the transaction is higher than 1 Ether.
w3 = Web3(...)
w3.eth.set_gas_price_strategy(value_based_gas_price_strategy)
web3.gas_strategies.rpc.rpc_gas_price_strategy(web3, transaction_params=None)
Makes a call to the JSON-RPC eth_gasPrice method which returns the gas price configured by the connected
Ethereum node.
web3.gas_strategies.time_based.construct_time_based_gas_price_strategy(max_wait_seconds,
sample_size=120,
probability=98,
weighted=False)
Constructs a strategy which will compute a gas price such that the transaction will be mined within a number
of seconds defined by max_wait_seconds with a probability defined by probability. The gas price is com-
puted by sampling sample_size of the most recently mined blocks. If weighted=True, the block time will be
weighted towards more recently mined blocks.
• max_wait_seconds The desired maximum number of seconds the transaction should take to mine.
• sample_size The number of recent blocks to sample
• probability An integer representation of the desired probability that the transaction will be mined within
max_wait_seconds. 0 means 0% and 100 means 100%.
The following ready to use versions of this strategy are available.
• web3.gas_strategies.time_based.fast_gas_price_strategy: Transaction mined within 60 sec-
onds.
• web3.gas_strategies.time_based.medium_gas_price_strategy: Transaction mined within 5
minutes.
• web3.gas_strategies.time_based.slow_gas_price_strategy: Transaction mined within 1 hour.
• web3.gas_strategies.time_based.glacial_gas_price_strategy: Transaction mined within 24
hours.
Warning: Due to the overhead of sampling the recent blocks it is recommended that a caching solution be
used to reduce the amount of chain data that needs to be re-fetched for each request.
w3 = Web3()
w3.eth.set_gas_price_strategy(medium_gas_price_strategy)
w3.middleware_onion.add(middleware.time_based_cache_middleware)
w3.middleware_onion.add(middleware.latest_block_based_cache_middleware)
w3.middleware_onion.add(middleware.simple_cache_middleware)
async setup_name(name: str, address: ChecksumAddress | None = None, transact: TxParams | None =
None) → HexBytes
Set up the address for reverse lookup, aka “caller ID”. After successful setup, the method name() will
return name when supplied with address.
Parameters
• name (str) – ENS name that address will point to
• address (str) – address to set up, in checksum format
• transact (dict) – the transaction configuration, like in send_transaction()
Raises
• AddressMismatch – if the name does not already point to the address
• InvalidName – if name has invalid syntax
• UnauthorizedError – if 'from' in transact does not own name
• UnownedName – if no one owns name
async owner(name: str) → ChecksumAddress
Get the owner of a name. Note that this may be different from the deed holder in the ‘.eth’ registrar. Learn
more about the difference between deed and name ownership in the ENS Managing Ownership docs
Parameters
name (str) – ENS name to look up
Returns
owner address
Return type
str
async setup_owner(name: str, new_owner: ChecksumAddress = <object object>, transact: TxParams |
None = None) → ChecksumAddress | None
Set the owner of the supplied name to new_owner.
For typical scenarios, you’ll never need to call this method directly, simply call setup_name() or
setup_address(). This method does not set up the name to point to an address.
If new_owner is not supplied, then this will assume you want the same owner as the parent domain.
If the caller owns parentname.eth with no subdomains and calls this method with sub.parentname.
eth, then sub will be created as part of this call.
Parameters
• name (str) – ENS name to set up
• new_owner – account that will own name. If None, set owner to empty addr. If not speci-
fied, name will point to the parent domain owner’s address.
• transact (dict) – the transaction configuration, like in send_transaction()
Raises
• InvalidName – if name has invalid syntax
• UnauthorizedError – if 'from' in transact does not own name
Returns
the new owner’s address
exception ens.exceptions.ENSException
Bases: Exception
Base class for all ENS Errors
exception ens.exceptions.AddressMismatch
Bases: ENSException
In order to set up reverse resolution correctly, the ENS name should first point to the address. This exception is
raised if the name does not currently point to the address.
exception ens.exceptions.InvalidName
Bases: IDNAError, ENSException
This exception is raised if the provided name does not meet the normalization standards specified in ENSIP-15.
exception ens.exceptions.UnauthorizedError
Bases: ENSException
Raised if the sending account is not the owner of the name you are trying to modify. Make sure to set from in
the transact keyword argument to the owner of the name.
exception ens.exceptions.UnownedName
Bases: ENSException
Raised if you are trying to modify a name that no one owns.
If working on a subdomain, make sure the subdomain gets created first with setup_address().
exception ens.exceptions.ResolverNotFound
Bases: ENSException
Raised if no resolver was found for the name you are trying to resolve.
exception ens.exceptions.UnsupportedFunction
Bases: ENSException
Raised if a resolver does not support a particular method.
exception ens.exceptions.BidTooLow
Bases: ENSException
Raised if you bid less than the minimum amount
exception ens.exceptions.InvalidBidHash
Bases: ENSException
Raised if you supply incorrect data to generate the bid hash.
exception ens.exceptions.InvalidLabel
Bases: ENSException
Raised if you supply an invalid label
exception ens.exceptions.OversizeTransaction
Bases: ENSException
Raised if a transaction you are trying to create would cost so much gas that it could not fit in a block.
For example: when you try to start too many auctions at once.
exception ens.exceptions.UnderfundedBid
Bases: ENSException
Raised if you send less wei with your bid than you declared as your intent to bid.
exception ens.exceptions.ENSValidationError
Bases: ENSException, ValidationError
Raised if there is a validation error
2.31 Constants
2.31.1 Strings
2.31.2 Int
web3.py and the Ethereum Python ecosystem have an active community of developers and educators. Here you’ll find
libraries, tutorials, examples, courses and other learning material.
Warning: Links on this page are community submissions and are not vetted by the team that maintains web3.py.
As always, DYOR (Do Your Own Research).
2.32.2 Courses
2.32.3 Tutorials
• Ape - The Ethereum development framework for Python Developers, Data Scientists, and Security Professionals
• Titanoboa - A Vyper interpreter and testing framework
• Wake - A Python-based development and testing framework for Solidity
• Brownie - [No longer actively maintained] A Python-based development and testing framework for smart con-
tracts targeting EVM
2.32.7 Libraries
• Web3 Ethereum DeFi - Library for DeFi trading and protocols (Uniswap, PancakeSwap, Sushi, Aave, Chainlink)
• lighter-v1-python - Lighter.xyz DEX client for Python
• uniswap-python - Library lets you easily retrieve prices and make trades on all Uniswap versions.
• pyWalletConnect - WalletConnect implementation for wallets in Python
• dydx-v3-python - Python client for dYdX v3
• Lido Python SDK - Library with which you can get all Lido validator’s signatures and check their validity
2.32.8 Applications
• Curve Finance
• Yearn Finance
• StakeWise Oracle
• ape-hackathon-kit - Ape project template with a web front-end (Next.js, Tailwind, RainbowKit, wagmi)
• eth-flogger - Sample web app utilizing async web3.py, Flask, SQLite, Sourcify
• Temo - Sample terminal app utilizing async web3py, Textual, Anvil
• web3py-discord-bot - Sample Discord bot utilizing websockets, eth_subscribe, and discord.py
• py-signer - Demo of typed data message signing (EIP-712) with eth-account and Ape
2.33 Contributing
Thanks for your interest in contributing to web3.py! Read on to learn what would be helpful and how to go about it. If
you get stuck along the way, reach for help in the Python Discord server.
Without code:
• Answer user questions within GitHub issues, Stack Overflow, or the Python Discord server.
• Write or record tutorial content.
• Improve our documentation (including typo fixes).
• Open an issue on GitHub to document a bug. Include as much detail as possible, e.g., how to reproduce the issue
and any exception messages.
With code:
• Fix a bug that has been reported in an issue.
• Add a feature that has been documented in an issue.
• Add a missing test case.
Warning: Before you start: always ask if a change would be desirable or let us know that you plan to work on
something! We don’t want to waste your time on changes we can’t accept or duplicated effort.
Note: Use of a virtual environment is strongly advised for minimizing dependency issues. See this article for usage
patterns.
All pull requests are made from a fork of the repository; use the GitHub UI to create a fork. web3.py depends on
submodules, so when you clone your fork to your local machine, include the --recursive flag:
Using Docker
Developing within Docker is not required, but if you prefer that workflow, use the sandbox container provided in the
docker-compose.yml file.
To start up the test environment, run:
$ docker compose up -d
This will build a Docker container set up with an environment to run the Python test code.
Note: This container does not have go-ethereum installed, so you cannot run the go-ethereum test suite.
You can run arbitrary commands inside the Docker container by using the bash -c prefix.
We value code consistency. To ensure your contribution conforms to the style being used in this project, we encourage
you to read our style guide.
We use Black for linting. To ignore the commits that introduced Black in git history, you can configure your git
environment like so:
This code base makes use of type hints. Type hints make it easy to prevent certain types of bugs, enable richer tooling,
and enhance the documentation, making the code easier to follow.
All new code is required to include type hints, with the exception of tests.
All parameters, as well as the return type of functions, are expected to be typed, with the exception of self and cls
as seen in the following example.
$ pytest
However, running the entire test suite takes a very long time and is generally impractical. Typically, you’ll just want to
run a subset instead, like:
$ pytest tests/core/eth-module/test_accounts.py
You can use tox to run all the tests for a given version of Python:
$ tox -e py37-core
Linting is also performed by the CI. You can save yourself some time by checking for linting errors locally:
$ make lint
It is important to understand that each pull request must pass the full test suite as part of the CI check. This test suite
will run in the CI anytime a pull request is opened or updated.
We strongly encourage contributors to write good tests for their code as part of the code review process. This helps
ensure that your code is doing what it should be doing.
We strongly encourage you to use our existing tests for both guidance and homogeneity / consistency across our tests.
We use pytest for our tests. For more specific pytest guidance, please refer to the pytest documentation.
Within the pytest scope, conftest.py files are used for common code shared between modules that exist within the
same directory as that particular conftest.py file.
Our unit tests are grouped together with tests against the eth-tester library, using the py-evm library as a backend,
via the EthereumTesterProvider.
These tests live under appropriately named child directories within the /tests directory. The core of these tests live
under /tests/core. Do your best to follow the existing structure when adding a test and make sure that its location
makes sense.
Integration Testing
Our integration test suite setup lives under the /tests/integration directory. The integration test suite is dependent
on what we call “fixtures” (not to be confused with pytest fixtures). These zip file fixtures, which also live in the /
tests/integration directory, are configured to run the specific client we are testing against along with a genesis
configuration that gives our tests some pre-determined useful objects (like unlocked, pre-loaded accounts) to be able
to interact with the client when we run our tests.
The parent /integration directory houses some common configuration shared across all client tests, whereas the
/go_ethereum directory houses common code to be shared across geth-specific provider tests. Though the setup
and run configurations exist across the different files within /tests/integration, our integration module tests are
written across different files within /web3/_utils/module_testing.
• common.py files within the client directories contain code that is shared across all provider tests (http, ipc, and
ws). This is mostly used to override tests that span across all providers.
• conftest.py files within each of these directories contain mostly code that can be used by all test files that exist
within the same directory or subdirectories of the conftest.py file. This is mostly used to house pytest fixtures
to be shared among our tests. Refer to the pytest documentation on fixtures for more information.
• test_{client}_{provider}.py files (e.g. test_goethereum_http.py) are where client-and-provider-
specific test configurations exist. This is mostly used to override tests specific to the provider type for the re-
spective client.
Contracts used for testing exist under web3/_utils/contract_sources. These contracts get compiled via the
compile_contracts.py script in the same directory. To use this script, simply pass the Solidity version to be used
to compile the contracts as an argument at the command line.
Arguments for the script are:
-v or –version Solidity version to be used to compile the contracts. If
blank, the script uses the latest available version from solcx.
-f or –filename If left blank, all .sol files will be compiled and the
respective contract data will be generated. Pass in a specific .sol filename here to compile just one file.
To run the script, you will need the py-solc-x library for compiling the files as well as black for code formatting.
You can install those independently or install the full [dev] package extra as shown below.
The following example compiles all the contracts and generates their respective contract data that is used across
our test files for the test suites. This data gets generated within the contract_data subdirectory within the
contract_sources folder.
$ cd ../web3.py/web3/_utils/contract_sources
$ python compile_contracts.py -v 0.8.17
Compiling OffchainLookup
...
...
reformatted ...
To compile and generate contract data for only one .sol file, specify using the filename with the -f (or --filename)
argument flag.
$ cd ../web3.py/web3/_utils/contract_sources
$ python compile_contracts.py -v 0.8.17 -f OffchainLookup.sol
Compiling OffchainLookup.sol
reformatted ...
If there is any contract data that is not generated via the script but is important to pass on to the integration tests,
the _custom_contract_data.py file within the contract_data subdirectory can be used to store that information
when appropriate.
Be sure to re-generate the integration test fixture after running the script to update the contract bytecodes for the inte-
gration test suite - see the Generating New Fixtures section below.
To import and test an unreleased version of web3.py in another context, you can install it from your development
directory:
2.33.8 Documentation
Good documentation will lead to quicker adoption and happier users. Please check out our guide on how to create
documentation for the Python Ethereum ecosystem.
Pull requests generate their own preview of the latest documentation at https://web3py--<pr-number>.org.
readthedocs.build/en/<pr-number>/.
It’s a good idea to make pull requests early on. A pull request represents the start of a discussion, and doesn’t necessarily
need to be the final, finished submission.
See GitHub’s documentation for working on pull requests.
Once you’ve made a pull request take a look at the Circle CI build status in the GitHub interface and make sure all tests
are passing. In general, pull requests that do not pass the CI build yet won’t get reviewed unless explicitly requested.
If the pull request introduces changes that should be reflected in the release notes, please add a newsfragment file as
explained here.
If possible, the change to the release notes file should be included in the commit that introduces the feature or bugfix.
Our integration tests make use of Geth private networks. When new versions of the client software are introduced, new
fixtures should be generated.
Before generating new fixtures, make sure you have the test dependencies installed:
Note: A “fixture” is a pre-synced network. It’s the result of configuring and running a client, deploying the test
contracts, and saving the resulting state for testing web3.py functionality against.
Geth Fixtures
1. Install the desired Geth version on your machine locally. We recommend py-geth for this purpose, because it
enables you to easily manage multiple versions of Geth.
Note that py-geth will need updating to support each new Geth version as well. Adding newer Geth versions
to py-geth is straightforward; see past commits for a template.
If py-geth has the Geth version you need, install that version locally. For example:
2. Specify the Geth binary and run the fixture creation script (from within the web3.py directory):
3. The output of this script is your fixture, a zip file, which is now stored in /tests/integration/. Update the
/tests/integration/go_ethereum/conftest.py and /web3/tools/benchmark/node.py files to point
to this new fixture. Delete the old fixture.
4. Run the tests. To ensure that the tests run with the correct Geth version locally, you may again include the
GETH_BINARY environment variable.
5. Update the geth_version and pygeth_version parameter defaults in /.circleci/config.yml to match
the go-ethereum version used to generate the test fixture and the py-geth version that supports installing it.
Occasionally you’ll want to have CI run the test suite against an unreleased version of Geth, for example, to test up-
coming hard fork changes. The workflow described below is for testing only, i.e., open a PR, let CI run the tests, but
the changes should only be merged into main once the Geth release is published or you have some workaround that
doesn’t require test fixtures built from an unstable client.
1. Configure tests/integration/generate_fixtures/go_ethereum/common.py as needed.
2. Geth automagically compiles new builds for every commit that gets merged into the codebase. Download the
desired build from the develop builds.
3. Build your test fixture, passing in the binary you just downloaded via GETH_BINARY. Don’t forget to update the
/tests/integration/go_ethereum/conftest.py file to point to your new fixture.
4. Our CI runs on Ubuntu, so download the corresponding 64-bit Linux develop build, then add it to the root of
your web3.py directory. Rename the binary custom_geth.
5. In .circleci/config.yml, update jobs relying on geth_steps, to instead use custom_geth_steps.
6. Create a PR and let CI do its thing.
2.33.11 Releasing
Before releasing a new version, build and test the package that will be released. There’s a script to build and install the
wheel locally, then generate a temporary virtualenv for smoke testing:
$ make package
$ make docs
After confirming that the release package looks okay, compile the release notes:
You may need to fix up any broken release note fragments before committing. Keep running make build-docs until
it passes, then commit and carry on.
After committing the compiled release notes and pushing them to the main branch, release a new version:
The version format for this repo is {major}.{minor}.{patch} for stable, and {major}.{minor}.
{patch}-{stage}.{devnum} for unstable (stage can be alpha or beta).
During a release, specify which part to bump, like make release bump=minor or make release bump=devnum.
If you are in an alpha version, make release bump=stage will bump to beta. If you are in a beta version, make
release bump=stage will bump to a stable version.
To issue an unstable version when the current version is stable, specify the new version explicitly, like make release
bump="--new-version 4.0.0-alpha.1 devnum".
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making
participation in our project and our community a harassment-free experience for everyone, regardless of age, body size,
disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality,
personal appearance, race, religion, or sexual identity and orientation.
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appro-
priate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits,
issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any
contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
2.34.4 Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the
project or its community. Examples of representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed representative at an online or offline
event. Representation of a project may be further defined and clarified by project maintainers.
2.34.5 Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at
[email protected]. All complaints will be reviewed and investigated and will result in a response that is
deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with
regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent
repercussions as determined by other members of the project’s leadership.
2.34.6 Attribution
This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.
contributor-covenant.org/version/1/4/code-of-conduct.html
THREE
• genindex
• modindex
• search
291
Populus Documentation, Release 6.17.0
e
ens, 271
ens.async_ens, 275
ens.ens, 272
ens.exceptions, 277
w
web3, 213
web3.contract, 110
web3.eth, 221
web3.gas_strategies.rpc, 271
web3.gas_strategies.time_based, 271
web3.geth, 259
web3.geth.admin, 259
web3.geth.miner, 258
web3.geth.personal, 262
web3.geth.txpool, 264
web3.net, 257
web3.tracing, 268
web3.utils, 269
web3.utils.filters, 105
293
Populus Documentation, Release 6.17.0
Symbols async_gas_price_strategy_middleware()
__init__() (web3.pm.ERC1319Registry method), 255 (web3.middleware method), 133
__repr__() (ethpm.Package method), 148 async_geth_poa_middleware() (web3.middleware
_generate_release_id() method), 139
(web3.pm.ERC1319Registry method), 256 async_handle_offchain_lookup() (web3.utils.utils
_get_all_package_ids() method), 269
(web3.pm.ERC1319Registry method), 256 async_http_retry_request_middleware()
_get_all_release_ids() (web3.middleware method), 133
(web3.pm.ERC1319Registry method), 256 async_local_filter_middleware()
_get_package_name() (web3.pm.ERC1319Registry (web3.middleware method), 140
method), 256 async_make_stalecheck_middleware()
_get_release_data() (web3.pm.ERC1319Registry (web3.middleware method), 137
method), 256 async_name_to_address_middleware()
_get_release_id() (web3.pm.ERC1319Registry (web3.middleware method), 132
method), 256 async_validation_middleware() (web3.middleware
_num_package_ids() (web3.pm.ERC1319Registry method), 133
method), 257 AsyncENS (class in ens.async_ens), 275
_num_release_ids() (web3.pm.ERC1319Registry attach_modules() (web3.w3 method), 220
method), 257 attrdict_middleware() (web3.middleware method),
_release() (web3.pm.ERC1319Registry method), 256 132
A B
BidTooLow, 278
abi (web3.contract.Contract attribute), 112
block_number (web3.eth.Eth attribute), 223
accounts (web3.eth.Eth attribute), 222
BlockFilter (class in web3.utils.filters), 106
add() (Web3.middleware_onion method), 135
buffered_gas_estimate_middleware()
add_peer() (in module web3.geth.admin), 261
(web3.middleware method), 133
address (web3.contract.Contract attribute), 112
build_dependencies (ethpm.Package attribute), 148
address() (ens.async_ens.AsyncENS method), 275
build_dependency()
address() (ens.ens.ENS method), 272
built-in function, 164
AddressMismatch, 277
build_filter() (web3.contract.Contract.events.your_event_name
all_functions() (web3.contract.Contract class
class method), 114
method), 115
build_transaction()
api (web3.Web3 attribute), 213
(web3.contract.Contract.fallback method),
async_attrdict_middleware() (web3.middleware
122
method), 132
build_transaction()
async_buffered_gas_estimate_middleware()
(web3.contract.ContractFunction method),
(web3.middleware method), 133
121
async_construct_sign_and_send_raw_middleware()
built-in function
(web3.middleware method), 140
build_dependency(), 164
async_construct_simple_cache_middleware()
deployment(), 162
(web3.middleware method), 137
deployment_type(), 163
295
Populus Documentation, Release 6.17.0
296 Index
Populus Documentation, Release 6.17.0
Index 297
Populus Documentation, Release 6.17.0
K N
keccak() (web3.Web3 class method), 216 name (ethpm.Package property), 148
name() (ens.async_ens.AsyncENS method), 275
L name() (ens.ens.ENS method), 273
link_bytecode() (LinkableContract class method), name_to_address_middleware() (web3.middleware
151 method), 132
linked_references (LinkableContract attribute), 151 needs_bytecode_linking (LinkableContract at-
list_accounts() (in module web3.geth.personal), 262 tribute), 151
list_wallets() (in module web3.geth.personal), 263 new_account() (in module web3.geth.personal), 263
listening() (in module web3.net), 257 node_info() (in module web3.geth.admin), 259
local_filter_middleware() (web3.middleware
method), 140 O
lock_account() (in module web3.geth.personal), 263 OversizeTransaction, 278
LogFilter (class in web3.utils.filters), 107 owner() (ens.async_ens.AsyncENS method), 276
owner() (ens.ens.ENS method), 273
M
make_dag() (web3.geth.miner.GethMiner method), 258 P
make_request() (BaseProvider method), 143 Package (class in ethpm), 148
make_stalecheck_middleware() (web3.middleware params (web3._utils.caching.RequestInformation at-
method), 137 tribute), 146
manifest (Package attribute), 149 peer_count() (in module web3.net), 257
manifest_version (ethpm.Package property), 148 peers() (in module web3.geth.admin), 260
max_priority_fee (web3.eth.Eth attribute), 222 pin_assets() (BaseIPFSBackend method), 152
method (web3._utils.caching.RequestInformation at- PM (class in web3.pm), 254
tribute), 146 pm (web3.Web3 attribute), 218
middleware_response_processors process_subscriptions()
(web3._utils.caching.RequestInformation (web3.providers.websocket.WebsocketConnection
attribute), 146 method), 90
middlewares (BaseProvider attribute), 143
middlewares (Web3.middleware_onion attribute), 136 R
miner (web3.Web3 attribute), 218 recv() (web3.providers.websocket.WebsocketConnection
mining (web3.eth.Eth attribute), 222 method), 91
modify_transaction() (web3.eth.Eth method), 235 release_package() (web3.pm.PM method), 254
module remove() (Web3.middleware_onion method), 135
ens, 271 replace() (Web3.middleware_onion method), 136
ens.async_ens, 275 replace_transaction() (web3.eth.Eth method), 234
ens.ens, 272 resolver() (ens.async_ens.AsyncENS method), 276
ens.exceptions, 277 resolver() (ens.ens.ENS method), 274
web3, 213 ResolverNotFound, 278
web3.contract, 110 response_formatters
web3.eth, 221 (web3._utils.caching.RequestInformation
web3.gas_strategies.rpc, 271 attribute), 146
web3.gas_strategies.time_based, 271 rpc_gas_price_strategy() (in module
web3.geth, 259 web3.gas_strategies.rpc), 271
web3.geth.admin, 259
web3.geth.miner, 258 S
web3.geth.personal, 262
web3.geth.txpool, 264 send() (web3.providers.websocket.WebsocketConnection
web3.net, 257 method), 91
web3.tracing, 268 send_raw_transaction() (web3.eth.Eth method), 234
web3.utils, 269
298 Index
Populus Documentation, Release 6.17.0
Index 299
Populus Documentation, Release 6.17.0
module, 259
web3.geth.admin
module, 259
web3.geth.miner
module, 258
web3.geth.personal
module, 262
web3.geth.txpool
module, 264
web3.main._PersistentConnectionWeb3 (built-in
class), 90
web3.net
module, 257
web3.providers.async_rpc.AsyncHTTPProvider
(built-in class), 91
web3.providers.ipc.IPCProvider (built-in class),
86
web3.providers.persistent.PersistentConnectionProvider
(built-in class), 87
web3.providers.rpc.HTTPProvider (built-in class),
86
web3.providers.websocket.request_processor.RequestProcessor
(built-in class), 145
web3.providers.websocket.WebsocketConnection
(built-in class), 90
web3.providers.websocket.WebsocketProvider
(built-in class), 87
web3.providers.websocket.WebsocketProviderV2
(built-in class), 88
web3.tracing
module, 268
web3.utils
module, 269
web3.utils.filters
module, 105
ws (web3.main._PersistentConnectionWeb3 attribute), 90
300 Index