diff --git a/_build/html_zh_CN/.buildinfo b/_build/html_zh_CN/.buildinfo
new file mode 100644
index 0000000000..90abf92cd3
--- /dev/null
+++ b/_build/html_zh_CN/.buildinfo
@@ -0,0 +1,4 @@
+# Sphinx build info version 1
+# This file records the configuration used when building these files. When it is not found, a full rebuild will be done.
+config: a017a6bee2951a2fd7f360bc661d6569
+tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/_build/html_zh_CN/.doctrees/code_of_conduct.doctree b/_build/html_zh_CN/.doctrees/code_of_conduct.doctree
new file mode 100644
index 0000000000..8adefe45ea
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/code_of_conduct.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/constants.doctree b/_build/html_zh_CN/.doctrees/constants.doctree
new file mode 100644
index 0000000000..1425f52b65
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/constants.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/contributing.doctree b/_build/html_zh_CN/.doctrees/contributing.doctree
new file mode 100644
index 0000000000..5aa059513c
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/contributing.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/ens.doctree b/_build/html_zh_CN/.doctrees/ens.doctree
new file mode 100644
index 0000000000..90ed057bec
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/ens.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/ens_overview.doctree b/_build/html_zh_CN/.doctrees/ens_overview.doctree
new file mode 100644
index 0000000000..85235e5d55
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/ens_overview.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/environment.pickle b/_build/html_zh_CN/.doctrees/environment.pickle
new file mode 100644
index 0000000000..a30fbd80ab
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/environment.pickle differ
diff --git a/_build/html_zh_CN/.doctrees/filters.doctree b/_build/html_zh_CN/.doctrees/filters.doctree
new file mode 100644
index 0000000000..ba91b6d2cf
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/filters.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/gas_price.doctree b/_build/html_zh_CN/.doctrees/gas_price.doctree
new file mode 100644
index 0000000000..1e83beea06
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/gas_price.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/index.doctree b/_build/html_zh_CN/.doctrees/index.doctree
new file mode 100644
index 0000000000..6eb256ce63
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/index.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/internals.doctree b/_build/html_zh_CN/.doctrees/internals.doctree
new file mode 100644
index 0000000000..d8c6f3aef4
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/internals.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/middleware.doctree b/_build/html_zh_CN/.doctrees/middleware.doctree
new file mode 100644
index 0000000000..b6ed42a7ec
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/middleware.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/migration.doctree b/_build/html_zh_CN/.doctrees/migration.doctree
new file mode 100644
index 0000000000..1fcd48e8a9
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/migration.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/overview.doctree b/_build/html_zh_CN/.doctrees/overview.doctree
new file mode 100644
index 0000000000..0076dd62a8
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/overview.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/providers.doctree b/_build/html_zh_CN/.doctrees/providers.doctree
new file mode 100644
index 0000000000..3694200aa9
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/providers.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/quickstart.doctree b/_build/html_zh_CN/.doctrees/quickstart.doctree
new file mode 100644
index 0000000000..e0bcd34ca4
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/quickstart.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/release_notes.doctree b/_build/html_zh_CN/.doctrees/release_notes.doctree
new file mode 100644
index 0000000000..67a8973a0d
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/release_notes.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/resources.doctree b/_build/html_zh_CN/.doctrees/resources.doctree
new file mode 100644
index 0000000000..6030f9dd7b
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/resources.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/subscriptions.doctree b/_build/html_zh_CN/.doctrees/subscriptions.doctree
new file mode 100644
index 0000000000..adff8a7b8f
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/subscriptions.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/toc.doctree b/_build/html_zh_CN/.doctrees/toc.doctree
new file mode 100644
index 0000000000..d7c2ef60bd
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/toc.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/transactions.doctree b/_build/html_zh_CN/.doctrees/transactions.doctree
new file mode 100644
index 0000000000..32aad91bdb
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/transactions.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/troubleshooting.doctree b/_build/html_zh_CN/.doctrees/troubleshooting.doctree
new file mode 100644
index 0000000000..0070429d59
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/troubleshooting.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/web3.beacon.doctree b/_build/html_zh_CN/.doctrees/web3.beacon.doctree
new file mode 100644
index 0000000000..c3463d428b
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/web3.beacon.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/web3.contract.doctree b/_build/html_zh_CN/.doctrees/web3.contract.doctree
new file mode 100644
index 0000000000..63213e0c65
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/web3.contract.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/web3.eth.account.doctree b/_build/html_zh_CN/.doctrees/web3.eth.account.doctree
new file mode 100644
index 0000000000..1b691cd978
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/web3.eth.account.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/web3.eth.doctree b/_build/html_zh_CN/.doctrees/web3.eth.doctree
new file mode 100644
index 0000000000..679391da7d
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/web3.eth.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/web3.geth.doctree b/_build/html_zh_CN/.doctrees/web3.geth.doctree
new file mode 100644
index 0000000000..2bf5e30719
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/web3.geth.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/web3.main.doctree b/_build/html_zh_CN/.doctrees/web3.main.doctree
new file mode 100644
index 0000000000..cfa8e81f27
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/web3.main.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/web3.net.doctree b/_build/html_zh_CN/.doctrees/web3.net.doctree
new file mode 100644
index 0000000000..7d36b9c26c
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/web3.net.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/web3.tracing.doctree b/_build/html_zh_CN/.doctrees/web3.tracing.doctree
new file mode 100644
index 0000000000..eb3c7088b5
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/web3.tracing.doctree differ
diff --git a/_build/html_zh_CN/.doctrees/web3.utils.doctree b/_build/html_zh_CN/.doctrees/web3.utils.doctree
new file mode 100644
index 0000000000..c83d73c1e5
Binary files /dev/null and b/_build/html_zh_CN/.doctrees/web3.utils.doctree differ
diff --git a/_build/html_zh_CN/_images/banner-snek.jpg b/_build/html_zh_CN/_images/banner-snek.jpg
new file mode 100644
index 0000000000..f49a07dd8c
Binary files /dev/null and b/_build/html_zh_CN/_images/banner-snek.jpg differ
diff --git a/_build/html_zh_CN/_sources/code_of_conduct.rst.txt b/_build/html_zh_CN/_sources/code_of_conduct.rst.txt
new file mode 100644
index 0000000000..a5f842ef33
--- /dev/null
+++ b/_build/html_zh_CN/_sources/code_of_conduct.rst.txt
@@ -0,0 +1,78 @@
+Code of Conduct
+---------------
+
+Our Pledge
+~~~~~~~~~~
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to make 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.
+
+Our Standards
+~~~~~~~~~~~~~
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+Our Responsibilities
+~~~~~~~~~~~~~~~~~~~~
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate 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.
+
+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.
+
+Enforcement
+~~~~~~~~~~~
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at snakecharmers@ethereum.org. 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.
+
+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
diff --git a/_build/html_zh_CN/_sources/constants.rst.txt b/_build/html_zh_CN/_sources/constants.rst.txt
new file mode 100644
index 0000000000..ca6ad7456f
--- /dev/null
+++ b/_build/html_zh_CN/_sources/constants.rst.txt
@@ -0,0 +1,28 @@
+.. _constants:
+
+Constants
+=========
+
+The web3.constants module contains commonly used values.
+
+Strings
+*******
+
+.. code-block:: python
+
+ #The Address Zero, which is 20 bytes (40 nibbles) of zero.
+ web3.constants.ADDRESS_ZERO
+
+ #The hexadecimal version of Max uint256.
+ web3.constants.MAX_INT
+
+ #The Hash Zero, which is 32 bytes (64 nibbles) of zero.
+ web3.constants.HASH_ZERO
+
+Int
+***
+
+.. code-block:: python
+
+ #The amount of Wei in one Ether
+ web3.constants.WEI_PER_ETHER
diff --git a/_build/html_zh_CN/_sources/contributing.rst.txt b/_build/html_zh_CN/_sources/contributing.rst.txt
new file mode 100644
index 0000000000..e08589a89e
--- /dev/null
+++ b/_build/html_zh_CN/_sources/contributing.rst.txt
@@ -0,0 +1,514 @@
+.. _contributing:
+
+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`_.
+
+
+How to Help
+~~~~~~~~~~~
+
+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.
+
+
+Your Development Environment
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. 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:
+
+.. code:: sh
+
+ $ git clone --recursive https://github.com//web3.py.git
+ $ cd web3.py
+
+
+Finally, install all development dependencies:
+
+.. code:: sh
+
+ $ python -m pip install -e ".[dev]"
+ $ pre-commit install
+
+
+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:
+
+.. code:: sh
+
+ $ docker compose up -d
+
+
+This will build a Docker container set up with an environment to run the
+Python test code.
+
+To run the core tests from your local machine:
+
+.. code:: sh
+
+ $ docker compose exec sandbox bash -c 'pytest tests/core'
+
+
+The container does not have ``go-ethereum`` installed, so you can exclude those tests
+by using the ``-k "not goethereum"`` flag.
+
+.. code:: sh
+
+ $ docker compose exec sandbox bash -c 'pytest tests/integration -k "not goethereum"'
+
+
+You can run arbitrary commands inside the Docker container by using the
+``bash -c`` prefix.
+
+.. code:: sh
+
+ $ docker compose exec sandbox bash -c 'pwd && ls'
+
+
+Or, if you would like to open a session to the container, run:
+
+.. code:: sh
+
+ $ docker compose exec sandbox bash
+
+
+Running The Tests
+~~~~~~~~~~~~~~~~~
+
+A great way to explore the code base is to run the tests.
+
+
+First, install the test dependencies:
+
+.. code:: sh
+
+ $ python -m pip install -e ".[test]"
+
+
+You can run all tests with:
+
+.. code:: sh
+
+ $ 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:
+
+.. code:: sh
+
+ $ pytest tests/core/eth-module/test_accounts.py
+
+
+Linting is also performed by the CI and locally with each commit. You can save yourself
+some time by checking for linting errors manually:
+
+.. code:: sh
+
+ $ 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.
+
+
+Writing Tests
+~~~~~~~~~~~~~
+
+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, :file:`conftest.py` files are used for common code
+shared between modules that exist within the same directory as that particular
+:file:`conftest.py` file.
+
+
+Unit Testing and eth-tester Tests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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``.
+
+* :file:`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.
+* :file:`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 :file:`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. :file:`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 respective client.
+
+The integration tests are each run in insolation to prevent muddied contexts. Because
+they are run in isolation, they can be parallelized with ``pytest-xdist`` in order to
+speed up the test suite. To run the tests in parallel, you can use the ``-n`` flag
+with ``pytest``. For example, to run the tests in parallel with 4 workers, you can
+use the following command:
+
+.. code:: sh
+
+ $ pytest tests/integration/go_ethereum/path/to/module/or/test -n 4
+
+
+Working With Test Contracts
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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 with:
+
+.. code:: sh
+
+ $ python -m pip install py-solc-x black
+
+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.
+
+.. code-block:: bash
+
+ $ 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.
+
+.. code-block:: bash
+
+ $ 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 integration test suite - see the
+:ref:`generating_fixtures` section below.
+
+
+Manual Testing
+~~~~~~~~~~~~~~
+
+To import and test an unreleased version of web3.py in another context,
+you can install it from your development directory:
+
+.. code:: sh
+
+ $ python -m pip install -e ../path/to/web3py
+
+
+Code Style
+~~~~~~~~~~
+
+We use `pre-commit `_ to enforce a consistent code style across
+the library. This tool runs automatically with every commit, but you can also run it
+manually with:
+
+.. code:: sh
+
+ $ make lint
+
+
+If you need to make a commit that skips the ``pre-commit`` checks, you can do so with
+``git commit --no-verify``.
+
+We use Black as part of our linting. To ignore the commits that introduced Black in
+git history, you can configure your git environment like so:
+
+.. code:: sh
+
+ $ git config blame.ignoreRevsFile .git-blame-ignore-revs
+
+
+This library uses `type hints`_, which are enforced by the ``mypy`` tool (part of the
+``pre-commit`` checks). All new code is required to land with type hints, with the
+exception of code within the ``tests`` directory.
+
+
+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--.org.readthedocs.build/en//``.
+
+
+Pull Requests
+~~~~~~~~~~~~~
+
+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.
+
+.. _generating_fixtures:
+
+Generating New Fixtures
+~~~~~~~~~~~~~~~~~~~~~~~
+
+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:
+
+.. code:: sh
+
+ $ python -m pip install -e ".[test]"
+
+.. 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:
+
+ .. code:: sh
+
+ $ python -m geth.install v1.16.2
+
+2. Specify the Geth binary and run the fixture creation script (from within the web3.py directory):
+
+ .. code:: sh
+
+ $ GETH_BINARY=~/.py-geth/geth-v1.16.2/bin/geth python ./tests/integration/generate_fixtures/go_ethereum.py
+
+3. The output of this script is your fixture, a zip file, which is now stored in ``/tests/integration/``.
+ The ``/tests/integration/go_ethereum/conftest.py`` and
+ ``/web3/tools/benchmark/node.py`` files should be updated automatically 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. The ``geth_version`` and ``pygeth_version`` parameter defaults in
+ ``/.circleci/config.yml`` should be automatically updated to match the
+ ``go-ethereum`` version used to generate the test fixture and the ``py-geth``
+ version that supports installing it.
+
+
+CI Testing With a Nightly Geth Build
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Occasionally you'll want to have CI run the test suite against an unreleased version of
+Geth - e.g. to test upcoming hard fork changes. The workflow described below is for
+testing only, as updates will only be merged into main once the Geth release is
+published and the test runs are updated to use the new stable version.
+
+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 the ``geth_version`` pipeline parameter to
+ "custom". This will trigger the custom Geth build to be used in the CI test suite.
+
+6. Create a PR and let CI do its thing.
+
+
+Releasing
+~~~~~~~~~
+
+Releases are typically done from the ``main`` branch, except when releasing a beta (in
+which case the beta is released from ``main``, and the previous stable branch is
+released from said branch).
+
+Final test before each release
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Before releasing a new version, build and test the package that will be released:
+
+.. code:: sh
+
+ $ git checkout main && git pull
+ $ make package-test
+
+This will build the package and install it in a temporary virtual environment. Follow
+the instructions to activate the venv and test whatever you think is important.
+
+Review the documentation that will get published:
+
+.. code:: sh
+
+ $ make docs
+
+Validate and preview the release notes:
+
+.. code:: sh
+
+ $ make validate-newsfragments
+
+Build the release notes
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Before bumping the version number, build the release notes. You must include the part of
+the version to bump (see below), which changes how the version number will show in the
+release notes.
+
+.. code:: sh
+
+ $ make notes bump=$$VERSION_PART_TO_BUMP$$
+
+If there are any errors, be sure to re-run make notes until it works.
+
+Push the release to github & pypi
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+After confirming that the release package looks okay, release a new version:
+
+.. code:: sh
+
+ $ make release bump=$$VERSION_PART_TO_BUMP$$
+
+This command will:
+
+- Bump the version number as specified in ``.pyproject.toml`` and ``setup.py``.
+- Create a git commit and tag for the new version.
+- Build the package.
+- Push the commit and tag to github.
+- Push the new package files to pypi.
+
+Which version part to bump
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``$$VERSION_PART_TO_BUMP$$`` must be one of: ``major``, ``minor``, ``patch``, ``stage``,
+or ``devnum``.
+
+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).
+
+If you are in a beta version, ``make release bump=stage`` will switch to a stable.
+
+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"``.
+
+You can see what the result of bumping any particular version part would be with
+``bump-my-version show-bump``.
+
+.. _Python Discord server: https://discord.gg/GHryRvPB84
+.. _style guide: https://github.com/ethereum/snake-charmers-tactical-manual/blob/main/style-guide.md
+.. _type hints: https://www.python.org/dev/peps/pep-0484/
+.. _how to create documentation: https://github.com/ethereum/snake-charmers-tactical-manual/blob/main/documentation.md
+.. _working on pull requests: https://help.github.com/articles/about-pull-requests/
+.. _py-geth: https://github.com/ethereum/py-geth
+.. _pytest documentation: https://docs.pytest.org/en/latest
+.. _pytest documentation on fixtures: https://docs.pytest.org/en/latest/how-to/fixtures.html
diff --git a/_build/html_zh_CN/_sources/ens.rst.txt b/_build/html_zh_CN/_sources/ens.rst.txt
new file mode 100644
index 0000000000..372326a838
--- /dev/null
+++ b/_build/html_zh_CN/_sources/ens.rst.txt
@@ -0,0 +1,27 @@
+.. py:module:: ens
+
+ENS API
+===========
+
+:doc:`ens_overview` has a friendly overview.
+
+Continue below for the detailed specs on each method and class in the ens module.
+
+ens\.ens module
+----------------
+
+.. automodule:: ens.ens
+ :members:
+
+ens\.async_ens module
+---------------------
+
+.. automodule:: ens.async_ens
+ :members:
+
+ens\.exceptions module
+----------------------
+
+.. automodule:: ens.exceptions
+ :members:
+ :show-inheritance:
diff --git a/_build/html_zh_CN/_sources/ens_overview.rst.txt b/_build/html_zh_CN/_sources/ens_overview.rst.txt
new file mode 100644
index 0000000000..5a9dcd0fae
--- /dev/null
+++ b/_build/html_zh_CN/_sources/ens_overview.rst.txt
@@ -0,0 +1,343 @@
+.. _ens_overview:
+
+Ethereum Name Service (ENS)
+===========================
+
+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 :mod:`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.
+
+
+Setup
+-----
+
+Create an :class:`~ens.ENS` object (named ``ns`` below) in one of three ways:
+
+1. Automatic detection
+2. Specify an instance of a :ref:`provider `
+3. From an existing :class:`web3.Web3` object
+
+.. code-block:: python
+
+ # automatic detection
+ from ens.auto import ns
+
+ # or, with a provider
+ from web3 import IPCProvider
+ from ens import ENS
+
+ provider = IPCProvider(...)
+ ns = ENS(provider)
+
+ # or, with a w3 instance
+ # Note: This inherits the w3 middleware from the w3 instance and adds a stalecheck middleware to the middleware onion.
+ # It also inherits the provider and codec from the w3 instance, as well as the ``strict_bytes_type_checking`` flag value.
+ from ens import ENS
+ w3 = Web3(...)
+ ns = ENS.from_web3(w3)
+
+
+Asynchronous support is available via the ``AsyncENS`` module:
+
+.. code-block:: python
+
+ from ens import AsyncENS
+
+ 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.
+
+.. code-block:: python
+
+ # instantiate w3 instance
+ from web3 import Web3, IPCProvider
+ w3 = Web3(IPCProvider(...))
+
+ # use the module
+ w3.ens.address('ethereum.eth')
+
+
+.. py:attribute:: 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 :ref:`disable-strict-byte-check`
+
+ 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.
+
+ .. doctest::
+
+ >>> from web3 import Web3, EthereumTesterProvider
+ >>> from ens import ENS
+ >>> w3 = Web3(EthereumTesterProvider())
+
+ >>> assert w3.strict_bytes_type_checking # assert strict by default
+ >>> w3.is_encodable('bytes2', b'1')
+ False
+
+ >>> w3.strict_bytes_type_checking = False
+ >>> w3.is_encodable('bytes2', b'1') # zero-padded, so encoded to: b'1\x00'
+ True
+
+ >>> 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
+
+ >>> # assert these are now separate instances
+ >>> ns.strict_bytes_type_checking = True
+ >>> ns.w3.is_encodable('bytes2', b'1')
+ False
+
+ >>> # assert w3 flag value remains
+ >>> assert w3.strict_bytes_type_checking is False
+ >>> 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.
+
+ .. doctest::
+
+ >>> from web3 import Web3, EthereumTesterProvider
+ >>> w3 = Web3(EthereumTesterProvider())
+
+ >>> assert w3.strict_bytes_type_checking # assert strict by default
+ >>> w3.is_encodable('bytes2', b'1')
+ False
+
+ >>> w3.strict_bytes_type_checking = False
+ >>> w3.is_encodable('bytes2', b'1') # zero-padded, so encoded to: b'1\x00'
+ True
+
+ >>> assert w3 == w3.ens.w3 # assert same object
+ >>> assert not w3.ens.w3.strict_bytes_type_checking
+ >>> w3.ens.w3.is_encodable('bytes2', b'1')
+ True
+
+ >>> # sanity check on eth module as well
+ >>> assert not w3.eth.w3.strict_bytes_type_checking
+ >>> w3.eth.w3.is_encodable('bytes2', b'1')
+ True
+
+
+Usage
+-----
+
+Name Info
+~~~~~~~~~
+
+.. _ens_get_address:
+
+Get the Address for an ENS Name
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: python
+
+ from ens.auto import ns
+ eth_address = ns.address('ens.eth')
+ assert eth_address == '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7'
+
+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.
+
+Multichain Address Resolution
++++++++++++++++++++++++++++++
+
+`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.
+
+.. code-block:: python
+
+ from ens.auto import ns
+ eth_address = ns.address('ens.eth', coin_type=60) # ETH is coin_type 60
+ assert eth_address == '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7'
+
+
+Get the ENS Name for an Address
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: python
+
+ domain = ns.name('0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7')
+
+ # name() also accepts the bytes version of the address
+ assert ns.name(b'\xfe\x89\xccz\xbb,A\x83h:\xb7\x16S\xc4\xcd\xc9\xb0-D\xb7') == domain
+
+ # 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.
+
+Get the Owner of a Name
+^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: python
+
+ eth_address = ns.owner('exchange.eth')
+
+....
+
+Set Up Your Name and Address
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Link a Name to an Address
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You can set up your name so that :meth:`~ens.ENS.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).
+
+.. code-block:: python
+
+ 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.
+
+.. code-block:: python
+
+ ns.setup_address('ens.eth')
+
+You can claim arbitrarily deep subdomains.
+
+.. code-block:: python
+
+ ns.setup_address('supreme.executive.power.derives.from.a.mandate.from.the.masses.ens.eth')
+
+ # wait for the transaction to be mined, then:
+ assert (
+ ns.address('supreme.executive.power.derives.from.a.mandate.from.the.masses.ens.eth')
+ == '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7'
+ )
+
+.. warning:: Gas costs scale up with the number of subdomains!
+
+Multichain Address Support
+++++++++++++++++++++++++++
+
+`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.
+
+.. code-block:: python
+
+ from ens.auto import ns
+ ns.setup_address('ens.eth', coin_type=60) # ETH is coin_type 60
+ assert ns.address('ens.eth', coin_type=60) == '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7'
+
+Link an Address to a Name
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You can set up your address so that :meth:`~ens.ENS.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.
+
+.. code-block:: python
+
+ ns.setup_name('ens.eth', '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7')
+
+If you don't supply the address, :meth:`~ens.ENS.setup_name` will assume you want the
+address returned by :meth:`~ens.ENS.address`.
+
+.. code-block:: python
+
+ ns.setup_name('ens.eth')
+
+If the name doesn't already point to an address, :meth:`~ens.ENS.setup_name` will
+call :meth:`~ens.ENS.setup_address` for you.
+
+Wait for the transaction to be mined, then:
+
+.. code-block:: python
+
+ assert ns.name('0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7') == 'ens.eth'
+
+....
+
+Text Records
+~~~~~~~~~~~~
+
+Set Text Metadata for an ENS Record
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+As the owner of an ENS record, you can add text metadata.
+A list of supported fields can be found in the
+`ENS documentation `_.
+You'll need to setup the address first, and then the text can be set:
+
+.. code-block:: python
+
+ ns.setup_address('ens.eth', '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7')
+ ns.set_text('ens.eth', 'url', 'https://example.com')
+
+A transaction dictionary can be passed as the last argument if desired:
+
+.. code-block:: python
+
+ transaction_dict = {'from': '0x123...'}
+ ns.set_text('ens.eth', 'url', 'https://example.com', transaction_dict)
+
+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``.
+
+Read Text Metadata for an ENS Record
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Anyone can read the data from an ENS Record:
+
+.. code-block:: python
+
+ url = ns.get_text('ens.eth', 'url')
+ assert url == 'https://example.com'
+
+....
+
+Working With Resolvers
+~~~~~~~~~~~~~~~~~~~~~~
+
+Get the Resolver for an ENS Record
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You can get the resolver for an ENS name via the :meth:`~ens.ENS.resolver` method.
+
+.. code-block:: python
+
+ >>> resolver = ns.resolver('ens.eth')
+ >>> resolver.address
+ '0x5B2063246F2191f18F2675ceDB8b28102e957458'
+
+....
+
+Wildcard Resolution Support
+---------------------------
+
+The ``ENS`` module supports Wildcard Resolution for resolvers that implement the ``ExtendedResolver`` interface
+as described 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 subdomains
+to a unique address.
diff --git a/_build/html_zh_CN/_sources/filters.rst.txt b/_build/html_zh_CN/_sources/filters.rst.txt
new file mode 100644
index 0000000000..1ccebc98a8
--- /dev/null
+++ b/_build/html_zh_CN/_sources/filters.rst.txt
@@ -0,0 +1,1083 @@
+.. _filtering:
+
+Events and Logs
+===============
+
+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 several 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.
+
+.. code-block:: python
+
+ 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 :ref:`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.
+
+.. code-block:: python
+
+ 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"}]'
+
+ weth_contract = w3.eth.contract(address=WETH_ADDRESS, abi=WETH_ABI)
+
+ # fetch transfer events in the last block
+ logs = weth_contract.events.Transfer().get_logs(from_block=w3.eth.block_number)
+
+ for log in logs:
+ print(f"Transfer of {w3.from_wei(log.args.wad, 'ether')} WETH from {log.args.src} to {log.args.dst}")
+
+See an advanced example of fetching log history :ref:`here `.
+
+3. Subscribe to events for real-time updates. When using a persistent connection provider
+ (:class:`~web3.providers.persistent.WebSocketProvider` or
+ :class:`~web3.providers.persistent.AsyncIPCProvider`), the
+ :meth:`subscribe() ` method can be used to establish a new
+ event subscription. This example subscribes to ``Transfer`` events of the WETH contract.
+
+ .. code-block:: python
+
+ import asyncio
+ from web3 import AsyncWeb3, WebSocketProvider
+ from eth_abi.abi import decode
+
+ WETH_ADDRESS = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
+
+
+ async def subscribe_to_transfer_events():
+ async with AsyncWeb3(WebSocketProvider("...")) as w3:
+ transfer_event_topic = w3.keccak(text="Transfer(address,address,uint256)")
+ filter_params = {
+ "address": WETH_ADDRESS,
+ "topics": [transfer_event_topic],
+ }
+ subscription_id = await w3.eth.subscribe("logs", filter_params)
+ print(f"Subscribing to transfer events for WETH at {subscription_id}")
+
+ async for payload in w3.socket.process_subscriptions():
+ result = payload["result"]
+
+ from_addr = decode(["address"], result["topics"][1])[0]
+ to_addr = decode(["address"], result["topics"][2])[0]
+ amount = decode(["uint256"], result["data"])[0]
+ print(f"{w3.from_wei(amount, 'ether')} WETH from {from_addr} to {to_addr}")
+
+ asyncio.run(subscribe_to_transfer_events())
+
+
+ For more usage examples see the docs on :ref:`subscription-examples`.
+
+4. Use a filter.
+
+.. 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.
+
+.. py:module:: web3.utils.filters
+
+The :meth:`web3.eth.Eth.filter` method can be used to set up filters for:
+
+* Pending Transactions: ``w3.eth.filter("pending")``
+
+* New Blocks ``w3.eth.filter("latest")``
+
+* Event Logs
+
+ Through the contract instance api:
+
+ .. code-block:: python
+
+ event_filter = my_contract.events.myEvent.create_filter(from_block='latest', argument_filters={'arg1':10})
+
+ Or built manually by supplying `valid filter params `_:
+
+ .. code-block:: python
+
+ event_filter = w3.eth.filter({"address": contract_address})
+
+* Attaching to an existing filter
+
+ .. code-block:: python
+
+ 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 :class:`web3.contract.ContractEvents`.
+
+
+
+Filter Class
+------------
+
+.. py:class:: Filter(web3, filter_id)
+
+.. py:attribute:: Filter.filter_id
+
+ The ``filter_id`` for this filter as returned by the ``eth_newFilter`` RPC
+ method when this filter was created.
+
+
+.. py:method:: Filter.get_new_entries()
+
+ Retrieve new entries for this filter.
+
+ Logs will be retrieved using the
+ :func:`web3.eth.Eth.get_filter_changes` which returns only new entries since the last
+ poll.
+
+
+.. py:method:: Filter.get_all_entries()
+
+ Retrieve all entries for this filter.
+
+ Logs will be retrieved using the
+ :func:`web3.eth.Eth.get_filter_logs` which returns all entries that match the given
+ filter.
+
+
+.. py:method:: 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 unmodified.
+
+
+.. py:method:: Filter.is_valid_entry(entry)
+
+ Hook for subclasses to add additional programmatic filtering. The default
+ implementation always returns ``True``.
+
+
+Block and Transaction Filter Classes
+------------------------------------
+
+.. py:class:: BlockFilter(...)
+
+``BlockFilter`` is a subclass of :class:`Filter`.
+
+You can setup a filter for new blocks using ``web3.eth.filter('latest')`` which
+will return a new :class:`BlockFilter` object.
+
+ .. code-block:: python
+
+ 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``.
+
+.. py:class:: TransactionFilter(...)
+
+``TransactionFilter`` is a subclass of :class:`Filter`.
+
+You can setup a filter for new blocks using ``web3.eth.filter('pending')`` which
+will return a new :class:`TransactionFilter` object.
+
+ .. code-block:: python
+
+ new_transaction_filter = w3.eth.filter('pending')
+ new_transaction_filter.get_new_entries()
+
+
+Event Log Filters
+-----------------
+
+You can set up a filter for event logs using the web3.py contract api:
+:meth:`web3.contract.Contract.events.your_event_name.create_filter`, which provides some conveniences for
+creating event log filters. Refer to the following example:
+
+ .. code-block:: python
+
+ event_filter = my_contract.events..create_filter(from_block="latest", argument_filters={'arg1':10})
+ event_filter.get_new_entries()
+
+See :meth:`web3.contract.Contract.events.your_event_name.create_filter()` documentation for more information.
+
+You can set up an event log filter like the one above with ``web3.eth.filter`` by supplying a
+dictionary containing the standard filter parameters. Assuming that ``arg1`` is indexed, the
+equivalent filter creation would look like:
+
+ .. code-block:: python
+
+ 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 :class:`LogFilter` instance.
+
+.. py:class:: LogFilter(web3, filter_id, log_entry_formatter=None, data_filter_set=None)
+
+The :py:class:`LogFilter` class is a subclass of :class:`Filter`. See the :class:`Filter`
+documentation for inherited methods.
+
+:class:`LogFilter` provides the following additional
+methods:
+
+.. py:method:: 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.
+
+Examples: Listening For Events
+------------------------------
+
+Synchronous
+~~~~~~~~~~~
+
+ .. code-block:: python
+
+ from web3 import Web3, IPCProvider
+ import time
+
+ # instantiate Web3 instance
+ w3 = Web3(IPCProvider(...))
+
+ def handle_event(event):
+ print(event)
+
+ def log_loop(event_filter, poll_interval):
+ while True:
+ for event in event_filter.get_new_entries():
+ handle_event(event)
+ time.sleep(poll_interval)
+
+ def main():
+ block_filter = w3.eth.filter('latest')
+ log_loop(block_filter, 2)
+
+ if __name__ == '__main__':
+ main()
+
+.. _asynchronous_filters:
+
+Asynchronous Filter Polling
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+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.
+
+Single threaded concurrency with ``async`` and ``await``
+````````````````````````````````````````````````````````
+
+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.
+
+ .. code-block:: python
+
+ from web3 import Web3, IPCProvider
+ import asyncio
+
+ # instantiate Web3 instance
+ w3 = Web3(IPCProvider(...))
+
+ def handle_event(event):
+ print(event)
+ # and whatever
+
+ async def log_loop(event_filter, poll_interval):
+ while True:
+ for event in event_filter.get_new_entries():
+ handle_event(event)
+ await asyncio.sleep(poll_interval)
+
+ 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()
+
+ Read the asyncio_ documentation for more information.
+
+Running the event loop in a separate thread
+```````````````````````````````````````````
+
+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.
+
+ .. code-block:: python
+
+ from web3 import Web3, IPCProvider
+ from threading import Thread
+ import time
+
+ # instantiate Web3 instance
+ w3 = Web3(IPCProvider(...))
+
+ def handle_event(event):
+ print(event)
+ # and whatever
+
+
+ def log_loop(event_filter, poll_interval):
+ while True:
+ for event in event_filter.get_new_entries():
+ handle_event(event)
+ time.sleep(poll_interval)
+
+
+ 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
+
+ if __name__ == '__main__':
+ main()
+
+Here are some other libraries that provide frameworks for writing asynchronous python:
+
+ * gevent_
+ * twisted_
+ * celery_
+
+
+Examples
+--------
+
+.. _advanced_token_fetch:
+
+Advanced example: Fetching all token transfer events
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+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 an easy way 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 of ``eth_getLogs``, the JSON-RPC call gives a timeout error, decrease the end block number and tries 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 default exception retry configuration 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 ``.
+
+.. code-block:: python
+
+ """A stateful event scanner for Ethereum-based blockchains using web3.py.
+
+ 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
+ import logging
+ from abc import ABC, abstractmethod
+ from typing import Tuple, Optional, Callable, List, Iterable, Dict, Any
+
+ from web3 import Web3
+ from web3.contract import Contract
+ from web3.datastructures import AttributeDict
+ from web3.exceptions import BlockNotFound
+ from eth_abi.codec import ABICodec
+
+ # Currently this method is not exposed over official web3 API,
+ # but we need it to construct eth_getLogs parameters
+ from web3._utils.filters import construct_event_filter_params
+ from web3._utils.events import get_event_data
+
+
+ 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.
+
+ :return: 0 if no blocks scanned yet
+ """
+
+ @abstractmethod
+ def start_chunk(self, block_number: int):
+ """Scanner is about to ask data of multiple blocks over JSON-RPC.
+
+ Start a database session if needed.
+ """
+
+ @abstractmethod
+ def end_chunk(self, block_number: int):
+ """Scanner finished a number of blocks.
+
+ Persistent any data in your state now.
+ """
+
+ @abstractmethod
+ def process_event(self, block_when: datetime.datetime, event: AttributeDict) -> object:
+ """Process incoming events.
+
+ This function takes raw events from Web3, transforms them to your application internal
+ format, then saves them in a database or some other state.
+
+ :param block_when: When this block was mined
+
+ :param event: Symbolic dictionary of the event data
+
+ :return: Internal state structure that is the result of event transformation.
+ """
+
+ @abstractmethod
+ def delete_data(self, since_block: int) -> int:
+ """Delete any data since this block was scanned.
+
+ Purges any potential minor reorg data.
+ """
+
+
+ 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.
+
+ You *should* disable the default ``exception_retry_configuration`` on your provider for Web3,
+ because it cannot correctly throttle and decrease the `eth_getLogs` block number range.
+ """
+
+ def __init__(self, w3: Web3, contract: Contract, state: EventScannerState, events: List, filters: Dict[str, Any],
+ max_chunk_scan_size: int = 10000, max_request_retries: int = 30, request_retry_seconds: float = 3.0):
+ """
+ :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)
+ :param max_request_retries: How many times we try to reattempt a failed JSON-RPC call
+ :param request_retry_seconds: Delay between failed requests to let JSON-RPC server to recover
+ """
+
+ self.logger = logger
+ self.contract = contract
+ self.w3 = w3
+ self.state = state
+ self.events = events
+ self.filters = filters
+
+ # Our JSON-RPC throttling parameters
+ self.min_scan_chunk_size = 10 # 12 s/block = 120 seconds period
+ self.max_scan_chunk_size = max_chunk_scan_size
+ self.max_request_retries = max_request_retries
+ self.request_retry_seconds = request_retry_seconds
+
+ # 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
+
+ # Factor how fast we increase chunk size if no results are found
+ self.chunk_size_increase = 2.0
+
+ @property
+ def address(self):
+ return self.token_address
+
+ def get_block_timestamp(self, block_num) -> datetime.datetime:
+ """Get Ethereum block timestamp"""
+ try:
+ block_info = self.w3.eth.get_block(block_num)
+ except BlockNotFound:
+ # Block was not mined yet,
+ # minor chain reorganisation?
+ return None
+ last_time = block_info["timestamp"]
+ return datetime.datetime.utcfromtimestamp(last_time)
+
+ def get_suggested_scan_start_block(self):
+ """Get where we should start to scan for new token events.
+
+ If there are no prior scans, start from block 1.
+ Otherwise, start from the last end block minus ten blocks.
+ We rescan the last ten scanned blocks in the case there were forks to avoid
+ misaccounting due to minor single block works (happens once in an hour in Ethereum).
+ 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."""
+
+ # Do not scan all the way to the final block, as this
+ # block might not be mined yet
+ return self.w3.eth.block_number - 1
+
+ def get_last_scanned_block(self) -> int:
+ return self.state.get_last_scanned_block()
+
+ def delete_potentially_forked_block_data(self, after_block: int):
+ """Purge old data in the case of blockchain reorganisation."""
+ self.state.delete_data(after_block)
+
+ def scan_chunk(self, start_block, end_block) -> Tuple[int, datetime.datetime, list]:
+ """Read and process events between to block numbers.
+
+ 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
+
+ # Cache block timestamps to reduce some RPC overhead
+ # Real solution might include smarter models around block
+ def get_block_when(block_num):
+ if block_num not in block_timestamps:
+ block_timestamps[block_num] = get_block_timestamp(block_num)
+ return block_timestamps[block_num]
+
+ all_processed = []
+
+ for event_type in self.events:
+
+ # Callable that takes care of the underlying web3 call
+ def _fetch_events(_start_block, _end_block):
+ return _fetch_events_for_all_contracts(self.w3,
+ event_type,
+ self.filters,
+ from_block=_start_block,
+ to_block=_end_block)
+
+ # Do `n` retries on `eth_getLogs`,
+ # throttle down block range if needed
+ end_block, events = _retry_web3_call(
+ _fetch_events,
+ start_block=start_block,
+ end_block=end_block,
+ retries=self.max_request_retries,
+ delay=self.request_retry_seconds)
+
+ for evt in events:
+ idx = evt["logIndex"] # Integer of the log index position in the block, null when its pending
+
+ # We cannot avoid minor chain reorganisations, but
+ # at least we must avoid blocks that are not mined yet
+ assert idx is not None, "Somehow tried to scan a pending block"
+
+ 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)
+
+ logger.debug("Processing event %s, block: %s count: %s", evt['event'], block_number, block_number)
+ processed = self.state.process_event(block_when, evt)
+ all_processed.append(processed)
+
+ end_block_timestamp = get_block_when(end_block)
+ return end_block, end_block_timestamp, all_processed
+
+ def estimate_next_chunk_size(self, current_chuck_size: int, event_found_count: int):
+ """Try to figure out optimal chunk size
+
+ Our scanner might need to scan the whole blockchain for all events
+
+ * We want to minimize API calls over empty blocks
+
+ * 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
+
+ current_chuck_size = max(self.min_scan_chunk_size, current_chuck_size)
+ current_chuck_size = min(self.max_scan_chunk_size, current_chuck_size)
+ return int(current_chuck_size)
+
+ def scan(self, start_block, end_block, start_chunk_size=20, progress_callback=Optional[Callable]) -> Tuple[
+ list, int]:
+ """Perform a token balances scan.
+
+ Assumes all balances in the database are valid before start_block (no forks sneaked in).
+
+ :param start_block: The first block included in the scan
+
+ :param end_block: The last block included in the scan
+
+ :param start_chunk_size: How many blocks we try to fetch over JSON-RPC on the first attempt
+
+ :param progress_callback: If this is an UI application, update the progress of the scan
+
+ :return: [All processed events, number of chunks used]
+ """
+
+ assert start_block <= end_block
+
+ current_block = start_block
+
+ # Scan in chunks, commit between
+ chunk_size = start_chunk_size
+ last_scan_duration = last_logs_found = 0
+ total_chunks_scanned = 0
+
+ # All processed entries we got on this scan cycle
+ all_processed = []
+
+ while current_block <= end_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 = min(current_block + chunk_size, end_block)
+ logger.debug(
+ "Scanning token transfers for blocks: %s - %s, chunk size %s, last chunk scan took %s, last logs found %s",
+ current_block, estimated_end_block, chunk_size, last_scan_duration, last_logs_found,
+ )
+
+ start = time.time()
+ actual_end_block, end_block_timestamp, new_entries = self.scan_chunk(current_block, estimated_end_block)
+
+ # Where does our current chunk scan ends - are we out of chain yet?
+ current_end = actual_end_block
+
+ last_scan_duration = time.time() - start
+ all_processed += new_entries
+
+ # Print progress bar
+ if progress_callback:
+ progress_callback(start_block, end_block, current_block, end_block_timestamp, chunk_size, len(new_entries))
+
+ # 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))
+
+ # Set where the next chunk starts
+ current_block = current_end + 1
+ total_chunks_scanned += 1
+ self.state.end_chunk(current_end)
+
+ return all_processed, total_chunks_scanned
+
+
+ def _retry_web3_call(func, start_block, end_block, retries, delay) -> Tuple[int, list]:
+ """A custom retry loop to throttle down block range.
+
+ 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.
+
+ :param func: A callable that triggers Ethereum JSON-RPC, as func(start_block, end_block)
+ :param start_block: The initial start block of the block range
+ :param end_block: The initial start block of the block range
+ :param retries: How many times we retry
+ :param delay: Time to sleep between retries
+ """
+ for i in range(retries):
+ try:
+ return end_block, func(start_block, end_block)
+ except Exception as e:
+ # Assume this is HTTPConnectionPool(host='localhost', port=8545): Read timed out. (read timeout=10)
+ # 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(
+ "Retrying events for block range %s - %s (%s) failed with %s , retrying in %s seconds",
+ start_block, end_block, end_block-start_block, e, delay,
+ )
+ # Decrease the `eth_getBlocks` range
+ end_block = start_block + ((end_block - start_block) // 2)
+ # Let the JSON-RPC to recover e.g. from restart
+ time.sleep(delay)
+ continue
+ else:
+ logger.warning("Out of retries")
+ raise
+
+
+ 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.
+
+ This method is detached from any contract instance.
+
+ This is a stateless method, as opposed to create_filter.
+ It can be safely called against nodes which do not provide `eth_newFilter` API, like Infura.
+ """
+
+ if from_block is None:
+ raise Web3TypeError("Missing mandatory keyword argument to get_logs: from_block")
+
+ # Currently no way to poke this using a public web3.py API.
+ # This will return raw underlying ABI JSON object for the event
+ abi = event._get_event_abi()
+
+ # Depending on the Solidity version used to compile
+ # the contract that uses the ABI,
+ # it might have Solidity ABI encoding v1 or v2.
+ # We just assume the default that you set on Web3 object here.
+ # More information here https://eth-abi.readthedocs.io/en/latest/index.html
+ codec: ABICodec = w3.codec
+
+ # Here we need to poke a bit into Web3 internals, as this
+ # functionality is not exposed by default.
+ # Construct JSON-RPC raw filter presentation based on human readable Python descriptions
+ # Namely, convert event names to their keccak signatures
+ # More information here:
+ # https://github.com/ethereum/web3.py/blob/e176ce0793dafdd0573acc8d4b76425b6eb604ca/web3/_utils/filters.py#L71
+ data_filter_set, event_filter_params = construct_event_filter_params(
+ abi,
+ codec,
+ address=argument_filters.get("address"),
+ argument_filters=argument_filters,
+ from_block=from_block,
+ to_block=to_block
+ )
+
+ logger.debug("Querying eth_getLogs with the following parameters: %s", event_filter_params)
+
+ # Call JSON-RPC API on your Ethereum node.
+ # get_logs() returns raw AttributedDict entries
+ logs = w3.eth.get_logs(event_filter_params)
+
+ # Convert raw binary data to Python proxy objects as described by ABI
+ all_events = []
+ for log in logs:
+ # Convert raw JSON-RPC log result to human readable event by using ABI data
+ # More information how process_log works here
+ # https://github.com/ethereum/web3.py/blob/fbaf1ad11b0c7fac09ba34baff2c256cffe0a148/web3/_utils/events.py#L200
+ evt = get_event_data(codec, abi, log)
+ # Note: This was originally yield,
+ # but deferring the timeout exception caused the throttle logic not to work
+ all_events.append(evt)
+ return all_events
+
+
+ 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
+
+ # We use tqdm library to render a nice progress bar in the console
+ # https://pypi.org/project/tqdm/
+ from tqdm import tqdm
+
+ # RCC has around 11k Transfer events
+ # https://etherscan.io/token/0x9b6443b0fb9c241a7fdac375595cea13e6b7807a
+ RCC_ADDRESS = "0x9b6443b0fb9c241a7fdac375595cea13e6b7807a"
+
+ # Reduced ERC-20 ABI, only Transfer event
+ ABI = """[
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Transfer",
+ "type": "event"
+ }
+ ]
+ """
+
+ class JSONifiedState(EventScannerState):
+ """Store the state of scanned blocks and all events.
+
+ All state is an in-memory dict.
+ Simple load/store massive JSON on start up.
+ """
+
+ 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):
+ """Save everything we have scanned so far in a file."""
+ with open(self.fname, "wt") as f:
+ json.dump(self.state, f)
+ self.last_save = time.time()
+
+ #
+ # 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"]
+
+ def delete_data(self, since_block):
+ """Remove potentially reorganised blocks from the scan data."""
+ for block_num in range(since_block, self.get_last_scanned_block()):
+ if block_num in self.state["blocks"]:
+ del self.state["blocks"][block_num]
+
+ def start_chunk(self, block_number, chunk_size):
+ pass
+
+ def end_chunk(self, block_number):
+ """Save at the end of each block, so we can resume in the case of a crash or CTRL+C"""
+ # Next time the scanner is started we will resume from this block
+ self.state["last_scanned_block"] = block_number
+
+ # Save the database file for every minute
+ if time.time() - self.last_save > 60:
+ self.save()
+
+ def process_event(self, block_when: datetime.datetime, event: AttributeDict) -> str:
+ """Record a ERC-20 transfer in our database."""
+ # Events are keyed by their transaction hash and log index
+ # One transaction may contain multiple events
+ # and each one of those gets their own log index
+
+ # event_name = event.event # "Transfer"
+ log_index = event.logIndex # Log index within the block
+ # transaction_index = event.transactionIndex # Transaction index within the block
+ txhash = event.transactionHash.hex() # Transaction hash
+ block_number = event.blockNumber
+
+ # Convert ERC-20 Transfer event to our internal format
+ args = event["args"]
+ transfer = {
+ "from": args["from"],
+ "to": args.to,
+ "value": args.value,
+ "timestamp": block_when.isoformat(),
+ }
+
+ # 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).
+ # Create a tx entry that contains all events by a log index
+ self.state["blocks"][block_number][txhash] = {}
+
+ # Record ERC-20 transfer in our database
+ self.state["blocks"][block_number][txhash][log_index] = transfer
+
+ # Return a pointer that allows us to look up this event later if needed
+ return f"{block_number}-{txhash}-{log_index}"
+
+ def run():
+
+ if len(sys.argv) < 2:
+ print("Usage: eventscanner.py http://your-node-url")
+ sys.exit(1)
+
+ api_url = sys.argv[1]
+
+ # Enable logs to the stdout.
+ # DEBUG is very verbose level
+ logging.basicConfig(level=logging.INFO)
+
+ provider = HTTPProvider(api_url)
+
+ # Disable the default JSON-RPC retry configuration
+ # as it correctly cannot handle eth_getLogs block range
+ provider.exception_retry_configuration = None
+
+ w3 = Web3(provider)
+
+ # Prepare stub ERC-20 contract object
+ abi = json.loads(ABI)
+ ERC20 = w3.eth.contract(abi=abi)
+
+ # Restore/create our persistent state
+ state = JSONifiedState()
+ state.restore()
+
+ # chain_id: int, w3: Web3, abi: Dict, state: EventScannerState, events: List, filters: Dict, max_chunk_scan_size: int=10000
+ scanner = EventScanner(
+ w3=w3,
+ contract=ERC20,
+ state=state,
+ events=[ERC20.events.Transfer],
+ filters={"address": RCC_ADDRESS},
+ # How many maximum blocks at the time we request from JSON-RPC
+ # and we are unlikely to exceed the response size limit of the JSON-RPC server
+ 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)
+
+ # Scan from [last block scanned] - [latest ethereum block]
+ # Note that our chain reorg safety blocks cannot go negative
+ start_block = max(state.get_last_scanned_block() - chain_reorg_safety_blocks, 0)
+ end_block = scanner.get_suggested_scan_end_block()
+ blocks_to_scan = end_block - start_block
+
+ print(f"Scanning events from blocks {start_block} - {end_block}")
+
+ # Render a progress bar in the console
+ start = time.time()
+ with tqdm(total=blocks_to_scan) as progress_bar:
+ def _update_progress(start, end, current, current_block_timestamp, chunk_size, events_count):
+ 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)
+
+ # Run the scan
+ result, total_chunks_scanned = scanner.scan(start_block, end_block, progress_callback=_update_progress)
+
+ 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()
+
+
+.. _WETH: https://etherscan.io/token/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code
+.. _asyncio: https://docs.python.org/3/library/asyncio.html
+.. _gevent: https://www.gevent.org/
+.. _twisted: https://twistedmatrix.com/
+.. _celery: https://www.celeryproject.org/
diff --git a/_build/html_zh_CN/_sources/gas_price.rst.txt b/_build/html_zh_CN/_sources/gas_price.rst.txt
new file mode 100644
index 0000000000..62fbb9379b
--- /dev/null
+++ b/_build/html_zh_CN/_sources/gas_price.rst.txt
@@ -0,0 +1,119 @@
+.. _Gas_Price:
+
+Gas Price API
+===============
+
+.. 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.
+
+For Ethereum (legacy) transactions, gas price is a delicate property. For this reason,
+Web3 includes an API for configuring 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).
+
+Retrieving gas price
+--------------------
+
+To retrieve the gas price using the selected strategy simply call
+:meth:`~web3.eth.Eth.generate_gas_price`
+
+.. code-block:: python
+
+ >>> web3.eth.generate_gas_price()
+ 20000000000
+
+Creating a gas price strategy
+-------------------------------
+
+A gas price strategy is implemented as a python method with the following
+signature:
+
+.. code-block:: python
+
+ def gas_price_strategy(web3, transaction_params=None):
+ ...
+
+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.
+
+.. code-block:: python
+
+ from web3 import Web3
+
+ def value_based_gas_price_strategy(web3, transaction_params):
+ if transaction_params['value'] > Web3.to_wei(1, 'ether'):
+ return Web3.to_wei(20, 'gwei')
+ else:
+ return Web3.to_wei(5, 'gwei')
+
+Selecting the gas price strategy
+--------------------------------
+
+The gas price strategy can be set by calling :meth:`~web3.eth.Eth.set_gas_price_strategy`.
+
+.. code-block:: python
+
+ from web3 import Web3
+
+ def value_based_gas_price_strategy(web3, transaction_params):
+ ...
+
+ w3 = Web3(...)
+ w3.eth.set_gas_price_strategy(value_based_gas_price_strategy)
+
+Available gas price strategies
+------------------------------
+
+.. py:module:: web3.gas_strategies.rpc
+
+.. py:method:: 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.
+
+.. py:module:: web3.gas_strategies.time_based
+
+.. py:method:: 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 computed 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 seconds.
+ * ``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.
+
+ .. code-block:: python
+
+ from web3 import Web3
+ from web3.gas_strategies.time_based import medium_gas_price_strategy
+
+ w3 = Web3(...)
+ w3.eth.set_gas_price_strategy(medium_gas_price_strategy)
+
+ w3.provider.cache_allowed_requests = True
diff --git a/_build/html_zh_CN/_sources/index.rst.txt b/_build/html_zh_CN/_sources/index.rst.txt
new file mode 100644
index 0000000000..a6dafc28e2
--- /dev/null
+++ b/_build/html_zh_CN/_sources/index.rst.txt
@@ -0,0 +1,48 @@
+.. meta::
+ :description: Python Web3 SDK for Ethereum and EVM blockchains
+
+gm
+==
+
+.. image:: _static/banner/banner-snek.jpg
+ :alt: Banner Image
+
+**web3.py** is a Python library for interacting with Ethereum.
+
+It's commonly found in `decentralized apps (dapps)`_ to help with
+sending transactions, interacting with smart contracts, reading
+block data, and a variety of other use cases.
+
+For project updates, follow `@EthereumPython`_ and sign up
+for new post notifications on the `blog`_.
+
+
+Getting Started
+---------------
+
+.. NOTE::
+ 👋 Brand new to Ethereum?
+
+ 0. Don't travel alone! Join the Ethereum Python Community `Discord`_.
+ 1. Read this `blog post series`_ for a gentle introduction to Ethereum blockchain concepts.
+ 2. The :ref:`Overview` page will give you a quick idea of what else web3.py can do.
+ 3. Try building a little something!
+
+- Ready to code? → :ref:`quickstart`
+- Quick tour? → :ref:`overview`
+- Synchronous help? → `Discord`_
+- Asynchronous help? → `StackExchange`_
+- Report a bug? → `Github`_
+- Want to help us? → :ref:`Contribute `
+- Looking for inspiration? → :ref:`resources`
+
+.. include:: toc.rst
+
+
+.. _decentralized apps (dapps): https://ethereum.org/en/dapps/
+.. _@EthereumPython: https://twitter.com/EthereumPython
+.. _blog: https://snakecharmers.ethereum.org/
+.. _blog post series: https://snakecharmers.ethereum.org/a-developers-guide-to-ethereum-pt-1
+.. _StackExchange: https://ethereum.stackexchange.com/questions/tagged/web3.py
+.. _Discord: https://discord.gg/GHryRvPB84
+.. _Github: https://github.com/ethereum/web3.py/issues
diff --git a/_build/html_zh_CN/_sources/internals.rst.txt b/_build/html_zh_CN/_sources/internals.rst.txt
new file mode 100644
index 0000000000..58b1b56a85
--- /dev/null
+++ b/_build/html_zh_CN/_sources/internals.rst.txt
@@ -0,0 +1,622 @@
+Web3 Internals
+==============
+
+
+.. 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.
+* **Middleware** provide hooks for monitoring and modifying requests and
+ responses to and from the 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 a remote node and all *write* operations
+ to a local 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
+
+
+Request Lifecycle
+-----------------
+
+Each web3 RPC call passes through these layers in the following manner.
+
+.. code-block:: none
+
+ *********** ************
+ | Request | | Response |
+ *********** ************
+ | ^
+ v |
+ +-----------------------------+
+ | Manager |
+ +-----------------------------+
+ | ^
+ v |
+ +-----------------------------+
+ | Middleware |
+ +-----------------------------+
+ | ^
+ v |
+ +-----------------------------+
+ | Provider |
+ +-----------------------------+
+
+
+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``.
+
+
+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
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Writing your own provider requires implementing two required methods as well as
+setting the middleware the provider should use.
+
+
+.. py:method:: 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.
+
+
+.. py:method:: 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*.
+
+
+.. py:attribute:: BaseProvider.middleware
+
+ This should be an iterable of middleware.
+
+You can set a new list of middleware by assigning to ``provider.middleware``,
+with the first middleware that processes the request at the beginning of the list.
+
+
+Provider Configurations
+~~~~~~~~~~~~~~~~~~~~~~~
+
+.. _request_caching:
+
+Request Caching
+```````````````
+
+.. important::
+ Familiarize yourself with the validation logic for request caching before
+ enabling it. Since this feature often requires making additional requests under the
+ hood to try to guarantee the validity of the data, it may create unnecessary
+ overhead for your use case. Validation can be turned off by setting the
+ ``request_cache_validation_threshold`` option to ``None``, caching all allowed
+ requests, or configured for adjusting performance to your needs.
+
+
+Request caching can be configured at the provider level via the following configuration
+options on the provider instance:
+
+- ``cache_allowed_requests: bool = False``
+- ``cacheable_requests: Optional[Set[RPCEndpoint]]``
+- ``request_cache_validation_threshold: Optional[Union[RequestCacheValidationThreshold, int]]``
+
+For requests that don't rely on block data (e.g., ``eth_chainId``), enabling request
+caching by setting the ``cache_allowed_requests`` option to ``True`` will cache all
+responses. This is safe to do.
+
+However, for requests that rely on block data (e.g., ``eth_getBlockByNumber``), it is
+not safe to always cache their responses because block data can change - during a
+chain reorganization or while finality has not been reached, for example. The
+``request_cache_validation_threshold`` option allows configuring a safe threshold for
+caching responses that depend on block data. By default, this option is configured
+to internal values deemed "safe" for the chain id you are connected to. If you are
+connected to mainnet Ethereum, this value is set to the ``finalized`` block number.
+If you are connected to another chain, this value is set to a time interval in seconds,
+from the current time, that is deemed "safe" for that chain's finality mechanism.
+
+**It's important to understand that, in order to perform these validations, extra
+requests are sometimes made to the node to get the appropriate information. For a
+transaction request, for example, it is necessary to get the block information to
+validate the transaction is beyond the safe threshold. This can create overhead,
+especially for high-frequency requests. For this reason, it is important to understand
+when to turn on caching and how to configure the validation appropriately for your
+use case in order to avoid unnecessary overhead.**
+
+We keep a list of some reasonable values for bigger chains and
+use the time interval of 1 hour for everything else. Below is a list of the default
+values for internally configured chains:
+
+ - ETH: RequestCacheValidationThreshold.FINALIZED ("finalized" block)
+ - ARB1: 7 days
+ - ZKSYNC: 1 hour
+ - OETH: 3 minutes
+ - MATIC: 30 minutes
+ - ZKEVM: 1 hour
+ - BASE: 7 days
+ - SCR: 1 hour
+ - GNO: 5 minutes
+ - AVAX: 2 minutes
+ - BNB: 2 minutes
+ - FTM: 1 minute
+
+For Ethereum mainnet, for example, this means that a request's response will be cached
+if the block number the request relies on is less than or equal to the ``finalized``
+block number. If the block number exceeds the ``finalized`` block number, the response
+won't be cached. For all others, the response will be cached if the block timestamp
+related to the data that is being requested is older than or equal to the time interval
+configured for that chain. For any chain not on this list, the default value is set to
+1 hour (this includes all testnets).
+
+This behavior can be modified by setting the ``request_cache_validation_threshold``
+option to ``RequestCacheValidationThreshold.SAFE``, which uses the ``safe`` block as
+the threshold (Ethereum mainnet only), to your own time interval in seconds (for any
+chain, including mainnet Ethereum), or to ``None``, which disables any validation and
+caches all requests (this is not recommended for non testnet chains). The
+``RequestCacheValidationThreshold`` enum, for mainnet ``finalized`` and ``safe`` values,
+is imported from the ``web3.utils`` module.
+
+Note that the ``cacheable_requests`` option can be used to specify a set of RPC
+endpoints that are allowed to be cached. By default, this option is set to an internal
+list of deemed-safe-to-cache endpoints, excluding endpoints such as ``eth_call``, whose
+responses can vary and are not safe to cache. The default list of cacheable requests is
+below, with requests validated by the ``request_cache_validation_threshold`` option in
+bold:
+
+ - eth_chainId
+ - web3_clientVersion
+ - net_version
+ - **eth_getBlockByNumber**
+ - **eth_getRawTransactionByBlockNumberAndIndex**
+ - **eth_getBlockTransactionCountByNumber**
+ - **eth_getUncleByBlockNumberAndIndex**
+ - **eth_getUncleCountByBlockNumber**
+ - **eth_getBlockByHash**
+ - **eth_getTransactionByHash**
+ - **eth_getTransactionByBlockNumberAndIndex**
+ - **eth_getTransactionByBlockHashAndIndex**
+ - **eth_getBlockTransactionCountByHash**
+ - **eth_getRawTransactionByBlockHashAndIndex**
+ - **eth_getUncleByBlockHashAndIndex**
+ - **eth_getUncleCountByBlockHash**
+
+.. code-block:: python
+
+ from web3 import Web3, HTTPProvider
+ from web3.utils import RequestCacheValidationThreshold
+
+ w3 = Web3(HTTPProvider(
+ endpoint_uri="...",
+
+ # optional flag to turn on cached requests, defaults to ``False``
+ cache_allowed_requests=True,
+
+ # optional, defaults to an internal list of deemed-safe-to-cache endpoints (see above)
+ cacheable_requests={"eth_chainId", "eth_getBlockByNumber"},
+
+ # optional, defaults to a value that is based on the chain id (see above)
+ request_cache_validation_threshold=60 * 60, # 1 hour
+ # request_cache_validation_threshold=RequestCacheValidationThreshold.SAFE, # Ethereum mainnet only
+ ))
+
+.. _http_retry_requests:
+
+Retry Requests for HTTP Providers
+`````````````````````````````````
+
+``HTTPProvider`` and ``AsyncHTTPProvider`` instances retry certain requests by default
+on exceptions. This can be configured via the ``exception_retry_configuration``
+property on the provider instance, which takes a
+:class:`~web3.providers.rpc.utils.ExceptionRetryConfiguration` class as its value. The
+retry mechanism employs an exponential backoff strategy, starting from the initial
+value determined by the ``backoff_factor``, and doubling the delay with each attempt,
+up to the ``retries`` value. Below is an example showing the default options for the
+retry configuration and how to override them.
+
+
+.. py:class:: web3.providers.rpc.utils.ExceptionRetryConfiguration
+
+ .. py:attribute:: errors
+
+ A tuple of exceptions that the provider should retry on. The default is
+ ``HTTPProvider``: ``(ConnectionError, requests.HTTPError, requests.Timeout)``
+ and ``AsyncHTTPProvider``: ``(aiohttp.ClientError, asyncio.TimeoutError)``.
+
+ .. py:attribute:: retries
+
+ The number of retries to attempt. The default is 5.
+
+ .. py:attribute:: backoff_factor
+
+ The initial delay multiplier, which doubles with each retry attempt. The default
+ is 0.125.
+
+ .. py:attribute:: method_allowlist
+
+ A list of retryable methods. The default is an in-house list of deemed-safe-to-
+ retry methods.
+
+.. code-block:: python
+
+ from web3 import Web3, HTTPProvider
+ from web3.providers.rpc.utils import (
+ REQUEST_RETRY_ALLOWLIST,
+ ExceptionRetryConfiguration,
+ )
+
+ w3 = Web3(HTTPProvider(
+ endpoint_uri="...",
+ exception_retry_configuration=ExceptionRetryConfiguration(
+ errors=DEFAULT_EXCEPTIONS,
+
+ # number of retries to attempt
+ retries=5,
+
+ # initial delay multiplier, doubles with each retry attempt
+ backoff_factor=0.125,
+
+ # an in-house default list of retryable methods
+ method_allowlist=REQUEST_RETRY_ALLOWLIST,
+ ),
+ ))
+
+For the different http providers, ``DEFAULT_EXCEPTIONS`` is defined as:
+
+- ``HTTPProvider``: ``(ConnectionError, requests.HTTPError, requests.Timeout)``
+- ``AsyncHTTPProvider``: ``(ConnectionError, aiohttp.ClientError, asyncio.TimeoutError)``
+
+Setting ``retry_configuration`` to ``None`` will disable retries on exceptions for the
+provider instance.
+
+.. code-block:: python
+
+ from web3 import Web3, HTTPProvider
+
+ w3 = Web3(HTTPProvider(endpoint_uri="...", retry_configuration=None)
+
+
+
+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.
+
+.. _internals__persistent_connection_providers:
+
+Request Processing for Persistent Connection Providers
+------------------------------------------------------
+
+.. py:class:: web3.providers.persistent.request_processor.RequestProcessor
+
+The ``RequestProcessor`` class is responsible for the storing and syncing up of
+asynchronous requests to responses for a ``PersistentConnectionProvider``. The
+:class:`~web3.providers.persistent.WebSocketProvider` and the
+:class:`~web3.providers.persistent.AsyncIPCProvider` are two persistent connection
+providers. In order to send a request and receive a response to that same request,
+``PersistentConnectionProvider`` instances have to match request *id* values to
+response *id* values coming back from the socket connection. 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.
+
+Listening for Responses
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Implementations of the ``PersistentConnectionProvider`` class have a message listener
+background task that is called when the socket connection is established. This task
+is responsible for listening for any and all messages coming in over the socket
+connection and storing them in the ``RequestProcessor`` instance internal to the
+``PersistentConnectionProvider`` instance. The ``RequestProcessor`` instance is
+responsible for storing the messages 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.
+
+.. code-block:: python
+
+ >>> async def ws_one_to_one_example():
+ ... async with AsyncWeb3(WebSocketProvider(f"ws://127.0.0.1:8546")) as w3:
+ ... # make a request and expect a single response returned on the same line
+ ... latest_block_num = await w3.eth.block_number
+
+ >>> asyncio.run(ws_one_to_one_example())
+
+With persistent socket connections, we have to call ``send()`` and asynchronously
+receive responses via another means, generally by calling ``recv()`` or by iterating
+on the socket connection for messages. As outlined above, the
+``PersistentConnectionProvider`` class has a message listener background task that
+handles the receiving of messages.
+
+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 middleware 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.
+
+.. py:class:: web3._utils.caching.RequestInformation
+
+ .. py:attribute:: method
+
+ The name of the method - e.g. "eth_subscribe".
+
+ .. py:attribute:: params
+
+ The params used when the call was made - e.g. ("newPendingTransactions", True).
+
+ .. py:attribute:: response_formatters
+
+ The formatters that will be used to process the response.
+
+ .. py:attribute:: 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.
+
+ .. py:attribute:: 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 response 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 response, 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. The many responses this call will produce can be handled in one
+of a few ways.
+
+The recommended way to handle one-to-many responses is to use the subscription manager
+API. The subscription manager API is a public API on the ``AsyncWeb3`` class, when
+connected to a ``PersistentConnectionProvider`` instance, that allows the user to
+subscribe to a subscription and handle the many responses asynchronously. The
+``subscription_manager`` instance is responsible for handling the many responses that
+come in over the socket connection, as long as handlers are passed to each subscription
+call. The subscription manager can also be used to unsubscribe from a subscription when
+the user is done with it.
+
+.. code-block:: python
+
+ >>> async def new_heads_handler(
+ ... handler_context: NewHeadsSubscriptionContext,
+ ... ) -> None:
+ ... result = handler_context.result
+ ... print(f"New block header: {result}\n")
+ ... if result["number"] > 1234567:
+ ... await handler_context.subscription.unsubscribe()
+
+ >>> async def ws_subscription_example():
+ ... async with AsyncWeb3(WebSocketProvider(f"ws://127.0.0.1:8546")) as w3:
+ ... # Subscribe to new block headers and receive the subscription_id.
+ ... # A one-to-one call with a trigger for many responses
+ ... subscription_id = await w3.eth.subscribe("newHeads", handler=new_heads_handler)
+ ...
+ ... # Handle the subscription messages asynchronously using the subscription
+ ... # manager. This will continue until no more subscriptions are present in
+ ... # the subscription manager, or indefinitely if the `run_forever` flag
+ ... # is set to `True`.
+ ... await w3.subscription_manager.handle_subscriptions(run_forever=False)
+ >>> asyncio.run(ws_subscription_example())
+
+The manager can also subscribe to many subscriptions at one time. The
+``EthSubscription`` classes, available via ``web3.utils.subscriptions``, provide a
+friendly API for managing subscriptions. Since each connection and provider instance
+has its own message listener task and subscription manager instance, you can subscribe
+to many subscriptions at once and handle the many responses that come in over the socket
+connections via handlers. The handlers contain:
+
+- ``async_w3``: The ``AsyncWeb3`` instance that the subscription was made on.
+- ``subscription``: The subscription instance that the handler is attached to.
+- ``result``: The response that came in over the socket connection for the subscription.
+
+Subscriptions also accept a ``handler_context`` argument that can be used to pass
+additional information to the handler when subscribing to a subscription. This can be
+used to pass in an event object, for example, that can be used to parse a log event
+when it comes in.
+
+
+.. code-block:: python
+
+ >>> from web3 import (
+ ... AsyncWeb3,
+ ... WebSocketProvider,
+ ... AsyncIPCProvider,
+ ... )
+ >>> from web3.utils.subscriptions import (
+ ... EthSubscription,
+ ... NewHeadsSubscription,
+ ... NewHeadsSubscriptionContext,
+ ... PendingTxSubscription,
+ ... PendingTxSubscriptionContext,
+ ... LogsSubscription,
+ ... LogsSubscriptionContext,
+ ... )
+
+ >>> async def new_heads_handler(
+ ... handler_context: NewHeadsSubscriptionContext,
+ ... ) -> None:
+ ... header = handler_context.result
+ ... print(f"New block header: {header}\n")
+ ... if header["number"] > 1234567:
+ ... await handler_context.subscription.unsubscribe()
+
+ >>> async def pending_txs_handler(
+ ... handler_context: PendingTxSubscriptionContext,
+ ... ) -> None:
+ ... ...
+
+ >>> async def log_handler(
+ ... handler_context: LogsSubscriptionContext,
+ ... ) -> None:
+ ... log_receipt = handler_context.result
+ ... # event is now available in the handler context, because we pass it to in the
+ ... # ``handler_context`` when subscribing to the log
+ ... event_data = handler_context.transfer_event.process_log(log_receipt)
+ ... print(f"Log event data: {event_data}\n")
+
+ >>> async def sub_manager():
+ ... local_w3 = await AsyncWeb3(AsyncIPCProvider(LOCAL_IPC))
+ ...
+ ... # subscribe to many subscriptions via the subscription manager with handlers
+ ... weth_contract = local_w3.eth.contract(
+ ... address=local_w3.to_checksum_address("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
+ ... abi=WETH_ABI,
+ ... )
+ ... transfer_event = weth_contract.events.Transfer()
+ ... await local_w3.subscription_manager.subscribe(
+ ... [
+ ... NewHeadsSubscription(label="new-heads-mainnet", handler=new_heads_handler),
+ ... PendingTxSubscription(
+ ... label="pending-tx-mainnet", # optional label
+ ... full_transactions=True,
+ ... handler=pending_tx_handler,
+ ... ),
+ ... LogsSubscription(
+ ... label="WETH transfers", # optional label
+ ... address=weth_contract.address,
+ ... topics=[transfer_event.topic],
+ ... handler=log_handler,
+ ... # optional ``handler_context`` args to help parse a response
+ ... handler_context={"transfer_event": transfer_event},
+ ... ),
+ ... ]
+ ... )
+ ...
+ ... public_w3 = await AsyncWeb3(WebSocketProvider(PUBLIC_PROVIDER_WS))
+ ... # subscribe via eth_subscribe, with handler and label (optional)
+ ... await public_w3.eth.subscribe("public_newHeads", handler=pending_tx_handler, label="new-heads-public-ws")
+
+ >>> # This will handle all subscriptions until no more subscriptions are present
+ ... # in either subscription manager instance. If the `run_forever` flag is set
+ ... # to `True` on any manager instance, this will run indefinitely.
+ >>> await asyncio.gather(
+ ... public_w3.subscription_manager.handle_subscriptions(),
+ ... local_w3.subscription_manager.handle_subscriptions(),
+ ... )
+ ...
+ ... # close the connections
+ ... await local_w3.provider.disconnect()
+ ... await public_w3.provider.disconnect()
+
+ >>> asyncio.run(sub_manager())
+
+
+The ``process_subscriptions()`` method on the
+:class:`~web3.providers.persistent.PersistentConnection` class, the public API for
+interacting with the active persistent socket connection, is also set up to receive
+``eth_subscription`` responses over an asynchronous iterator pattern. You can use this
+method to listen for raw messages and process them as they come in.
+
+.. code-block:: python
+
+ >>> async def ws_subscription_example():
+ ... async with AsyncWeb3(WebSocketProvider(f"ws://127.0.0.1:8546")) as w3:
+ ... # Subscribe to new block headers and receive the subscription_id.
+ ... # A one-to-one call with a trigger for many responses
+ ... subscription_id = await w3.eth.subscribe("newHeads")
+ ...
+ ... # Listen to the socket for the many responses utilizing the
+ ... # ``w3.socket`` ``PersistentConnection`` public API method
+ ... # ``process_subscriptions()``
+ ... async for response in w3.socket.process_subscriptions():
+ ... # Receive only one-to-many responses here so that we don't
+ ... # accidentally return the response for a one-to-one request in this
+ ... # block
+ ...
+ ... print(f"{response}\n")
+ ...
+ ... if some_condition:
+ ... # unsubscribe from new block headers, another one-to-one request
+ ... is_unsubscribed = await w3.eth.unsubscribe(subscription_id)
+ ... if is_unsubscribed:
+ ... break
+
+ >>> asyncio.run(ws_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 ``PersistentConnection`` class is set up
+to pop messages from this queue as FIFO over an asynchronous iterator pattern.
+
+If the stream of messages from the socket is not being interrupted by any other
+tasks, the queue will generally be in sync with the messages coming in over the
+socket. 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 socket
+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.
diff --git a/_build/html_zh_CN/_sources/middleware.rst.txt b/_build/html_zh_CN/_sources/middleware.rst.txt
new file mode 100644
index 0000000000..c1fb43f38a
--- /dev/null
+++ b/_build/html_zh_CN/_sources/middleware.rst.txt
@@ -0,0 +1,613 @@
+.. _middleware_internals:
+
+Middleware
+==========
+
+``Web3`` is instantiated with layers of middleware by default. They sit between the public
+``Web3`` methods and the :doc:`providers`, and are used to perform sanity checks, convert data
+types, enable ENS support, and more. Each layer can modify the request and/or response.
+While several middleware are enabled by default, others are available for optional use,
+and you're free to create your own!
+
+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 middleware that are in deeper layers).
+
+
+.. _Modifying_Middleware:
+
+Configuring Middleware
+-----------------------
+
+Middleware can be added, removed, replaced, and cleared at runtime. To make that easier, you
+can name the middleware for later reference.
+
+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:
+
+.. code-block:: none
+
+ New request from web3.py
+
+ |
+ |
+ 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
+
+ Returned value in web3.py
+
+
+The middleware are maintained in ``Web3.middleware_onion``. See below for the API.
+
+When specifying middleware in a list, or retrieving the list of middleware, they will
+be returned in the order of outermost layer first and innermost layer last. In the above
+example, that means that ``w3.middleware_onion.middleware`` would return the middleware
+in the order of: ``[2, 1, 0]``.
+
+
+.. _middleware_stack_api:
+
+Middleware Stack API
+~~~~~~~~~~~~~~~~~~~~
+
+To add or remove items in different layers, use the following API:
+
+.. py:method:: Web3.middleware_onion.add(middleware, name=None)
+
+ Middleware will be added to the outermost layer. That means the new middleware will modify the
+ request first, and the response last. You can optionally name it with any hashable object,
+ typically a string.
+
+ .. code-block:: python
+
+ >>> w3 = Web3(...)
+ >>> w3.middleware_onion.add(web3.middleware.GasPriceStrategyMiddleware)
+ # or
+ >>> w3.middleware_onion.add(web3.middleware.GasPriceStrategyMiddleware, 'gas_price_strategy')
+
+.. py:method:: Web3.middleware_onion.inject(middleware, name=None, layer=None)
+
+ Inject a named middleware to an arbitrary layer.
+
+ The current implementation only supports injection at the innermost or
+ outermost layers. Note that injecting to the outermost layer is equivalent to calling
+ :meth:`Web3.middleware_onion.add` .
+
+ .. code-block:: python
+
+ # Either of these will put the gas_price_strategy middleware at the innermost layer
+ >>> w3 = Web3(...)
+ >>> w3.middleware_onion.inject(web3.middleware.GasPriceStrategyMiddleware, layer=0)
+ # or
+ >>> w3.middleware_onion.inject(web3.middleware.GasPriceStrategyMiddleware, 'gas_price_strategy', layer=0)
+
+.. py:method:: 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:
+
+ .. code-block:: python
+
+ >>> w3 = Web3(...)
+ >>> w3.middleware_onion.remove(web3.middleware.GasPriceStrategyMiddleware)
+ # or
+ >>> w3.middleware_onion.remove('gas_price_strategy')
+
+.. py:method:: 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.
+
+ .. code-block:: python
+
+ >>> from web3.middleware import GasPriceStrategyMiddleware, AttributeDictMiddleware
+ >>> w3 = Web3(provider, middleware=[GasPriceStrategyMiddleware, AttributeDictMiddleware])
+
+ >>> w3.middleware_onion.replace(GasPriceStrategyMiddleware, AttributeDictMiddleware)
+ # this is now referenced by the new middleware object, so to remove it:
+ >>> w3.middleware_onion.remove(AttributeDictMiddleware)
+
+ # or, if it was named
+
+ >>> w3.middleware_onion.replace('gas_price_strategy', AttributeDictMiddleware)
+ # this is still referenced by the original name, so to remove it:
+ >>> w3.middleware_onion.remove('gas_price_strategy')
+
+.. py:method:: Web3.middleware_onion.clear()
+
+ Empty all the middleware, including the default ones.
+
+ .. code-block:: python
+
+ >>> w3 = Web3(...)
+ >>> w3.middleware_onion.clear()
+ >>> assert len(w3.middleware_onion) == 0
+
+.. py:attribute:: Web3.middleware_onion.middleware
+
+ Return all the current middleware for the ``Web3`` instance in the appropriate order for importing into a new
+ ``Web3`` instance.
+
+ .. code-block:: python
+
+ >>> w3_1 = Web3(...)
+ # add uniquely named middleware:
+ >>> w3_1.middleware_onion.add(web3.middleware.GasPriceStrategyMiddleware, 'test_middleware')
+ # export middleware from first w3 instance
+ >>> middleware = w3_1.middleware_onion.middleware
+
+ # import into second instance
+ >>> w3_2 = Web3(..., middleware=middleware)
+ >>> assert w3_1.middleware_onion.middleware == w3_2.middleware_onion.middleware
+ >>> assert w3_2.middleware_onion.get('test_middleware')
+
+
+Instantiate with Custom Middleware
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Instead of working from the default list, you can specify a custom list of
+middleware when initializing Web3:
+
+.. code-block:: python
+
+ Web3(middleware=[my_middleware1, my_middleware2])
+
+.. warning::
+ This will *replace* the default middleware. To keep the default functionality,
+ either use ``middleware_onion.add()`` from above, or add the default middleware to
+ your list of new middleware.
+
+
+.. _default_middleware:
+
+Default Middleware
+------------------
+
+The following middleware are included by default:
+
+* ``gas_price_strategy``
+* ``ens_name_to_address``
+* ``attrdict``
+* ``validation``
+* ``gas_estimate``
+
+The defaults are defined in the ``get_default_middleware()`` method in ``web3/manager.py``.
+
+AttributeDict
+~~~~~~~~~~~~~
+
+.. py:class:: web3.middleware.AttributeDictMiddleware
+
+ 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.
+
+ENS Name to Address Resolution
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. py:class:: web3.middleware.ENSNameToAddressMiddleware
+
+ This middleware converts Ethereum Name Service (ENS) names into the
+ address that the name points to. For example :meth:`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.
+
+Gas Price Strategy
+~~~~~~~~~~~~~~~~~~
+
+.. py:class:: web3.middleware.GasPriceStrategyMiddleware
+
+ .. 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 :ref:`Gas_Price` for information about how gas price is derived.
+
+Buffered Gas Estimate
+~~~~~~~~~~~~~~~~~~~~~
+
+.. py:class:: web3.middleware.BufferedGasEstimateMiddleware
+
+ 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
+
+Validation
+~~~~~~~~~~
+
+.. py:class:: web3.middleware.ValidationMiddleware
+
+ This middleware includes block and transaction validators which perform validations
+ for transaction parameters.
+
+
+Optional Middleware
+-------------------
+
+``Web3`` includes optional middleware for common use cases. Below is a list of available
+middleware which are not enabled by default.
+
+Stalecheck
+~~~~~~~~~~~~
+
+.. py:method:: web3.middleware.StalecheckMiddlewareBuilder
+
+ 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.
+
+ .. code-block:: python
+
+ two_day_stalecheck = StalecheckMiddlewareBuilder.build(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()``.
+
+
+.. _geth-poa:
+
+Proof of Authority
+~~~~~~~~~~~~~~~~~~
+
+.. py:class:: web3.middleware.ExtraDataToPOAMiddleware
+
+.. important::
+ It is **crucial** that this middleware is injected at the 0th layer of the
+ middleware onion, using
+ ``w3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)``, to guarantee
+ it is the *first* middleware to process the response and modify the ``extraData``
+ field. This ensures it processes the field before any other middleware attempts
+ to validate it.
+
+``ExtraDataToPOAMiddleware`` is required to connect to ``geth --dev`` and 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.
+
+.. code-block:: shell
+
+ web3.exceptions.ExtraDataLengthError: The field extraData is 97 bytes, but should be
+ 32. It is quite likely that you are connected to a POA chain. Refer to
+ http://web3py.readthedocs.io/en/stable/middleware.html#proof-of-authority
+ for more details. The full extraData is: HexBytes('...')
+
+The easiest way to connect to a default ``geth --dev`` instance which loads the
+middleware is:
+
+.. code-block:: python
+
+ >>> from web3.auto.gethdev import w3
+
+ # confirm that the connection succeeded
+ >>> w3.client_version
+ 'Geth/v1.14.12-stable-4bb3c89d/linux-amd64/go1.22.4'
+
+This example connects to a local ``geth --dev`` instance on Linux with a
+unique IPC location and loads the middleware:
+
+.. code-block:: python
+
+ >>> from web3 import Web3, IPCProvider
+
+ # connect to the IPC location started with 'geth --dev --datadir ~/mynode'
+ >>> w3 = Web3(IPCProvider('~/mynode/geth.ipc'))
+
+ >>> from web3.middleware import ExtraDataToPOAMiddleware
+
+ # inject the poa compatibility middleware to the innermost layer (0th layer)
+ >>> w3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
+
+ # confirm that the connection succeeded
+ >>> w3.client_version
+ 'Geth/v1.14.12-stable-4bb3c89d/linux-amd64/go1.22.4'
+
+Why is ``ExtraDataToPOAMiddleware`` necessary?
+''''''''''''''''''''''''''''''''''''''''''''''
+
+There is no strong community consensus on a single Proof-of-Authority (PoA) standard yet.
+Some nodes have successful 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 is one such example
+where PoA uses more than 32 bytes, so this middleware modifies the block data a bit
+before returning it.
+
+.. _local-filter:
+
+Locally Managed Log and Block Filters
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. py:method:: web3.middleware.LocalFilterMiddleware
+
+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.
+
+.. doctest::
+
+ >>> from web3 import Web3, EthereumTesterProvider
+ >>> w3 = Web3(EthereumTesterProvider())
+ >>> from web3.middleware import LocalFilterMiddleware
+ >>> w3.middleware_onion.add(LocalFilterMiddleware)
+
+.. code-block:: python
+
+ # Normal block and log filter apis behave as before.
+ >>> block_filter = w3.eth.filter("latest")
+
+ >>> log_filter = myContract.events.myEvent.build_filter().deploy()
+
+Signing
+~~~~~~~
+
+.. py:method:: web3.middleware.SignAndSendRawMiddlewareBuilder
+
+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.
+
+The ``build`` method for this middleware builder takes a single argument:
+
+ * ``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
+
+.. important::
+ Since this middleware signs transactions, it must always run after any middleware
+ that modifies the transaction. Therefore, it is recommended to inject the signing
+ middleware at the 0th layer of the middleware onion using
+ ``w3.middleware_onion.inject(SignAndSendRawMiddlewareBuilder.build(...), layer=0)``.
+ Ensure that any transaction-modifying middleware exists in a higher layer within the
+ onion so that it runs before the signing middleware.
+
+.. note::
+ If used with ``ExtraDataToPOAMiddleware``, the injection order doesn't matter, as
+ the ``extraData`` field isn't involved in transaction signing. The key is ensuring
+ ``SignAndSendRawMiddlewareBuilder`` runs after any middleware that modifies the
+ transaction.
+
+
+.. code-block:: python
+
+ >>> from web3 import Web3, EthereumTesterProvider
+ >>> w3 = Web3(EthereumTesterProvider)
+ >>> from web3.middleware import SignAndSendRawMiddlewareBuilder
+ >>> from eth_account import Account
+ >>> acct = Account.create('KEYSMASH FJAFJKLDSKF7JKFDJ 1530')
+ >>> w3.middleware_onion.inject(SignAndSendRawMiddlewareBuilder.build(acct), layer=0)
+ >>> w3.eth.default_account = acct.address
+
+:ref:`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
+``SignAndSendRawMiddlewareBuilder.build(private_key_or_account)``.
+
+.. code-block:: python
+
+ >>> from web3 import Web3
+ >>> w3 = Web3(Web3.HTTPProvider('HTTP_ENDPOINT'))
+ >>> from web3.middleware import SignAndSendRawMiddlewareBuilder
+ >>> from eth_account import Account
+ >>> import os
+ >>> acct = w3.eth.account.from_key(os.environ.get('PRIVATE_KEY'))
+ >>> w3.middleware_onion.inject(SignAndSendRawMiddlewareBuilder.build(acct), layer=0)
+ >>> w3.eth.default_account = acct.address
+
+ >>> # use `eth_sendTransaction` to automatically sign and send the raw transaction
+ >>> w3.eth.send_transaction(tx_dict)
+ HexBytes('0x09511acf75918fd03de58141d2fd409af4fd6d3dce48eb3aa1656c8f3c2c5c21')
+
+Similarly, with AsyncWeb3:
+
+.. code-block:: python
+
+ >>> from web3 import AsyncWeb3
+ >>> async_w3 = AsyncWeb3(AsyncHTTPProvider('HTTP_ENDPOINT'))
+ >>> from web3.middleware import SignAndSendRawMiddlewareBuilder
+ >>> from eth_account import Account
+ >>> import os
+ >>> acct = async_w3.eth.account.from_key(os.environ.get('PRIVATE_KEY'))
+ >>> async_w3.middleware_onion.inject(SignAndSendRawMiddlewareBuilder.build(acct), layer=0)
+ >>> async_w3.eth.default_account = acct.address
+
+ >>> # 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 transactions),
+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 effectively replace the legacy ``gasPrice`` value, do not set a ``gasPrice`` for dynamic fee transactions.
+Doing so will lead to validation issues.
+
+.. code-block:: python
+
+ # dynamic fee transaction, introduced by EIP-1559:
+ >>> dynamic_fee_transaction = {
+ ... 'type': '0x2', # optional - defaults to '0x2' when dynamic fee transaction params are present
+ ... 'from': acct.address, # optional if w3.eth.default_account was set with acct.address
+ ... 'to': receiving_account_address,
+ ... 'value': 22,
+ ... 'maxFeePerGas': 2000000000, # required for dynamic fee transactions
+ ... 'maxPriorityFeePerGas': 1000000000, # required for dynamic fee transactions
+ ... }
+ >>> w3.eth.send_transaction(dynamic_fee_transaction)
+
+A legacy transaction still works in the same way as it did before EIP-1559 was introduced:
+
+.. code-block:: python
+
+ >>> 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)
+
+
+Creating Custom Middleware
+--------------------------
+
+To write your own middleware, create a class and extend from the base ``Web3Middleware``
+class, then override only the parts of the middleware that make sense for your use case.
+
+.. note:: The Middleware API borrows from the Django middleware API introduced
+ in version 1.10.0.
+
+If all you need is to modify the params before a request is made, you can override
+the ``request_processor`` method, make the necessary tweaks to the params, and pass the
+arguments to the next element in the middleware stack. Need to do some processing on the
+response? Override the ``response_processor`` method and return the modified response.
+
+The pattern:
+
+.. code-block:: python
+
+ from web3.middleware import Web3Middleware
+
+ class CustomMiddleware(Web3Middleware):
+
+ def request_processor(self, method, params):
+ # Pre-request processing goes here before passing to the next middleware.
+ return (method, params)
+
+ def response_processor(self, method, response):
+ # Response processing goes here before passing to the next middleware.
+ return response
+
+ # If your provider is asynchronous, override the async methods instead:
+
+ async def async_request_processor(self, method, params):
+ # Pre-request processing goes here before passing to the next middleware.
+ return (method, params)
+
+ async def async_response_processor(self, method, response):
+ # Response processing goes here before passing to the next middleware.
+ return response
+
+
+If you wish to prevent making a call under certain conditions, you can override the
+``wrap_make_request`` method. This allows for defining pre-request processing,
+skipping or making the request under certain conditions, as well as response
+processing before passing it to the next middleware.
+
+
+.. code-block:: python
+
+ from web3.middleware import Web3Middleware
+
+ class CustomMiddleware(Web3Middleware):
+
+ def wrap_make_request(self, make_request):
+ def middleware(method, params):
+ # pre-request processing goes here
+ response = make_request(method, params) # make the request
+ # response processing goes here
+ return response
+
+ return middleware
+
+ # If your provider is asynchronous, override the async method instead:
+
+ async def async_wrap_make_request(self, make_request):
+ async def middleware(method, params):
+ # pre-request processing goes here
+ response = await make_request(method, params)
+ # response processing goes here
+ return response
+
+ return middleware
+
+
+Custom middleware can be added to the stack via the class itself, using the
+:ref:`middleware_stack_api`. The ``name`` kwarg is optional. For example:
+
+.. code-block:: python
+
+ from web3 import Web3
+ from my_module import (
+ CustomMiddleware,
+ )
+
+ w3 = Web3(HTTPProvider(endpoint_uri="..."))
+
+ # add the middleware to the stack as the class
+ w3.middleware_onion.add(CustomMiddleware, name="custom_middleware")
diff --git a/_build/html_zh_CN/_sources/migration.rst.txt b/_build/html_zh_CN/_sources/migration.rst.txt
new file mode 100644
index 0000000000..b9d5a68947
--- /dev/null
+++ b/_build/html_zh_CN/_sources/migration.rst.txt
@@ -0,0 +1,779 @@
+Migration Guide
+===============
+
+.. _migrating_v6_to_v7:
+
+Migrating from v6 to v7
+-----------------------
+
+web3.py follows `Semantic Versioning `_, which means that
+version 7 introduced backwards-incompatible changes. If you're upgrading from
+web3.py ``v6`` or earlier, you can expect to need to make some changes. Refer
+to this guide for a summary of breaking changes when updating from ``v6`` to
+``v7``. If you are more than one major version behind, you should also review
+the migration guides for the versions in between.
+
+
+Provider Updates
+~~~~~~~~~~~~~~~~
+
+
+WebSocketProvider
+`````````````````
+
+``WebsocketProviderV2``, introduced in web3.py ``v6``, has taken priority over the
+legacy ``WebsocketProvider``. The ``LegacyWebSocketProvider`` has been deprecated in
+``v7`` and is slated for removal in the next major version of the library. In summary:
+
+- ``WebsocketProvider`` -> ``LegacyWebSocketProvider`` (and deprecated)
+- ``WebsocketProviderV2`` -> ``WebSocketProvider``
+
+If migrating from ``WebSocketProviderV2`` to ``WebSocketProvider``, you can expect the
+following changes:
+
+- Instantiation no longer requires the ``persistent_websocket`` method:
+
+ .. code-block:: python
+
+ # WebsocketsProviderV2:
+ AsyncWeb3.persistent_websocket(WebsocketProviderV2('...'))
+
+ # WebSocketProvider:
+ AsyncWeb3(WebSocketProvider('...'))
+
+- Handling incoming subscription messages now occurs under a more flexible namespace:
+ ``socket``. The ``AsyncIPCProvider`` uses the same API to listen for messages via
+ an IPC socket.
+
+ .. code-block:: python
+
+ # WebsocketsProviderV2:
+ async for message in w3.ws.process_subscriptions():
+ ...
+
+ # WebSocketProvider:
+ async for message in w3.socket.process_subscriptions():
+ ...
+
+
+AsyncIPCProvider (non-breaking feature)
+```````````````````````````````````````
+
+An asynchronous IPC provider, ``AsyncIPCProvider``, is newly available in ``v7``.
+This provider makes use of some of the same internals that the new ``WebSocketProvider``
+introduced, allowing it to also support ``eth_subscription``.
+
+
+EthereumTesterProvider
+``````````````````````
+
+``EthereumTesterProvider`` now returns ``input`` instead of ``data`` for ``eth_getTransaction*``
+calls, as expected.
+
+
+Middlewares -> Middleware
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+All references to ``middlewares`` have been replaced with the more grammatically
+correct ``middleware``. Notably, this includes when a provider needs to be
+instantiated with custom middleware.
+
+
+Class-Based Middleware Model
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The middleware model has been changed to a class-based model.
+
+.. code-block:: python
+
+ # v6 (no longer supported)
+ from web3.middleware import pythonic_middleware
+ w3.middleware_onion.add(pythonic_middleware)
+
+ # v7
+ from web3.middleware import PythonicMiddleware
+ w3.middleware_onion.add(PythonicMiddleware)
+
+Previously, middleware were defined as functions that tightly wrapped the provider's
+``make_request`` function, where transformations could be conditionally applied before
+and after the request was made.
+
+Now, middleware logic can be separated into ``request_processor`` and ``response_processor``
+functions that enable pre-request and post-response logic, respectively. This change offers
+a simpler, clearer interface for defining middleware, gives more flexibility for
+asynchronous operations and also paved the way for supporting :ref:`batch_requests`.
+
+Major changes for migration are highlighted in this section. Consult the
+:ref:`middleware_internals` section of the documentation for specifics and examples on
+the new class-based design.
+
+
+Middleware Builder Classes
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In ``v6``, certain middleware needed to be constructed with parameters. This was done
+by passing the parameters to a constructor method.
+
+.. code-block:: python
+
+ # v6 (no longer supported)
+ from web3.middleware import construct_sign_and_send_raw_middleware
+ w3.middleware_onion.add(construct_sign_and_send_raw_middleware(private_key))
+
+In the class-based ``v7`` middleware model, a middleware builder class is instantiated
+with the necessary parameters via the ``build()`` method.
+
+.. code-block:: python
+
+ # v7
+ from web3.middleware import SignAndSendRawMiddlewareBuilder
+ w3.middleware_onion.inject(SignAndSendRawMiddlewareBuilder.build(private_key), layer=0)
+
+
+Middleware Renaming and Removals
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following middleware have been renamed for generalization or clarity:
+
+- ``name_to_address_middleware`` -> ``ENSNameToAddressMiddleware``
+- ``geth_poa_middleware`` -> ``ExtraDataToPOAMiddleware``
+
+The following middleware have been removed:
+
+
+ABI Middleware
+``````````````
+
+``abi_middleware`` is no longer necessary and has been removed. All of the functionality
+of the ``abi_middleware`` was already handled by web3.py's ABI formatters. For additional
+context: a bug in the ENS name-to-address middleware would override the formatters. Fixing
+this bug has removed the need for the ``abi_middleware``.
+
+
+Caching Middleware
+``````````````````
+
+The following middleware have been removed:
+
+- ``simple_cache_middleware``
+- ``latest_block_based_cache_middleware``
+- ``time_based_cache_middleware``
+
+All caching middleware has been removed in favor of a decorator/wrapper around the
+``make_request`` methods of providers with configuration options on the provider class.
+The configuration options are outlined in the documentation in the
+:ref:`request_caching` section.
+
+If desired, the previous caching middleware can be re-created using the new class-based
+middleware model overriding the ``wrap_make_request`` (or ``async_wrap_make_request``)
+method in the middleware class.
+
+
+Result Generating Middleware
+````````````````````````````
+The following middleware have been removed:
+
+- ``fixture_middleware``
+- ``result_generator_middleware``
+
+The ``fixture_middleware`` and ``result_generator_middleware`` which were used for
+testing/mocking purposes have been removed. These have been replaced internally by the
+``RequestMocker`` class, utilized for testing via a ``request_mocker`` pytest fixture.
+
+
+HTTP Retry Request Middleware
+`````````````````````````````
+
+The ``http_retry_request_middleware`` has been removed in favor of a configuration
+option on the ``HTTPProvider`` and ``AsyncHTTPProvider`` classes. The configuration
+options are outlined in the documentation in the :ref:`http_retry_requests` section.
+
+
+Normalize Request Parameters Middleware
+```````````````````````````````````````
+
+The ``normalize_request_parameters`` middleware was not used anywhere internally and
+has been removed.
+
+
+Remaining camelCase -> snake_case Updates
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following arguments have been renamed across the library from camelCase to
+snake_case in all methods where they are passed in as a kwarg.
+
+- ``fromBlock`` -> ``from_block``
+- ``toBlock`` -> ``to_block``
+- ``blockHash`` -> ``block_hash``
+
+Note that if a dictionary is used instead, say to a call such as `eth_getLogs`, the
+keys in the dictionary should be camelCase. This is because the dictionary is passed
+directly to the JSON-RPC request, where the keys are expected to be in camelCase.
+
+
+Changes to Exception Handling
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+All Python standard library exceptions that were raised from within web3.py have
+been replaced with custom ``Web3Exception`` classes. This change allows for better
+control over exception handling, being able to distinguish between exceptions raised
+by web3.py and those raised from elsewhere in a codebase. The following exceptions
+have been replaced:
+
+- ``AssertionError`` -> ``Web3AssertionError``
+- ``ValueError`` -> ``Web3ValueError``
+- ``TypeError`` -> ``Web3TypeError``
+- ``AttributeError`` -> ``Web3AttributeError``
+
+A new ``MethodNotSupported`` exception is now raised when a method is not supported by
+web3.py. This allows a user to distinguish between when a method is not available on
+the current provider, ``MethodUnavailable``, and when a method is not supported by
+web3.py under certain conditions, ``MethodNotSupported``.
+
+A ``MismatchedABI`` exception is now raised instead of a ``Web3ValidationError`` in
+cases where an ABI is not compatible with the data being passed to it. This change
+allows for more specific error handling when using certain ABI types.
+
+
+JSON-RPC Error Handling
+```````````````````````
+
+Rather than a ``ValueError`` being replaced with a ``Web3ValueError`` when a JSON-RPC
+response comes back with an ``error`` object, a new ``Web3RPCError`` exception is
+now raised to provide more distinction for JSON-RPC error responses. Some previously
+existing exceptions now extend from this class since they too are related to JSON-RPC
+errors:
+
+- ``MethodUnavailable``
+- ``BlockNotFound``
+- ``TransactionNotFound``
+- ``TransactionIndexingInProgress``
+
+
+End of Support and Feature Removals
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Python 3.7 Support Dropped
+``````````````````````````
+
+Python 3.7 support has been dropped in favor of Python 3.8+. Python 3.7 is no longer
+supported by the Python core team, and we want to focus our efforts on supporting
+the latest versions of Python.
+
+
+EthPM Module Removed
+````````````````````
+
+The EthPM module has been removed from the library. It was not widely used and has not
+been functional since around October 2022. It was deprecated in ``v6`` and has been
+completely removed in ``v7``.
+
+Types in the
+`eth_typing.ethpm `_
+module have been deprecated and will be removed from ``eth-typing`` in the next major
+release.
+
+
+Geth Miner Namespace Removed
+````````````````````````````
+
+The ``geth.miner`` namespace, deprecated in ``v6``, has been removed in ``v7``.
+The ``miner`` namespace was used for managing the concept of a miner in geth. This is
+no longer a feature in geth and is planned for complete removal in the future, with
+Ethereum having transitioned to proof-of-stake.
+
+
+Geth Personal Namespace Removed
+```````````````````````````````
+
+The ``geth.personal`` namespace, deprecated in ``v6``, has been removed in ``v7``.
+The ``personal`` namespace was used for managing accounts and keys and was deprecated
+in geth in ``v1.11.0``. Geth has moved to using ``clef`` for account and key management.
+
+
+ABI Types Removed
+`````````````````
+
+The type definitions for ABIs, deprecated in ``v6``, have been removed in ``v7``. New
+types have been introduced in the ``eth_typing`` ``v5`` package for ABIs. Improvements have
+been made to make required types more explicit and to offer better semantics.
+
+The following types from ``web3.types`` have been removed:
+- ``ABIEventParams`` is no longer available. Use ``ABIComponentIndexed`` from
+``eth_typing`` to represent event input components.
+- ``ABIEvent`` now resides in ``eth_typing``. ``ABIEvent.type`` and ``ABIEvent.name``
+are now required fields.
+- ``ABIFunctionComponents`` and ``ABIFunctionParams`` are no longer available. Use
+``ABIComponent`` from ``eth_typing`` to represent function input components.
+- ``ABIFunction`` now resides in ``eth_typing``. ``ABIFunction.type`` and
+``ABIFunction.name`` are now required fields.
+- ``ABIElement`` now resides in ``eth_typing`` and represents a ``Union`` of all valid
+ABI element types, ``ABICallable``, ``ABIEvent`` and ``ABIError``.
+
+
+Miscellaneous Changes
+~~~~~~~~~~~~~~~~~~~~~
+
+- ``LRU`` has been removed from the library and dependency on ``lru-dict`` library was
+ dropped.
+- ``CallOverride`` type was changed to ``StateOverride`` since more methods than
+ ``eth_call`` utilize the state override params.
+- ``User-Agent`` header was changed to a more readable format.
+- ``BaseContractFunctions`` iterator now returns instances of ``ContractFunction`` rather
+ than the function names.
+- ``BaseContractFunction`` class attribute ``function_identifier`` has been removed in
+ favor of the ``abi_element_identifier`` attribute.
+- ``web3.contract.utils.call_contract_function()`` no longer uses ``fn_abi`` as a
+ parameter. Instead, the ``abi_callable`` parameter of type ``ABICallable`` is used.
+- Beacon API filename change: ``beacon/main.py`` -> ``beacon/beacon.py``.
+- The asynchronous version of ``w3.eth.wait_for_transaction_receipt()`` changes its
+ signature to use ``Optional[float]`` instead of ``float`` since it may be ``None``.
+- ``get_default_ipc_path()`` and ``get_dev_ipc_path()`` now return the path value
+ without checking if the ``geth.ipc`` file exists.
+- ``Web3.is_address()`` returns ``True`` for non-checksummed addresses.
+- ``Contract.encodeABI()`` has been renamed to ``Contract.encode_abi()``. The ``fn_name``
+ argument has been changed to ``abi_element_identifier``.
+- JSON-RPC responses are now more strictly validated against the JSON-RPC 2.0
+ specification while providing more informative error messages for invalid responses.
+
+
+.. _migrating_v5_to_v6:
+
+Migrating from v5 to v6
+-----------------------
+
+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:
+
+Strict Bytes Checking by Default
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+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``).
+
+
+Snake Case
+~~~~~~~~~~
+
+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 camelCase 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.
+
+
+Python 3.10 and 3.11 Support
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+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+.
+
+Exceptions
+~~~~~~~~~~
+
+Exceptions inherit from a base class
+````````````````````````````````````
+
+In v5, some web3.py exceptions inherited from ``AttributeError``, namely:
+
+- ``NoABIFunctionsFound``
+- ``NoABIFound``
+- ``NoABIEventsFound``
+
+Others inherited from ``ValueError``, namely:
+
+- ``InvalidAddress``
+- ``NameNotFound``
+- ``LogTopicError``
+- ``InvalidEventABI``
+
+Now web3.py exceptions inherit from the same base ``Web3Exception``.
+
+As such, any code that was expecting a ``ValueError`` or an ``AttributeError`` from
+web3.py must update to expecting one of the exceptions listed above, or
+``Web3Exception``.
+
+Similarly, exceptions raised in the EthPM and ENS modules inherit from the base
+``EthPMException`` and ``ENSException``, respectively.
+
+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``.
+
+Web3 class split into Web3 and AsyncWeb3
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The `Web3` class previously contained both sync and async methods. We've separated
+`Web3` and `AsyncWeb3` functionality to tighten up typing. For example:
+
+.. code-block:: python
+
+ from web3 import Web3, AsyncWeb3
+
+ w3 = Web3(Web3.HTTPProvider())
+ async_w3 = AsyncWeb3(AsyncWeb3.AsyncHTTPProvider())
+
+`dict` to `AttributeDict` conversion moved to middleware
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`Eth` module data returned as key-value pairs was previously automatically converted to
+an `AttributeDict` by result formatters, 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.
+
+Other Misc Changes
+~~~~~~~~~~~~~~~~~~
+
+- ``InfuraKeyNotFound`` exception has been changed to ``InfuraProjectIdNotFound``
+- ``SolidityError`` has been removed in favor of ``ContractLogicError``
+- When a method is unavailable from a node provider (i.e. a response error
+ code of -32601 is returned), a ``MethodUnavailable`` error is
+ now raised instead of ``ValueError``
+- Logs' `data` field was previously formatted with `to_ascii_if_bytes`, now formatted to `HexBytes`
+- Receipts' `type` field was previously not formatted, now formatted with `to_integer_if_hex`
+
+Removals
+~~~~~~~~
+
+- Removed unused IBAN module
+- Removed ``WEB3_INFURA_API_KEY`` environment variable in favor of ``WEB3_INFURA_PROJECT_ID``
+- Removed Kovan auto provider
+- Removed deprecated ``sha3`` and ``soliditySha3`` methods in favor of ``keccak`` and ``solidityKeccak``
+- Remove Parity Module and References
+
+
+Other notable changes
+~~~~~~~~~~~~~~~~~~~~~
+
+- The ``ipfshttpclient`` library is now opt-in via a web3 install extra.
+ This only affects the ethpm ipfs backends, which rely on the library.
+
+
+.. _migrating_v4_to_v5:
+
+Migrating from v4 to v5
+-----------------------
+
+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:
+
+Python 3.5 no longer supported
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You will need to upgrade to either Python 3.6 or 3.7
+
+``eth-abi`` v1 no longer supported
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You will need to upgrade the ``eth-abi`` dependency to v2
+
+Changes to base API
+~~~~~~~~~~~~~~~~~~~
+
+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:
+
+- :meth:`~web3.eth.Eth.getTransaction` will throw a ``TransactionNotFound`` error
+- :meth:`~web3.eth.Eth.getTransactionReceipt` will throw a ``TransactionNotFound`` error
+- :meth:`~web3.eth.Eth.getTransactionByBlock` will throw a ``TransactionNotFound`` error
+- :meth:`~web3.eth.Eth.getTransactionCount` will throw a ``BlockNotFound`` error
+- :meth:`~web3.eth.Eth.getBlock` will throw a ``BlockNotFound`` error
+- :meth:`~web3.eth.Eth.getUncleCount` will throw a ``BlockNotFound`` error
+- :meth:`~web3.eth.Eth.getUncleByBlock` will throw a ``BlockNotFound`` error
+
+Removed Methods
+```````````````
+
+- ``contract.buildTransaction`` was removed for ``contract.functions.buildTransaction.``
+- ``contract.deploy`` was removed for ``contract.constructor.transact``
+- ``contract.estimateGas`` was removed for ``contract.functions..estimateGas``
+- ``contract.call`` was removed for ``contract...call``
+- ``contract.transact`` was removed for ``contract...transact``
+- ``contract.eventFilter`` was removed for ``contract.events..createFilter``
+- ``middleware_stack`` was renamed to :meth:`~Web3.middleware_onion`
+- ``web3.miner.hashrate`` was a duplicate of :meth:`~web3.eth.Eth.hashrate` and was removed.
+- ``web3.version.network`` was a duplicate of :meth:`~web3.net.Net.version` and was removed.
+- ``web3.providers.tester.EthereumTesterProvider`` and ``web3.providers.tester.TestRPCProvider`` have been removed for :meth:`~web3.providers.eth_tester.EthereumTesterProvider`
+- ``web3.eth.enableUnauditedFeatures`` was removed
+- ``web3.txpool`` was moved to :meth:`~web3.geth.txpool`
+- ``web3.version.node`` was removed for ``web3.clientVersion``
+- ``web3.version.ethereum`` was removed for :meth:`~web3.eth.Eth.protocolVersion`
+- Relocated personal RPC endpoints to reflect Parity and Geth implementations:
+
+ - ``web3.personal.listAccounts`` was removed for :meth:`~web3.geth.personal.listAccounts` or :meth:`~web3.parity.personal.listAccounts`
+ - ``web3.personal.importRawKey`` was removed for :meth:`~web3.geth.personal.importRawKey` or :meth:`~web3.parity.personal.importRawKey`
+ - ``web3.personal.newAccount`` was removed for :meth:`~web3.geth.personal.newAccount` or :meth:`~web3.parity.personal.newAccount`
+ - ``web3.personal.lockAccount`` was removed for :meth:`~web3.geth.personal.lockAccount`
+ - ``web3.personal.unlockAccount`` was removed for :meth:`~web3.geth.personal.unlockAccount` or :meth:`~web3.parity.personal.unlockAccount`
+ - ``web3.personal.sendTransaction`` was removed for :meth:`~web3.geth.personal.sendTransaction` or :meth:`~web3.parity.personal.sendTransaction`
+
+- Relocated ``web3.admin`` module to ``web3.geth`` namespace
+- Relocated ``web3.miner`` module to ``web3.geth`` namespace
+
+Deprecated Methods
+``````````````````
+
+Expect the following methods to be removed in v6:
+
+- ``web3.sha3`` was deprecated for :meth:`~Web3.keccak`
+- ``web3.soliditySha3`` was deprecated for :meth:`~Web3.solidityKeccak`
+- :meth:`~web3.net.Net.chainId` was deprecated for :meth:`~web3.eth.Eth.chainId`.
+ Follow issue `#1293 `_ for details
+- ``web3.eth.getCompilers()`` was deprecated and will not be replaced
+- :meth:`~web3.eth.getTransactionFromBlock()` was deprecated for :meth:`~Web3.getTransactionByBlock`
+
+Deprecated ConciseContract and ImplicitContract
+```````````````````````````````````````````````
+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..transact({})``
+
+ConciseContract has been replaced with the ContractCaller API. Instead of using the ConciseContract factory, you can now use:
+
+``contract.caller.``
+
+or the classic contract syntax:
+
+``contract.functions..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
+~~~~~~~~~~~~~~~
+
+Web3.py will no longer automatically look up a testnet connection
+in IPCProvider.
+
+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.
+
+Required Infura API Key
+~~~~~~~~~~~~~~~~~~~~~~~
+
+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.
+
+
+Migrating from v3 to v4
+-----------------------
+
+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:
+
+Python 2 to Python 3
+~~~~~~~~~~~~~~~~~~~~
+
+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 :class:`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 cryptographic functions. The following example
+uses :meth:`~Web3.sha3`, but the same pattern applies elsewhere.
+
+In v3 & Python 2, you might have calculated the hash of binary data this way:
+
+.. code-block:: python
+
+ >>> Web3.sha3('I\xe2\x99\xa5SF')
+ '0x50a826df121f4d076a3686d74558f40082a8e70b3469d8e9a16ceb2a79102e5e'
+
+Or, you might have calculated the hash of text data this way:
+
+.. code-block:: python
+
+ >>> Web3.sha3(text=u'I♥SF')
+ '0x50a826df121f4d076a3686d74558f40082a8e70b3469d8e9a16ceb2a79102e5e'
+
+After switching to Python 3, these would instead be executed as:
+
+.. code-block:: python
+
+ >>> Web3.sha3(b'I\xe2\x99\xa5SF')
+ HexBytes('0x50a826df121f4d076a3686d74558f40082a8e70b3469d8e9a16ceb2a79102e5e')
+
+ >>> Web3.sha3(text='I♥SF')
+ HexBytes('0x50a826df121f4d076a3686d74558f40082a8e70b3469d8e9a16ceb2a79102e5e')
+
+Note that the return value is different too: you can treat :class:`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.
+
+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:
+
+.. code-block:: python
+
+ >>> def new_block_callback(block_hash):
+ ... print(f"New Block: {block_hash}")
+ ...
+ >>> new_block_filter = web3.eth.filter('latest')
+ >>> new_block_filter.watch(new_block_callback)
+
+In v4, that same logic:
+
+.. code-block:: python
+
+ >>> new_block_filter = web3.eth.filter('latest')
+ >>> for block_hash in new_block_filter.get_new_entries():
+ ... print(f"New Block: {block_hash}")
+
+The caller is responsible for polling the results from ``get_new_entries()``.
+See :ref:`asynchronous_filters` for examples of filter-event handling with web3 v4.
+
+TestRPCProvider and EthereumTesterProvider
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+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 :class:`EthereumTesterProvider`, and the old v3 implementation has been
+removed. Web3.py v4 uses :class:`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:
+
+.. code-block:: bash
+
+ $ pip install web3[tester]
+
+
+Changes to base API convenience methods
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Web3.toDecimal()
+````````````````
+
+In v4 ``Web3.toDecimal()`` is renamed: :meth:`~Web3.toInt` for improved clarity. It does not return a :class:`decimal.Decimal`, it returns an :class:`int`.
+
+
+Removed Methods
+```````````````
+
+- ``Web3.toUtf8`` was removed for :meth:`~Web3.toText`.
+- ``Web3.fromUtf8`` was removed for :meth:`~Web3.toHex`.
+- ``Web3.toAscii`` was removed for :meth:`~Web3.toBytes`.
+- ``Web3.fromAscii`` was removed for :meth:`~Web3.toHex`.
+- ``Web3.fromDecimal`` was removed for :meth:`~Web3.toHex`.
+
+Provider Access
+~~~~~~~~~~~~~~~~~
+
+In v4, ``w3.currentProvider`` was removed, in favor of ``w3.providers``.
+
+Disambiguating String Inputs
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+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 :class:`str` you have by using the appropriate
+keyword argument. See examples in :ref:`overview_type_conversions`.
+
+In v3, some methods accepted a :class:`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:
+
+- :meth:`~Web3.sha3`
+- :meth:`~Web3.toBytes`
+
+Contracts
+~~~~~~~~~
+
+- When a contract returns the ABI type ``string``, Web3.py v4 now returns a :class:`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 :class:`bytes` value
+
+Personal API
+~~~~~~~~~~~~
+
+``w3.personal.signAndSendTransaction`` is no longer available. Use
+:meth:`w3.personal.sendTransaction() ` instead.
diff --git a/_build/html_zh_CN/_sources/overview.rst.txt b/_build/html_zh_CN/_sources/overview.rst.txt
new file mode 100644
index 0000000000..31a20e4844
--- /dev/null
+++ b/_build/html_zh_CN/_sources/overview.rst.txt
@@ -0,0 +1,317 @@
+.. _overview:
+
+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.
+
+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
+~~~~~~~~~
+
+:doc:`providers` are how web3.py connects to a blockchain. The library comes with the
+following built-in providers:
+
+- :class:`~web3.providers.rpc.HTTPProvider` for connecting to http and https based JSON-RPC servers.
+- :class:`~web3.providers.ipc.IPCProvider` for connecting to ipc socket based JSON-RPC servers.
+- :class:`~web3.providers.legacy_websocket.LegacyWebSocketProvider` (deprecated) for connecting to websocket based JSON-RPC servers.
+- :class:`~web3.providers.async_rpc.AsyncHTTPProvider` for connecting to http and https based JSON-RPC servers asynchronously.
+- :class:`~web3.providers.persistent.AsyncIPCProvider` for connecting to ipc socket based JSON-RPC servers asynchronously via a persistent connection.
+- :class:`~web3.providers.persistent.WebSocketProvider` for connecting to websocket based JSON-RPC servers asynchronously via a persistent connection.
+
+Examples
+````````
+
+.. code-block:: python
+
+ >>> from web3 import Web3, AsyncWeb3
+
+ # IPCProvider:
+ >>> w3 = Web3(Web3.IPCProvider('./path/to/filename.ipc'))
+ >>> w3.is_connected()
+ True
+
+ # HTTPProvider:
+ >>> w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
+ >>> w3.is_connected()
+ True
+
+ # AsyncHTTPProvider:
+ >>> w3 = AsyncWeb3(AsyncWeb3.AsyncHTTPProvider('http://127.0.0.1:8545'))
+ >>> await w3.is_connected()
+ True
+
+ # -- Persistent Connection Providers -- #
+
+ # WebSocketProvider:
+ >>> w3 = await AsyncWeb3(AsyncWeb3.WebSocketProvider('ws://127.0.0.1:8546'))
+ >>> await w3.is_connected()
+ True
+
+ # AsyncIPCProvider
+ >>> w3 = await AsyncWeb3(AsyncWeb3.AsyncIPCProvider('./path/to/filename.ipc'))
+ >>> await w3.is_connected()
+ True
+
+
+For more context, see the :doc:`providers` documentation.
+
+
+Middleware
+~~~~~~~~~~
+
+Your web3.py instance may be further configured via :doc:`middleware`.
+
+web3.py middleware is described using an onion metaphor, where each layer of
+middleware may affect both the incoming request and outgoing response from your
+provider. The documentation includes a :ref:`visualization `
+of this idea.
+
+Several middleware are :ref:`included by default `. You may add to
+(:meth:`add `, :meth:`inject `,
+:meth:`replace `) or disable
+(:meth:`remove `,
+:meth:`clear `) any of these middleware.
+
+
+Accounts and Private Keys
+-------------------------
+
+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 :attr:`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 :ref:`here `.
+The separate guide to :doc:`transactions` may also help clarify how to manage keys.
+
+
+Base API
+--------
+
+The :ref:`Web3 ` class includes a number of convenient utility functions:
+
+
+Encoding and Decoding Helpers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- :meth:`Web3.is_encodable() `
+- :meth:`Web3.to_bytes() `
+- :meth:`Web3.to_hex() `
+- :meth:`Web3.to_int() `
+- :meth:`Web3.to_json() `
+- :meth:`Web3.to_text() `
+
+
+Address Helpers
+~~~~~~~~~~~~~~~
+
+- :meth:`Web3.is_address() `
+- :meth:`Web3.is_checksum_address() `
+- :meth:`Web3.to_checksum_address() `
+
+
+Currency Conversions
+~~~~~~~~~~~~~~~~~~~~
+
+- :meth:`Web3.from_wei() `
+- :meth:`Web3.to_wei() `
+
+
+Cryptographic Hashing
+~~~~~~~~~~~~~~~~~~~~~
+
+- :meth:`Web3.keccak() `
+- :meth:`Web3.solidity_keccak() `
+
+
+web3.eth API
+------------
+
+The most commonly used APIs for interacting with Ethereum can be found under the
+:ref:`web3-eth` namespace.
+
+
+Fetching Data
+~~~~~~~~~~~~~
+
+Viewing account balances (:meth:`get_balance `), transactions
+(:meth:`get_transaction `), and block data
+(:meth:`get_block `) are some of the most common starting
+points in web3.py.
+
+
+API
+```
+
+- :meth:`web3.eth.get_balance() `
+- :meth:`web3.eth.get_block() `
+- :meth:`web3.eth.get_block_transaction_count() `
+- :meth:`web3.eth.get_code() `
+- :meth:`web3.eth.get_proof() `
+- :meth:`web3.eth.get_storage_at() `
+- :meth:`web3.eth.get_transaction() `
+- :meth:`web3.eth.get_transaction_by_block() `
+- :meth:`web3.eth.get_transaction_count() `
+- :meth:`web3.eth.get_uncle_by_block() `
+- :meth:`web3.eth.get_uncle_count() `
+
+
+Sending Transactions
+~~~~~~~~~~~~~~~~~~~~
+
+The most common use cases will be satisfied with
+:meth:`send_transaction ` or the combination of
+:meth:`sign_transaction ` and
+:meth:`send_raw_transaction `. For more context,
+see the full guide to :doc:`transactions`.
+
+.. note::
+
+ If interacting with a smart contract, a dedicated API exists. See the next
+ section, :ref:`Contracts `.
+
+
+API
+```
+
+- :meth:`web3.eth.send_transaction() `
+- :meth:`web3.eth.sign_transaction() `
+- :meth:`web3.eth.send_raw_transaction() `
+- :meth:`web3.eth.replace_transaction() `
+- :meth:`web3.eth.modify_transaction() `
+- :meth:`web3.eth.wait_for_transaction_receipt() `
+- :meth:`web3.eth.get_transaction_receipt() `
+- :meth:`web3.eth.sign() `
+- :meth:`web3.eth.sign_typed_data() `
+- :meth:`web3.eth.estimate_gas() `
+- :meth:`web3.eth.generate_gas_price() `
+- :meth:`web3.eth.set_gas_price_strategy() `
+
+
+.. _overview_contracts:
+
+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
+:meth:`constructor ` method will deploy an
+instance of the contract:
+
+.. code-block:: python
+
+ >>> ExampleContract = w3.eth.contract(abi=abi, bytecode=bytecode)
+ >>> tx_hash = ExampleContract.constructor().transact()
+ >>> tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
+ >>> tx_receipt.contractAddress
+ '0x8a22225eD7eD460D7ee3842bce2402B9deaD23D3'
+
+Once a deployed contract is loaded into a Contract object, the functions of that
+contract are available on the ``functions`` namespace:
+
+.. code-block:: python
+
+ >>> deployed_contract = w3.eth.contract(address=tx_receipt.contractAddress, abi=abi)
+ >>> deployed_contract.functions.myFunction(42).transact()
+
+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
+:meth:`ContractFunction.call ` method, or the
+more concise :attr:`ContractCaller ` syntax:
+
+.. code-block:: python
+
+ # Using ContractFunction.call
+ >>> deployed_contract.functions.getMyValue().call()
+ 42
+
+ # Using ContractCaller
+ >>> deployed_contract.caller().getMyValue()
+ 42
+
+For more, see the full :ref:`Contracts` documentation.
+
+
+API
+~~~
+
+- :meth:`web3.eth.contract() `
+- :attr:`Contract.address `
+- :attr:`Contract.abi `
+- :attr:`Contract.bytecode `
+- :attr:`Contract.bytecode_runtime `
+- :attr:`Contract.functions `
+- :attr:`Contract.events `
+- :attr:`Contract.fallback `
+- :meth:`Contract.constructor() `
+- :meth:`Contract.encode_abi() `
+- :attr:`web3.contract.ContractFunction `
+- :attr:`web3.contract.ContractEvents `
+
+
+Events, Logs, and Filters
+-------------------------
+
+If you want to react to new blocks being mined or specific events being emitted by
+a contract, you can leverage ``get_logs``, subscriptions, or filters.
+
+See the :doc:`filters` guide for more information.
+
+
+API
+~~~
+
+- :meth:`web3.eth.subscribe() `
+- :meth:`web3.eth.filter() `
+- :meth:`web3.eth.get_filter_changes() `
+- :meth:`web3.eth.get_filter_logs() `
+- :meth:`web3.eth.uninstall_filter() `
+- :meth:`web3.eth.get_logs() `
+- :meth:`Contract.events.your_event_name.create_filter() `
+- :meth:`Contract.events.your_event_name.build_filter() `
+- :meth:`Filter.get_new_entries() `
+- :meth:`Filter.get_all_entries() `
+- :meth:`Filter.format_entry() `
+- :meth:`Filter.is_valid_entry() `
+
+
+Net API
+-------
+
+Some basic network properties are available on the ``web3.net`` object:
+
+- :attr:`web3.net.listening`
+- :attr:`web3.net.peer_count`
+- :attr:`web3.net.version`
+
+
+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
+:ref:`here `.
diff --git a/_build/html_zh_CN/_sources/providers.rst.txt b/_build/html_zh_CN/_sources/providers.rst.txt
new file mode 100644
index 0000000000..21e9c490c3
--- /dev/null
+++ b/_build/html_zh_CN/_sources/providers.rst.txt
@@ -0,0 +1,606 @@
+.. _providers:
+
+Providers
+=========
+
+Using Ethereum requires access to an Ethereum node. If you have the means, you're
+encouraged to `run your own node`_. (Note that you do not need to stake ether to
+run a node.) If you're unable to run your own node, you can use a `remote node`_.
+
+Once you have access to a node, you can connect to it using a **provider**.
+Providers generate `JSON-RPC`_ requests and return the response. This is done by submitting
+the request to an HTTP, WebSocket, 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 this providers section.
+
+.. _run your own node: https://ethereum.org/en/developers/docs/nodes-and-clients/run-a-node/
+.. _remote node: https://ethereum.org/en/developers/docs/nodes-and-clients/nodes-as-a-service/
+.. _JSON-RPC: https://ethereum.org/en/developers/docs/apis/json-rpc/
+
+.. _choosing_provider:
+
+Choosing a Provider
+-------------------
+
+Most nodes have a variety of ways to connect to them. Most commonly:
+
+1. IPC (uses local filesystem: fastest and most secure)
+2. WebSocket (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 WebSocket.
+- If your node does not support WebSocket, use HTTP.
+
+Once you have decided how to connect, you'll select and configure the appropriate provider
+class:
+
+- :class:`~web3.providers.rpc.HTTPProvider`
+- :class:`~web3.providers.ipc.IPCProvider`
+- :class:`~web3.providers.async_rpc.AsyncHTTPProvider`
+- :class:`~web3.providers.persistent.AsyncIPCProvider` (Persistent Connection Provider)
+- :class:`~web3.providers.persistent.WebSocketProvider` (Persistent Connection Provider)
+
+Each provider above links to the documentation on how to properly initialize that
+provider. Once you have reviewed the relevant documentation for the provider of your
+choice, you are ready to :ref:`get started with web3.py`.
+
+Provider via Environment Variable
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+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``
+
+
+Auto-initialization Provider Shortcuts
+--------------------------------------
+
+Geth dev Proof of Authority
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To connect to a ``geth --dev`` Proof of Authority instance with
+the POA middleware loaded by default:
+
+.. code-block:: python
+
+ >>> from web3.auto.gethdev import w3
+
+ # confirm that the connection succeeded
+ >>> w3.is_connected()
+ True
+
+Or, connect to an async web3 instance:
+
+.. code-block:: python
+
+ >>> from web3.auto.gethdev import async_w3
+ >>> await async_w3.provider.connect()
+
+ # confirm that the connection succeeded
+ >>> await async_w3.is_connected()
+ True
+
+
+Built In Providers
+------------------
+
+Web3 ships with the following providers which are appropriate for connecting to
+local and remote JSON-RPC servers.
+
+
+HTTPProvider
+~~~~~~~~~~~~
+
+.. py:class:: web3.providers.rpc.HTTPProvider(endpoint_uri, request_kwargs={}, session=None, exception_retry_configuration=ExceptionRetryConfiguration())
+
+ This provider handles interactions with an HTTP or HTTPS based JSON-RPC server.
+
+ * ``endpoint_uri`` should be the full URI to the RPC endpoint such as
+ ``'https://localhost:8545'``. For RPC servers behind HTTP connections
+ running on port 80 and HTTPS connections running on port 443 the port can
+ be omitted from the URI.
+ * ``request_kwargs`` should be a dictionary of keyword arguments which
+ will be passed onto each http/https POST request made to your node.
+ * ``session`` allows you to pass a ``requests.Session`` object initialized
+ as desired.
+ * ``exception_retry_configuration`` is an instance of the
+ :class:`~web3.providers.rpc.utils.ExceptionRetryConfiguration`
+ class which allows you to configure how the provider should handle exceptions
+ when making certain requests. Setting this to ``None`` will disable
+ exception retries.
+
+ .. code-block:: python
+
+ >>> from web3 import Web3
+ >>> w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:8545"))
+
+ 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 HTTPProviders 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.
+
+
+ .. code-block:: python
+
+ >>> from web3 import Web3
+ >>> w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:8545", request_kwargs={'timeout': 60}))
+
+
+ To tune the connection pool size, you can pass your own ``requests.Session``.
+
+ .. code-block:: python
+
+ >>> from web3 import Web3
+ >>> adapter = requests.adapters.HTTPAdapter(pool_connections=20, pool_maxsize=20)
+ >>> session = requests.Session()
+ >>> session.mount('http://', adapter)
+ >>> session.mount('https://', adapter)
+ >>> w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:8545", session=session))
+
+
+IPCProvider
+~~~~~~~~~~~
+
+.. py:class:: web3.providers.ipc.IPCProvider(ipc_path=None, timeout=10)
+
+ This provider handles interaction with an IPC Socket based JSON-RPC
+ server.
+
+ * ``ipc_path`` is the filesystem path to the IPC socket:
+
+ .. code-block:: python
+
+ >>> from web3 import Web3
+ >>> w3 = Web3(Web3.IPCProvider("~/Library/Ethereum/geth.ipc"))
+
+ If no ``ipc_path`` is specified, it will use a default depending on your operating
+ system.
+
+ - On Linux and FreeBSD: ``~/.ethereum/geth.ipc``
+ - On Mac OS: ``~/Library/Ethereum/geth.ipc``
+ - On Windows: ``\\.\pipe\geth.ipc``
+
+
+AsyncHTTPProvider
+~~~~~~~~~~~~~~~~~
+
+.. py:class:: web3.providers.rpc.AsyncHTTPProvider(endpoint_uri, request_kwargs={}, exception_retry_configuration=ExceptionRetryConfiguration())
+
+ This provider handles interactions with an HTTP or HTTPS based JSON-RPC server asynchronously.
+
+ * ``endpoint_uri`` should be the full URI to the RPC endpoint such as
+ ``'https://localhost:8545'``. For RPC servers behind HTTP connections
+ running on port 80 and HTTPS connections running on port 443 the port can
+ be omitted from the URI.
+ * ``request_kwargs`` should be a dictionary of keyword arguments which
+ will be passed onto each http/https POST request made to your node.
+ * ``exception_retry_configuration`` is an instance of the
+ :class:`~web3.providers.rpc.utils.ExceptionRetryConfiguration`
+ class which allows you to configure how the provider should handle exceptions
+ when making certain requests. Setting this to ``None`` will disable
+ exception retries.
+
+ The ``cache_async_session()`` method allows you to use your own
+ ``aiohttp.ClientSession`` object.
+
+ .. code-block:: python
+
+ >>> from aiohttp import ClientSession
+ >>> from web3 import AsyncWeb3, AsyncHTTPProvider
+
+ >>> w3 = AsyncWeb3(AsyncHTTPProvider(endpoint_uri))
+
+ >>> # If you want to pass in your own session:
+ >>> custom_session = ClientSession()
+ >>> await w3.provider.cache_async_session(custom_session) # This method is an async method so it needs to be handled accordingly
+ >>> # when you're finished, disconnect:
+ >>> w3.provider.disconnect()
+
+ Under the hood, the ``AsyncHTTPProvider`` uses the python
+ `aiohttp `_ library for making requests.
+
+Persistent Connection Providers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Persistent Connection Base Class
+++++++++++++++++++++++++++++++++
+
+.. note::
+ This class is not meant to be used directly. If your provider class inherits
+ from this class, look to these docs for additional configuration options.
+
+.. py:class:: web3.providers.persistent.PersistentConnectionProvider(\
+ request_timeout: float = 50.0, \
+ subscription_response_queue_size: int = 500, \
+ silence_listener_task_exceptions: bool = False \
+ max_connection_retries: int = 5, \
+ request_information_cache_size: int = 500, \
+ )
+
+ This is a base provider class, inherited by the following providers:
+
+ - :class:`~web3.providers.persistent.WebSocketProvider`
+ - :class:`~web3.providers.persistent.AsyncIPCProvider`
+
+ It handles interactions with a persistent connection to a JSON-RPC server. Among
+ its configuration, it houses all of the
+ :class:`~web3.providers.persistent.request_processor.RequestProcessor` logic for
+ handling the asynchronous sending and receiving of requests and responses. See
+ the :ref:`internals__persistent_connection_providers` section for more details on
+ the internals of persistent connection providers.
+
+ * ``request_timeout`` is the timeout in seconds, used when sending data over the
+ connection and waiting for a response to be received from the listener task.
+ Defaults to ``50.0``.
+
+ * ``subscription_response_queue_size`` is the size of the queue used to store
+ subscription responses, defaults to ``500``. While messages are being consumed,
+ this queue should never fill up as it is a transient queue and meant to handle
+ asynchronous receiving and processing of responses. When in sync with the
+ socket stream, this queue should only ever store 1 to a few messages at a time.
+
+ * ``silence_listener_task_exceptions`` is a boolean that determines whether
+ exceptions raised by the listener task are silenced. Defaults to ``False``,
+ raising any exceptions that occur in the listener task.
+
+ * ``max_connection_retries`` is the maximum number of times to retry a connection
+ to the provider when initializing the provider. Defaults to ``5``.
+
+ * ``request_information_cache_size`` specifies the size of the transient cache for
+ storing request details, enabling the provider to process responses based on the
+ original request information. Defaults to ``500``.
+
+AsyncIPCProvider
+++++++++++++++++
+
+.. py:class:: web3.providers.persistent.AsyncIPCProvider(ipc_path=None, max_connection_retries=5)
+
+ This provider handles asynchronous, persistent interaction with an IPC Socket based
+ JSON-RPC server.
+
+ * ``ipc_path`` is the filesystem path to the IPC socket:
+ * ``read_buffer_limit`` is the maximum size of data, in bytes, that can be read
+ from the socket at one time. Defaults to 20MB (20 * 1024 * 1024). Raises
+ ``ReadBufferLimitReached`` if the limit is reached, suggesting that the buffer
+ limit be increased.
+
+ This provider inherits from the
+ :class:`~web3.providers.persistent.PersistentConnectionProvider` class. Refer to
+ the :class:`~web3.providers.persistent.PersistentConnectionProvider` documentation
+ for details on additional configuration options available for this provider.
+
+ If no ``ipc_path`` is specified, it will use a default depending on your operating
+ system.
+
+ - On Linux and FreeBSD: ``~/.ethereum/geth.ipc``
+ - On Mac OS: ``~/Library/Ethereum/geth.ipc``
+ - On Windows: ``\\.\pipe\geth.ipc``
+
+WebSocketProvider
++++++++++++++++++
+
+.. py:class:: web3.providers.persistent.WebSocketProvider(endpoint_uri: str, websocket_kwargs: Dict[str, Any] = {}, use_text_frames: bool = False)
+
+ This provider handles interactions with an WS or WSS based JSON-RPC server.
+
+ * ``endpoint_uri`` should be the full URI to the RPC endpoint such as
+ ``'ws://localhost:8546'``.
+ * ``websocket_kwargs`` this should be a dictionary of keyword arguments which
+ will be passed onto the ws/wss websocket connection.
+ * ``use_text_frames`` will ensure websocket data is sent as text frames
+ for servers that do not support binary communication.
+
+ This provider inherits from the
+ :class:`~web3.providers.persistent.PersistentConnectionProvider` class. Refer to
+ the :class:`~web3.providers.persistent.PersistentConnectionProvider` documentation
+ for details on additional configuration options available for this provider.
+
+ 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 documentation`_ for
+ available arguments.
+
+
+.. _subscription-examples:
+
+Using Persistent Connection Providers
++++++++++++++++++++++++++++++++++++++
+
+The ``AsyncWeb3`` class may be used as a context manager, utilizing the ``async with``
+syntax, when instantiating with a
+:class:`~web3.providers.persistent.PersistentConnectionProvider`. This will
+automatically close the connection when the context manager exits and is the
+recommended way to initiate a persistent connection to the provider.
+
+A similar example using a ``websockets`` connection as an asynchronous context manager
+can be found in the `websockets connection`_ docs.
+
+.. code-block:: python
+
+ >>> import asyncio
+ >>> from web3 import AsyncWeb3
+ >>> from web3.providers.persistent import (
+ ... AsyncIPCProvider,
+ ... WebSocketProvider,
+ ... )
+
+ >>> LOG = True # toggle debug logging
+ >>> if LOG:
+ ... import logging
+ ... # logger = logging.getLogger("web3.providers.AsyncIPCProvider") # for the AsyncIPCProvider
+ ... logger = logging.getLogger("web3.providers.WebSocketProvider") # for the WebSocketProvider
+ ... logger.setLevel(logging.DEBUG)
+ ... logger.addHandler(logging.StreamHandler())
+
+ >>> async def context_manager_subscription_example():
+ ... # async with AsyncWeb3(AsyncIPCProvider("./path/to.filename.ipc") as w3: # for the AsyncIPCProvider
+ ... async with AsyncWeb3(WebSocketProvider(f"ws://127.0.0.1:8546")) as w3: # for the WebSocketProvider
+ ... # subscribe to new block headers
+ ... subscription_id = await w3.eth.subscribe("newHeads")
+ ...
+ ... async for response in w3.socket.process_subscriptions():
+ ... print(f"{response}\n")
+ ... # handle responses here
+ ...
+ ... if some_condition:
+ ... # unsubscribe from new block headers and break out of
+ ... # iterator
+ ... await w3.eth.unsubscribe(subscription_id)
+ ... break
+ ...
+ ... # still an open connection, make any other requests and get
+ ... # responses via send / receive
+ ... latest_block = await w3.eth.get_block("latest")
+ ... print(f"Latest block: {latest_block}")
+ ...
+ ... # the connection closes automatically when exiting the context
+ ... # manager (the `async with` block)
+
+ >>> asyncio.run(context_manager_subscription_example())
+
+
+The ``AsyncWeb3`` class may also be used as an asynchronous iterator, utilizing the
+``async for`` syntax, when instantiating with a
+:class:`~web3.providers.persistent.PersistentConnectionProvider`. This may be used to
+set up an indefinite websocket connection and reconnect automatically if the connection
+is lost.
+
+A similar example using a ``websockets`` connection as an asynchronous iterator can
+be found in the `websockets connection`_ docs.
+
+.. _`websockets connection`: https://websockets.readthedocs.io/en/stable/reference/asyncio/client.html#websockets.client.connect
+
+.. code-block:: python
+
+ >>> import asyncio
+ >>> import websockets
+ >>> from web3 import AsyncWeb3
+ >>> from web3.providers.persistent import (
+ ... AsyncIPCProvider,
+ ... WebSocketProvider,
+ ... )
+
+ >>> async def subscription_iterator_example():
+ ... # async for w3 in AsyncWeb3(AsyncIPCProvider("./path/to/filename.ipc")): # for the AsyncIPCProvider
+ ... async for w3 in AsyncWeb3(WebSocketProvider(f"ws://127.0.0.1:8546")): # for the WebSocketProvider
+ ... try:
+ ... ...
+ ... except websockets.ConnectionClosed:
+ ... continue
+
+ # run the example
+ >>> asyncio.run(subscription_iterator_example())
+
+
+Awaiting the instantiation with a
+:class:`~web3.providers.persistent.PersistentConnectionProvider`, or instantiating
+and awaiting the ``connect()`` method is also possible. Both of these examples are
+shown below.
+
+.. code-block:: python
+
+ >>> async def await_instantiation_example():
+ ... # w3 = await AsyncWeb3(AsyncIPCProvider("./path/to/filename.ipc")) # for the AsyncIPCProvider
+ ... w3 = await AsyncWeb3(WebSocketProvider(f"ws://127.0.0.1:8546")) # for the WebSocketProvider
+ ...
+ ... # some code here
+ ...
+ ... # manual cleanup
+ ... await w3.provider.disconnect()
+
+ # run the example
+ >>> asyncio.run(await_instantiation_example())
+
+.. code-block:: python
+
+ >>> async def await_provider_connect_example():
+ ... # w3 = AsyncWeb3(AsyncIPCProvider("./path/to/filename.ipc")) # for the AsyncIPCProvider
+ ... w3 = AsyncWeb3(WebSocketProvider(f"ws://127.0.0.1:8546")) # for the WebSocketProvider
+ ... await w3.provider.connect()
+ ...
+ ... # some code here
+ ...
+ ... # manual cleanup
+ ... await w3.provider.disconnect()
+
+ # run the example
+ >>> asyncio.run(await_provider_connect_example())
+
+:class:`~web3.providers.persistent.PersistentConnectionProvider` classes use the
+:class:`~web3.providers.persistent.request_processor.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
+:class:`~web3.providers.persistent.request_processor.RequestProcessor`
+documentation for details.
+
+AsyncWeb3 with Persistent Connection Providers
+++++++++++++++++++++++++++++++++++++++++++++++
+
+When an ``AsyncWeb3`` class is connected to a
+:class:`~web3.providers.persistent.PersistentConnectionProvider`, some attributes and
+methods become available.
+
+ .. py:attribute:: socket
+
+ The public API for interacting with the websocket connection is available via
+ the ``socket`` attribute of the ``Asyncweb3`` class. This attribute is an
+ instance of the
+ :class:`~web3.providers.persistent.persistent_connection.PersistentConnection`
+ class and is the main interface for interacting with the socket connection.
+
+
+Interacting with the Persistent Connection
+++++++++++++++++++++++++++++++++++++++++++
+
+.. py:class:: web3.providers.persistent.persistent_connection.PersistentConnection
+
+ This class handles interactions with a persistent socket connection. It is available
+ via the ``socket`` attribute on the ``AsyncWeb3`` class. The
+ ``PersistentConnection`` class has the following methods and attributes:
+
+ .. py:attribute:: subscriptions
+
+ This attribute returns the current active subscriptions as a dict mapping
+ the subscription ``id`` to a dict of metadata about the subscription
+ request.
+
+ .. py:method:: 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 middleware that were present at the time of subscription.
+ Examples on how to use this method can be seen above in the
+ `Using Persistent Connection Providers`_ section.
+
+ .. py:method:: send(method: RPCEndpoint, params: Sequence[Any])
+
+ This method is available strictly for sending raw requests to the socket,
+ 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
+ middleware. Instead, use the methods available on the respective web3
+ module. For example, use ``w3.eth.get_block("latest")`` instead of
+ ``w3.socket.send("eth_getBlockByNumber", ["latest", True])``.
+
+ .. py:method:: recv()
+
+ The ``recv()`` method can be used to receive the next response for a request
+ from the socket. The response from this method is the raw response. This is not
+ the recommended way to receive a response for a request, as it is not formatted
+ by *web3.py* formatters or run through the middleware. Instead, use the methods
+ available on the respective web3 module
+ (e.g. ``block_num = await w3.eth.block_number``) for retrieving responses for
+ one-to-one request-to-response calls.
+
+ .. py:method:: make_request(method: RPCEndpoint, params: Sequence[Any])
+
+ This method is available for making requests to the socket and retrieving the
+ response. It is not recommended to use this method directly, as the responses
+ will not be properly formatted by *web3.py* formatters or run through the
+ middleware. Instead, use the methods available on the respective web3 module.
+ For example, use ``w3.eth.get_block("latest")`` instead of
+ ``w3.socket.make_request("eth_getBlockByNumber", ["latest", True])``.
+
+
+LegacyWebSocketProvider
+~~~~~~~~~~~~~~~~~~~~~~~
+
+.. warning::
+
+ ``LegacyWebSocketProvider`` is deprecated and is likely to be removed in a
+ future major release. Please use ``WebSocketProvider`` instead.
+
+.. py:class:: web3.providers.legacy_websocket.LegacyWebSocketProvider(endpoint_uri[, websocket_timeout, websocket_kwargs])
+
+ This provider handles interactions with an WS or WSS based JSON-RPC server.
+
+ * ``endpoint_uri`` should be the full URI to the RPC endpoint such as
+ ``'ws://localhost:8546'``.
+ * ``websocket_timeout`` is the timeout in seconds, used when receiving or
+ sending data over the connection. Defaults to 10.
+ * ``websocket_kwargs`` this should be a dictionary of keyword arguments which
+ will be passed onto the ws/wss websocket connection.
+
+ .. code-block:: python
+
+ >>> from web3 import Web3
+ >>> w3 = Web3(Web3.LegacyWebSocketProvider("ws://127.0.0.1:8546"))
+
+ Under the hood, ``LegacyWebSocketProvider`` 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 documentation`_ for
+ available arguments.
+
+ .. _`websockets documentation`: https://websockets.readthedocs.io/en/stable/reference/asyncio/client.html#websockets.client.WebSocketClientProtocol
+
+ Unlike HTTP connections, the timeout for WS connections is controlled by a
+ separate ``websocket_timeout`` argument, as shown below.
+
+
+ .. code-block:: python
+
+ >>> from web3 import Web3
+ >>> w3 = Web3(Web3.LegacyWebSocketProvider("ws://127.0.0.1:8546", websocket_timeout=60))
+
+
+AutoProvider
+~~~~~~~~~~~~
+
+:class:`~web3.providers.auto.AutoProvider` is the default used when initializing
+:class:`web3.Web3` without any providers. There's rarely a reason to use it
+explicitly.
+
+.. py:currentmodule:: web3.providers.eth_tester
+
+EthereumTesterProvider
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. warning:: Experimental: This provider is experimental. There are still significant
+ gaps in functionality. However it is being actively developed and supported.
+
+.. py:class:: EthereumTesterProvider(ethereum_tester=None, api_endpoints=None)
+.. py:class:: AsyncEthereumTesterProvider(ethereum_tester=None, api_endpoints=None)
+
+ This provider integrates with the ``eth-tester`` library. The ``ethereum_tester``
+ constructor argument should be an instance of the :class:`~eth_tester.EthereumTester`
+ or a subclass of :class:`~eth_tester.backends.base.BaseChainBackend` class provided
+ by the ``eth-tester`` library. The ``api_endpoints`` argument should be a ``dict``
+ of RPC endpoints. You can see the structure and defaults `here `_.
+ If you would like a custom ``eth-tester`` instance to test with, see the
+ ``eth-tester`` library `documentation `_
+ for details.
+
+ .. code-block:: python
+
+ >>> from web3 import Web3, EthereumTesterProvider
+ >>> w3 = Web3(EthereumTesterProvider())
+
+.. 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: e.g. ``pip install "web3[tester]"``
diff --git a/_build/html_zh_CN/_sources/quickstart.rst.txt b/_build/html_zh_CN/_sources/quickstart.rst.txt
new file mode 100644
index 0000000000..5f7c68daaa
--- /dev/null
+++ b/_build/html_zh_CN/_sources/quickstart.rst.txt
@@ -0,0 +1,163 @@
+.. _quickstart:
+
+Quickstart
+==========
+
+.. contents:: :local:
+
+.. 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 `_.
+
+Installation
+------------
+
+web3.py can be installed (preferably in a :ref:`virtualenv `)
+using ``pip`` as follows:
+
+.. code-block:: shell
+
+ $ pip install web3
+
+
+.. NOTE:: If you run into problems during installation, you might have a
+ broken environment. See the troubleshooting guide to :ref:`setting up a
+ clean environment `.
+
+
+Using Web3
+----------
+
+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 :ref:`Providers` documentation. This Quickstart guide will highlight
+a couple of the most common use cases.
+
+
+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.
+
+.. code-block:: python
+
+ >>> from web3 import Web3, EthereumTesterProvider
+ >>> w3 = Web3(EthereumTesterProvider())
+ >>> w3.is_connected()
+ True
+
+
+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:
+
+.. code-block:: python
+
+ >>> from web3 import Web3, AsyncWeb3
+
+ # IPCProvider:
+ >>> w3 = Web3(Web3.IPCProvider('./path/to/filename.ipc'))
+ >>> w3.is_connected()
+ True
+
+ # HTTPProvider:
+ >>> w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
+ >>> w3.is_connected()
+ True
+
+ # AsyncHTTPProvider:
+ >>> w3 = AsyncWeb3(AsyncWeb3.AsyncHTTPProvider('http://127.0.0.1:8545'))
+ >>> await w3.is_connected()
+ True
+
+ # -- Persistent Connection Providers -- #
+
+ # WebSocketProvider:
+ >>> w3 = await AsyncWeb3(AsyncWeb3.WebSocketProvider('ws://127.0.0.1:8546'))
+ >>> await w3.is_connected()
+ True
+
+ # AsyncIPCProvider:
+ >>> w3 = await AsyncWeb3(AsyncWeb3.AsyncIPCProvider('./path/to/filename.ipc'))
+ >>> await w3.is_connected()
+ True
+
+
+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:
+
+.. code-block:: python
+
+ >>> from web3 import Web3, AsyncWeb3
+
+ >>> w3 = Web3(Web3.HTTPProvider('https://'))
+
+ >>> w3 = AsyncWeb3(AsyncWeb3.AsyncHTTPProvider('https://'))
+
+ >>> w3 = await AsyncWeb3(AsyncWeb3.WebSocketProvider('wss://'))
+
+This endpoint is provided by the remote node service, typically after you create an account.
+
+.. _first_w3_use:
+
+
+Getting Blockchain Info
+-----------------------
+
+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:
+
+.. code-block:: python
+
+ >>> w3.eth.get_block('latest')
+ {'difficulty': 1,
+ 'gasLimit': 6283185,
+ 'gasUsed': 0,
+ 'hash': HexBytes('0x53b983fe73e16f6ed8178f6c0e0b91f23dc9dad4cb30d0831f178291ffeb8750'),
+ 'logsBloom': HexBytes('0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'),
+ 'miner': '0x0000000000000000000000000000000000000000',
+ 'mixHash': HexBytes('0x0000000000000000000000000000000000000000000000000000000000000000'),
+ 'nonce': HexBytes('0x0000000000000000'),
+ 'number': 0,
+ 'parentHash': HexBytes('0x0000000000000000000000000000000000000000000000000000000000000000'),
+ 'proofOfAuthorityData': HexBytes('0x0000000000000000000000000000000000000000000000000000000000000000dddc391ab2bf6701c74d0c8698c2e13355b2e4150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'),
+ '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.
+
+A few suggestions from here:
+
+- The :doc:`overview` page provides a summary of web3.py's features.
+- The :class:`w3.eth ` API contains the most frequently used methods.
+- A guide to :ref:`contracts` includes deployment and usage examples.
+- The nuances of :doc:`transactions` are explained in another guide.
+
+.. 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.
diff --git a/_build/html_zh_CN/_sources/release_notes.rst.txt b/_build/html_zh_CN/_sources/release_notes.rst.txt
new file mode 100644
index 0000000000..72b6123ebd
--- /dev/null
+++ b/_build/html_zh_CN/_sources/release_notes.rst.txt
@@ -0,0 +1,4762 @@
+Release Notes
+=============
+
+v7 Breaking Changes Summary
+ See the :ref:`v7 Migration Guide`
+
+.. towncrier release notes start
+
+web3.py v7.13.0 (2025-08-04)
+----------------------------
+
+Bugfixes
+~~~~~~~~
+
+- Raise ``BadResponseFormat`` from within ``FormattingMiddleware`` if the raw response is not a dict. (`#3735 `__)
+
+
+Improved Documentation
+~~~~~~~~~~~~~~~~~~~~~~
+
+- Fix broken link to external ``eth_gasPrice`` documentation. (`#3717 `__)
+
+
+Features
+~~~~~~~~
+
+- Support parallelization of subscription handling globally via the subscription manager ``parallelize`` flag, and on a per-subscription basis via the ``parallelize`` flag on the subscription itself. (`#3709 `__)
+
+
+Internal Changes - for web3.py Contributors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Update integration test suite fixture to test against geth ``v1.16.2``. (`#1162 `__)
+- Add missing async tests for ``FormattingMiddleware`` as a sanity check. (`#3735 `__)
+
+
+web3.py v7.12.1 (2025-07-14)
+----------------------------
+
+Bugfixes
+~~~~~~~~
+
+- Fix ``AutoProvider`` batching setup by adding a proxy batch request. (`#3712 `__)
+
+
+Internal Changes - for web3.py Contributors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Update integrations tests to use geth ``v1.16.0``. (`#3727 `__)
+
+
+Miscellaneous Changes
+~~~~~~~~~~~~~~~~~~~~~
+
+- `#3698 `__, `#3710 `__
+
+
+web3.py v7.12.0 (2025-05-22)
+----------------------------
+
+Bugfixes
+~~~~~~~~
+
+- Thread safety for batching and better consistency with ``PersistentConnectionProvider`` implementations:
+
+ - Make request batching threadsafe by using ``contextvars.ContextVar`` rather than a global flag for setting the batching state.
+ - Deterministically match responses with request ids for ``PersistentConnectionProvider`` batch requests. (`#3705 `__)
+
+
+Deprecations
+~~~~~~~~~~~~
+
+- Deprecate ``ens_encode_name`` in favor of ``dns_encode_name``. (`#3700 `__)
+
+
+Features
+~~~~~~~~
+
+- Introduce ``ens.utils.dns_encode_name`` as a rename of the current ``ens_encode_name``, for consistency across other language implementations and with the ENS docs. Returns ``HexBytes`` instead of ``bytes``. (`#3700 `__)
+
+
+Internal Changes - for web3.py Contributors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Update some types in ``web3._utils.method_formatters`` (`#3669 `__)
+- Fix issues and start running the core tests with `pytest-xdist`, effectively reducing the CI test times by ~75-80%. (`#3705 `__)
+
+
+Performance Improvements
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+- optimize message formatting for logging (`#3643 `__)
+- Optimize web3._utils.decorators.reject_recursive_repeats (`#3668 `__)
+- optimize Method.method_selector_function (`#3696 `__)
+- optimize map_abi_data (`#3697 `__)
+
+
+web3.py v7.11.1 (2025-05-12)
+----------------------------
+
+Bugfixes
+~~~~~~~~
+
+- Fix contract event ``FilterParams`` to validate and normalize ``address`` parameters. (`#3618 `__)
+- Properly handle ``PersistentConnectionClosedOK`` for ``subscription_manager.handle_subscriptions()``. (`#3690 `__)
+
+
+Deprecations
+~~~~~~~~~~~~
+
+- Deprecate eth.get_uncle* methods. Will be removed in v8. (`#3683 `__)
+
+
+Internal Changes - for web3.py Contributors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Re-compile test contracts with new Solidity ``v0.8.30`` and re-generate integration test fixture to test against latest geth ``v1.15.11``. (`#3692 `__)
+- Remove old test fixtures when generating a new test fixture. (`#3693 `__)
+- Address some flaky tests due to a geth bug in state synchronization. (`#3695 `__)
+
+
+web3.py v7.11.0 (2025-04-29)
+----------------------------
+
+Bugfixes
+~~~~~~~~
+
+- Checks that ``PersistentConnectionProvider`` response cache value is a dict before attempting to access it like one. Also adds checks to ``make_batch_request`` to make sure it is in batching mode before being called and is not after. (`#3642 `__)
+- Moves base providers' ``_is_batching`` and ``_batch_request_func_cache`` from class to instance attrs to help with thread safety. (`#3661 `__)
+
+
+Features
+~~~~~~~~
+
+- Support for Prague network upgrade, mainly ``requests_hash`` and ``authorization_list`` formatters. Add support for serializing ``SignedSetCodeTransaction`` (`eth-account` pydantic model) directly added to transaction dicts. (`#3659 `__)
+- Allow setting the ``request_information_cache_size`` for ``PersistentConnectionProvider`` implementations. (`#3662 `__)
+
+
+Internal Changes - for web3.py Contributors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Update some outdated TODO notes in code & remove old un-tested uncles tests as no longer relevant post-merge. (`#3605 `__)
+- Run each integration test in isolation and parallelize, instead of running them all within a single `geth` (for example) process. This prevents muddied test contexts. (`#3659 `__)
+- Bound hypothesis integers in some tests to a max of uint256 value (`#3665 `__)
+- AsyncENS tests were xfailing for the wrong reason. (`#3675 `__)
+
+
+Performance Improvements
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Optimize performance for:
+
+ * web3._utils.utility_methods.all_in_dict
+ * web3._utils.utility_methods.any_in_dict
+ * web3._utils.utility_methods.none_in_dict (`#3667 `__)
+- optimize web3._utils.rpc_abi.apply_abi_formatters_to_dict (`#3671 `__)
+
+
+web3.py v7.10.0 (2025-03-27)
+----------------------------
+
+Miscellaneous Changes
+~~~~~~~~~~~~~~~~~~~~~
+
+- `#3653 `__
+
+
+web3.py v7.9.0 (2025-03-12)
+---------------------------
+
+Bugfixes
+~~~~~~~~
+
+- Prevent mutating list of subscriptions when unsubscribing via the ``subscription_manager`` by iterating over a copy of the provided list. (`#3604 `__)
+- Batching can now be used with the AutoProvider (`#3607 `__)
+
+
+Improved Documentation
+~~~~~~~~~~~~~~~~~~~~~~
+
+- Update and clean up Contributing docs. (`#3610 `__)
+
+
+Features
+~~~~~~~~
+
+- Add ``use_text_frames`` flag for ``WebSocketProvider`` to work around websocket servers that don't support binary frames (`#3619 `__)
+- Sync and async support for ``eth_simulateV1`` RPC method. (`#3622 `__)
+
+
+Internal Changes - for web3.py Contributors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Renames a test so pytest finds it. (`#3606 `__)
+- Merge template, replacing ``bumpversion`` with ``bump-my-version``. (`#3610 `__)
+- Update integration test fixture to use latest geth version ``v1.15.5``. (`#3636 `__)
+- Use ``-U`` to install latest `py-geth` version for CI geth steps. This is usually a requirement if we're missing the binary for the newly-generated fixture geth version. (`#3637 `__)
+- Re-compile test contracts with newly released Solidity ``v0.8.29``. (`#3640 `__)
+
+
+Miscellaneous Changes
+~~~~~~~~~~~~~~~~~~~~~
+
+- `#3623 `__
+
+
+web3.py v7.8.0 (2025-02-03)
+---------------------------
+
+Breaking Changes
+~~~~~~~~~~~~~~~~
+
+- The bugfix to match ``unsubscribe`` to ``subscribe`` for multiple subscriptions breaks the function signature for ``unsubscribe``, changing the ``subscription`` argument to ``subscriptions``. (`#3585 `__)
+
+
+Bugfixes
+~~~~~~~~
+
+- Handle the case when a single RPC error response is returned for a batch request, instead of always expecting a list of responses. (`#3585 `__)
+- Don't raise on non-unique default subscription labels (no label provided). Only raise if a non-unique custom label is explicitly set for a subscription. (`#3594 `__)
+- Fix bugs related to subscription manager: ``run_forever`` can start with ``0`` subscriptions and remains alive, ``unsubscribe`` accepts single or multiple subs as objects or hexstrs, ``subscribe`` for many subs returns a list of hexstr ids. (`#3595 `__)
+- Fix issue where ``.values()`` raised a ``KeyError`` in ``NamedTupledOnion`` (`#3596 `__)
+
+
+Improved Documentation
+~~~~~~~~~~~~~~~~~~~~~~
+
+- Include ``topic`` attribute in ``ContractEvent`` docs. (`#3586 `__)
+- Introduce Event Subscriptions docs guide (`#3600 `__)
+
+
+Features
+~~~~~~~~
+
+- New ``Beacon`` and ``AsyncBeacon`` endpoints: ``get_peer_count``, ``get_attester_duties``, ``get_block_proposer_duties``, ``get_sync_committee_duties``, and ``get_attestation_rewards``. (`#3504 `__)
+
+
+Internal Changes - for web3.py Contributors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Move duplicate code into ``BaseContract`` class from ``Contract`` and ``AsyncContract``. (`#3579 `__)
+- Address flaky tests in CI runs. (`#3583 `__)
+- Update copyright year from 2024 to 2025 in the LICENSE file. (`#3592 `__)
+
+
+Performance Improvements
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Avoid unnecessary extra call to resolver when resolving an ENS address with no ``coin_type`` specified (default). (`#3584 `__)
+
+
+web3.py v7.7.0 (2025-01-15)
+---------------------------
+
+Bugfixes
+~~~~~~~~
+
+- Add a ``disconnect`` method to the AsyncHTTPProvider that closes all sessions and clears the cache (`#3557 `__)
+- Fix a bug related to building the ipc path for connecting to a geth ``--dev`` instance via ``web3.auto.gethdev``. (`#3576 `__)
+
+
+Features
+~~~~~~~~
+
+- Add a subscription manager to persistent connection providers, with support for handler methods for ``eth_subscribe`` subscriptions. (`#3554 `__)
+- Implement a ``topic`` property for contract events to retrieve the topic for the event. (`#3578 `__)
+
+
+Miscellaneous Changes
+~~~~~~~~~~~~~~~~~~~~~
+
+- `#3546 `__
+
+
+Performance Improvements
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Improve ``AttributeDict.recursive()`` and ``AttributeDictMiddleware`` performance, effectively speeding up response processing for attrdict middleware by nearly 2x. (`#3575 `__)
+
+
+web3.py v7.6.1 (2024-12-18)
+---------------------------
+
+Bugfixes
+~~~~~~~~
+
+- Include an end-of-line delimiter when sending messages via IPC with the ``IPCProvider`` and ``AsyncIPCProvider``. (`#3537 `__)
+- Contract functions and events no longer initialize for each call. Retrieval of overloaded functions and events is now deterministic. Any ambiguity will result in an exception being raised. (`#3540 `__)
+- Bump the eth-tester version to one that works in the tester dependency extras (`#3555 `__)
+
+
+Improved Documentation
+~~~~~~~~~~~~~~~~~~~~~~
+
+- Update ENS-related links (`#3563 `__)
+
+
+Internal Changes - for web3.py Contributors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Upgrade Geth Fixture to 1.14.12 (`#3533 `__)
+- Delete ``ARCHITECTURE.md`` as unused (`#3547 `__)
+
+
+Miscellaneous Changes
+~~~~~~~~~~~~~~~~~~~~~
+
+- `#3525 `__
+
+
+web3.py v7.6.0 (2024-11-22)
+---------------------------
+
+Bugfixes
+~~~~~~~~
+
+- Update the `ContractEvents` class to raise a `NoABIFound` exception if the `Contract` is initialized without an `ABI` and an attempt to access an event is made. This exception makes `ContractEvents` consistent with `ContractFunctions`. (`#3491 `__)
+
+
+Features
+~~~~~~~~
+
+- Contracts with overloaded functions or events are now supported. The Contract initializes functions and events using an identifier to distinguish between them. The identifier is the function or event signature, which consists of the name and the parameter types. (`#3491 `__)
+- - Support for ``w3.eth.blob_base_fee``
+ - Async support for ``w3.eth.blob_base_fee`` (`#3527 `__)
+
+
+Internal Changes - for web3.py Contributors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Pin ``websockets<14`` due to breaking changes (`#3529 `__)
+
+
+Miscellaneous Changes
+~~~~~~~~~~~~~~~~~~~~~
+
+- `#3491 `__
+
+
+web3.py v7.5.0 (2024-11-06)
+---------------------------
+
+Improved Documentation
+~~~~~~~~~~~~~~~~~~~~~~
+
+- Polish docs index page (`#3522 `__)
+
+
+Features
+~~~~~~~~
+
+- Add support for Geth Debug traceTransaction. (`#3334 `__)
+- New contract methods to obtain event elements from a contract ABI using a name, signature, selector, or topic. (`#3472 `__)
+
+
+Internal Changes - for web3.py Contributors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Add python 3.13 support (`#3493 `__)
+- Compile test contracts with newly released Solidity ``v0.8.28`` to ensure compatibility. (`#3515 `__)
+
+
+web3.py v7.4.0 (2024-10-16)
+---------------------------
+
+Bugfixes
+~~~~~~~~
+
+- Fix a bug where CCIP-Read expected a ``{sender}`` in the url for a POST request. If ``{data}`` is missing from the url, assume a POST request is being made regardless of whether ``{sender}`` is present. (`#3291 `__)
+- Fix a bug where non-mainnet chains could not cache requests based on missing ``finalized`` block number. (`#3508 `__)
+- Send ``json``, not ``data`` with CCIP-Read POST requests. (`#3512 `__)
+
+
+Improved Documentation
+~~~~~~~~~~~~~~~~~~~~~~
+
+- Update the request caching documentation to clarify on when to reach for request caching and how to configure the request validation threshold for certain endpoints. (`#3508 `__)
+
+
+Features
+~~~~~~~~
+
+- Allow a time interval, in seconds, to be used as the ``request_cache_validation_threshold`` for request caching. Keep a list of internal default values based on the chain id for some of the bigger chains. (`#3508 `__)
+
+
+web3.py v7.3.1 (2024-10-14)
+---------------------------
+
+Bugfixes
+~~~~~~~~
+
+- Properly wrap ``AsyncBeacon.request_timeout`` float in a ``aiohttp.ClientTimeout`` when making requests. (`#3503 `__)
+- Changes related to an `eth-typing` bugfix, input types for ``ABIEvent``: ``ABIComponent`` -> ``ABIComponentIndexed``. (`#3510 `__)
+
+
+Improved Documentation
+~~~~~~~~~~~~~~~~~~~~~~
+
+- Fix ``EthereumTesterProvider`` signature in docs, added an ``eth_tester`` example. (`#3500 `__)
+- Fix `pip install -e ".[dev]"` command in linux README. (`#3505 `__)
+
+
+Internal Changes - for web3.py Contributors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Update the ENSIP-15 to the latest spec and update the test suite. (`#3501 `__)
+
+
+web3.py v7.3.0 (2024-09-25)
+---------------------------
+
+Bugfixes
+~~~~~~~~
+
+- Base default ``maxFeePerGas`` calculation off of existing ``maxPriorityFeePerGas`` key instead of separate RPC call (`#3052 `__)
+- Add back dependency extra for 'tester'. (`#3480 `__)
+- Fix a bug where sensitive requests that make use of block data should not be cached until some validation threshold deems it is safe to do so, when request caching is turned on. (`#3483 `__)
+
+
+Improved Documentation
+~~~~~~~~~~~~~~~~~~~~~~
+
+- Update ``contract.encode_abi`` signature in docs and migration guide (`#3473 `__)
+- Update documentation around ``SignAndSendRawMiddlewareBuilder`` injection into the middleware onion. It should be injected lower in the stack than any middleware that modifies the transaction, in order to ensure those modified fields are signed. (`#3488 `__)
+- Docs cleanups related to ``test`` vs ``tester`` install extras. (`#3496 `__)
+
+
+Features
+~~~~~~~~
+
+- Add a configuration for request caching that sets a threshold for validating cached requests that make use of block data. This can be turned off altogether by setting the threshold to ``None``. (`#3483 `__)
+- Add a configuration option for the ``read_buffer_limit`` for ``AsyncIPCProvider`` in order to control the expected message size limit (defaults to 20MB). Add ``ReadBufferLimitReached`` for when the read limit is reached, extend from ``PersistentConnectionError``. (`#3492 `__)
+
+
+Internal Changes - for web3.py Contributors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Test warning cleanup (`#3468 `__)
+- Re-compile test contracts with recently released Solidity ``v0.8.27``. (`#3475 `__)
+- Re-organize the install extras. Re-define the ``test`` extra to always include the ``tester`` extra since it's needed for testing. (`#3495 `__)
+
+
+Miscellaneous Changes
+~~~~~~~~~~~~~~~~~~~~~
+
+- `#3490 `__
+
+
+Performance Improvements
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Improve logic for reading from the async IPC socket in order to properly handle and adjust the handling of large messages. This improves reading speeds in general. (`#3492 `__)
+
+
+web3.py v7.2.0 (2024-08-29)
+---------------------------
+
+Bugfixes
+~~~~~~~~
+
+- Fix a bug with newer ``hexbytes`` versions that yield non-0x-prefixed hex for ``HexBytes``: ``raw_transaction.hex()`` -> ``raw_transaction.to_0x_hex()``. (`#3471 `__)
+
+
+Features
+~~~~~~~~
+
+- HTTPProvider and AsyncHTTPProvider's get_request_headers is now available on both the class and the instance (`#3467 `__)
+
+
+web3.py v7.1.0 (2024-08-28)
+---------------------------
+
+Bugfixes
+~~~~~~~~
+
+- Specify a unique ``__hash__()`` for unhashable ``Web3Middleware`` types and use this hash as the middleware onion key when a name is not provided for the middleware. This fixes a bug where different middleware were given the same name and therefore raised errors. (`#3463 `__)
+
+
+Improved Documentation
+~~~~~~~~~~~~~~~~~~~~~~
+
+- Fix bug in filters example code (`#3455 `__)
+- Update ``v6`` -> ``v7`` migration guide with examples for importing and adding middleware, as well as examples on how to use the ``MiddlewareBuilder`` classes. (`#3462