web3 6.20.2__py3-none-any.whl → 7.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. ens/__init__.py +13 -2
  2. ens/_normalization.py +2 -17
  3. ens/async_ens.py +33 -21
  4. ens/base_ens.py +3 -1
  5. ens/ens.py +16 -11
  6. ens/exceptions.py +16 -29
  7. ens/specs/nf.json +1 -1
  8. ens/specs/normalization_spec.json +1 -1
  9. ens/utils.py +52 -63
  10. web3/__init__.py +20 -24
  11. web3/_utils/abi.py +115 -271
  12. web3/_utils/async_transactions.py +7 -4
  13. web3/_utils/batching.py +217 -0
  14. web3/_utils/blocks.py +6 -2
  15. web3/_utils/caching.py +128 -5
  16. web3/_utils/compat/__init__.py +2 -3
  17. web3/_utils/contract_sources/compile_contracts.py +1 -1
  18. web3/_utils/contract_sources/contract_data/arrays_contract.py +3 -3
  19. web3/_utils/contract_sources/contract_data/bytes_contracts.py +5 -5
  20. web3/_utils/contract_sources/contract_data/constructor_contracts.py +7 -7
  21. web3/_utils/contract_sources/contract_data/contract_caller_tester.py +3 -3
  22. web3/_utils/contract_sources/contract_data/emitter_contract.py +3 -3
  23. web3/_utils/contract_sources/contract_data/event_contracts.py +5 -5
  24. web3/_utils/contract_sources/contract_data/extended_resolver.py +3 -3
  25. web3/_utils/contract_sources/contract_data/fallback_function_contract.py +3 -3
  26. web3/_utils/contract_sources/contract_data/function_name_tester_contract.py +3 -3
  27. web3/_utils/contract_sources/contract_data/math_contract.py +3 -3
  28. web3/_utils/contract_sources/contract_data/offchain_lookup.py +3 -3
  29. web3/_utils/contract_sources/contract_data/offchain_resolver.py +3 -3
  30. web3/_utils/contract_sources/contract_data/panic_errors_contract.py +3 -3
  31. web3/_utils/contract_sources/contract_data/payable_tester.py +3 -3
  32. web3/_utils/contract_sources/contract_data/receive_function_contracts.py +5 -5
  33. web3/_utils/contract_sources/contract_data/reflector_contracts.py +3 -3
  34. web3/_utils/contract_sources/contract_data/revert_contract.py +3 -3
  35. web3/_utils/contract_sources/contract_data/simple_resolver.py +3 -3
  36. web3/_utils/contract_sources/contract_data/storage_contract.py +3 -3
  37. web3/_utils/contract_sources/contract_data/string_contract.py +3 -3
  38. web3/_utils/contract_sources/contract_data/tuple_contracts.py +5 -5
  39. web3/_utils/contracts.py +130 -236
  40. web3/_utils/datatypes.py +5 -1
  41. web3/_utils/decorators.py +13 -23
  42. web3/_utils/empty.py +1 -1
  43. web3/_utils/encoding.py +16 -12
  44. web3/_utils/ens.py +2 -1
  45. web3/_utils/error_formatters_utils.py +5 -3
  46. web3/_utils/events.py +66 -69
  47. web3/_utils/fee_utils.py +1 -3
  48. web3/_utils/filters.py +24 -22
  49. web3/_utils/formatters.py +2 -2
  50. web3/_utils/http.py +5 -3
  51. web3/_utils/http_session_manager.py +303 -0
  52. web3/_utils/math.py +14 -15
  53. web3/_utils/method_formatters.py +34 -36
  54. web3/_utils/module.py +2 -1
  55. web3/_utils/module_testing/__init__.py +0 -3
  56. web3/_utils/module_testing/eth_module.py +695 -643
  57. web3/_utils/module_testing/module_testing_utils.py +61 -34
  58. web3/_utils/module_testing/persistent_connection_provider.py +56 -25
  59. web3/_utils/module_testing/utils.py +258 -0
  60. web3/_utils/module_testing/web3_module.py +438 -17
  61. web3/_utils/normalizers.py +13 -11
  62. web3/_utils/rpc_abi.py +5 -32
  63. web3/_utils/threads.py +8 -7
  64. web3/_utils/transactions.py +14 -12
  65. web3/_utils/type_conversion.py +5 -1
  66. web3/_utils/validation.py +17 -17
  67. web3/auto/gethdev.py +7 -2
  68. web3/beacon/__init__.py +6 -1
  69. web3/beacon/async_beacon.py +9 -5
  70. web3/beacon/{main.py → beacon.py} +7 -5
  71. web3/contract/__init__.py +7 -0
  72. web3/contract/async_contract.py +47 -46
  73. web3/contract/base_contract.py +183 -158
  74. web3/contract/contract.py +49 -43
  75. web3/contract/utils.py +203 -59
  76. web3/datastructures.py +79 -31
  77. web3/eth/__init__.py +7 -0
  78. web3/eth/async_eth.py +39 -51
  79. web3/eth/base_eth.py +17 -10
  80. web3/eth/eth.py +30 -68
  81. web3/exceptions.py +108 -82
  82. web3/gas_strategies/time_based.py +8 -6
  83. web3/geth.py +1 -254
  84. web3/main.py +75 -122
  85. web3/manager.py +316 -146
  86. web3/method.py +38 -31
  87. web3/middleware/__init__.py +67 -89
  88. web3/middleware/attrdict.py +36 -49
  89. web3/middleware/base.py +174 -0
  90. web3/middleware/buffered_gas_estimate.py +20 -21
  91. web3/middleware/filter.py +157 -117
  92. web3/middleware/formatting.py +124 -108
  93. web3/middleware/gas_price_strategy.py +20 -32
  94. web3/middleware/names.py +29 -26
  95. web3/middleware/proof_of_authority.py +68 -0
  96. web3/middleware/pythonic.py +2 -2
  97. web3/middleware/signing.py +74 -89
  98. web3/middleware/stalecheck.py +52 -79
  99. web3/middleware/validation.py +5 -13
  100. web3/module.py +54 -10
  101. web3/providers/__init__.py +10 -6
  102. web3/providers/async_base.py +117 -39
  103. web3/providers/auto.py +3 -3
  104. web3/providers/base.py +89 -33
  105. web3/providers/eth_tester/__init__.py +5 -0
  106. web3/providers/eth_tester/defaults.py +1 -64
  107. web3/providers/eth_tester/main.py +99 -31
  108. web3/providers/eth_tester/middleware.py +45 -73
  109. web3/providers/ipc.py +42 -46
  110. web3/providers/{websocket/websocket.py → legacy_websocket.py} +32 -7
  111. web3/providers/persistent/__init__.py +22 -0
  112. web3/providers/persistent/async_ipc.py +153 -0
  113. web3/providers/{persistent.py → persistent/persistent.py} +106 -25
  114. web3/providers/persistent/persistent_connection.py +84 -0
  115. web3/providers/{websocket → persistent}/request_processor.py +94 -32
  116. web3/providers/persistent/utils.py +43 -0
  117. web3/providers/{websocket/websocket_v2.py → persistent/websocket.py} +29 -28
  118. web3/providers/rpc/__init__.py +11 -0
  119. web3/providers/rpc/async_rpc.py +171 -0
  120. web3/providers/rpc/rpc.py +179 -0
  121. web3/providers/rpc/utils.py +92 -0
  122. web3/testing.py +4 -4
  123. web3/tools/benchmark/main.py +22 -22
  124. web3/tools/benchmark/node.py +2 -8
  125. web3/tools/benchmark/reporting.py +2 -2
  126. web3/tools/benchmark/utils.py +1 -1
  127. web3/tracing.py +9 -5
  128. web3/types.py +30 -107
  129. web3/utils/__init__.py +58 -5
  130. web3/utils/abi.py +575 -10
  131. web3/utils/async_exception_handling.py +19 -7
  132. web3/utils/caching.py +32 -13
  133. web3/utils/exception_handling.py +7 -5
  134. {web3-6.20.2.dist-info → web3-7.0.0.dist-info}/LICENSE +1 -1
  135. web3-7.0.0.dist-info/METADATA +112 -0
  136. web3-7.0.0.dist-info/RECORD +167 -0
  137. {web3-6.20.2.dist-info → web3-7.0.0.dist-info}/WHEEL +1 -1
  138. {web3-6.20.2.dist-info → web3-7.0.0.dist-info}/top_level.txt +0 -1
  139. ethpm/__init__.py +0 -20
  140. ethpm/_utils/__init__.py +0 -0
  141. ethpm/_utils/backend.py +0 -93
  142. ethpm/_utils/cache.py +0 -44
  143. ethpm/_utils/chains.py +0 -119
  144. ethpm/_utils/contract.py +0 -35
  145. ethpm/_utils/deployments.py +0 -145
  146. ethpm/_utils/ipfs.py +0 -116
  147. ethpm/_utils/protobuf/__init__.py +0 -0
  148. ethpm/_utils/protobuf/ipfs_file_pb2.py +0 -33
  149. ethpm/_utils/registry.py +0 -29
  150. ethpm/assets/__init__.py +0 -0
  151. ethpm/assets/ens/v3.json +0 -1
  152. ethpm/assets/escrow/with_bytecode_v3.json +0 -1
  153. ethpm/assets/ipfs_file.proto +0 -32
  154. ethpm/assets/owned/output_v3.json +0 -1
  155. ethpm/assets/owned/with_contract_type_v3.json +0 -1
  156. ethpm/assets/registry/contracts/Authority.sol +0 -156
  157. ethpm/assets/registry/contracts/IndexedOrderedSetLib.sol +0 -106
  158. ethpm/assets/registry/contracts/PackageDB.sol +0 -225
  159. ethpm/assets/registry/contracts/PackageRegistry.sol +0 -361
  160. ethpm/assets/registry/contracts/PackageRegistryInterface.sol +0 -97
  161. ethpm/assets/registry/contracts/ReleaseDB.sol +0 -309
  162. ethpm/assets/registry/contracts/ReleaseValidator.sol +0 -152
  163. ethpm/assets/registry/solc_input.json +0 -1
  164. ethpm/assets/registry/solc_output.json +0 -1
  165. ethpm/assets/registry/v3.json +0 -1
  166. ethpm/assets/safe-math-lib/v3-strict-no-deployments.json +0 -1
  167. ethpm/assets/simple-registry/contracts/Ownable.sol +0 -63
  168. ethpm/assets/simple-registry/contracts/PackageRegistry.sol +0 -373
  169. ethpm/assets/simple-registry/contracts/PackageRegistryInterface.sol +0 -96
  170. ethpm/assets/simple-registry/solc_input.json +0 -33
  171. ethpm/assets/simple-registry/solc_output.json +0 -1
  172. ethpm/assets/simple-registry/v3.json +0 -1
  173. ethpm/assets/standard-token/output_v3.json +0 -1
  174. ethpm/assets/standard-token/with_bytecode_v3.json +0 -1
  175. ethpm/assets/vyper_registry/0.1.0.json +0 -1
  176. ethpm/assets/vyper_registry/registry.vy +0 -216
  177. ethpm/assets/vyper_registry/registry_with_delete.vy +0 -244
  178. ethpm/backends/__init__.py +0 -0
  179. ethpm/backends/base.py +0 -43
  180. ethpm/backends/http.py +0 -108
  181. ethpm/backends/ipfs.py +0 -219
  182. ethpm/backends/registry.py +0 -154
  183. ethpm/constants.py +0 -17
  184. ethpm/contract.py +0 -187
  185. ethpm/dependencies.py +0 -58
  186. ethpm/deployments.py +0 -80
  187. ethpm/ethpm-spec/examples/escrow/1.0.0-pretty.json +0 -146
  188. ethpm/ethpm-spec/examples/escrow/1.0.0.json +0 -1
  189. ethpm/ethpm-spec/examples/escrow/contracts/Escrow.sol +0 -32
  190. ethpm/ethpm-spec/examples/escrow/contracts/SafeSendLib.sol +0 -20
  191. ethpm/ethpm-spec/examples/escrow/v3-pretty.json +0 -171
  192. ethpm/ethpm-spec/examples/escrow/v3.json +0 -1
  193. ethpm/ethpm-spec/examples/owned/1.0.0-pretty.json +0 -21
  194. ethpm/ethpm-spec/examples/owned/1.0.0.json +0 -1
  195. ethpm/ethpm-spec/examples/owned/contracts/Owned.sol +0 -12
  196. ethpm/ethpm-spec/examples/owned/v3-pretty.json +0 -27
  197. ethpm/ethpm-spec/examples/owned/v3.json +0 -1
  198. ethpm/ethpm-spec/examples/piper-coin/1.0.0-pretty.json +0 -31
  199. ethpm/ethpm-spec/examples/piper-coin/1.0.0.json +0 -1
  200. ethpm/ethpm-spec/examples/piper-coin/v3-pretty.json +0 -21
  201. ethpm/ethpm-spec/examples/piper-coin/v3.json +0 -1
  202. ethpm/ethpm-spec/examples/safe-math-lib/1.0.0-pretty.json +0 -85
  203. ethpm/ethpm-spec/examples/safe-math-lib/1.0.0.json +0 -1
  204. ethpm/ethpm-spec/examples/safe-math-lib/contracts/SafeMathLib.sol +0 -24
  205. ethpm/ethpm-spec/examples/safe-math-lib/v3-pretty.json +0 -117
  206. ethpm/ethpm-spec/examples/safe-math-lib/v3.json +0 -1
  207. ethpm/ethpm-spec/examples/standard-token/1.0.0-pretty.json +0 -55
  208. ethpm/ethpm-spec/examples/standard-token/1.0.0.json +0 -1
  209. ethpm/ethpm-spec/examples/standard-token/contracts/AbstractToken.sol +0 -20
  210. ethpm/ethpm-spec/examples/standard-token/contracts/StandardToken.sol +0 -84
  211. ethpm/ethpm-spec/examples/standard-token/v3-pretty.json +0 -460
  212. ethpm/ethpm-spec/examples/standard-token/v3.json +0 -1
  213. ethpm/ethpm-spec/examples/transferable/1.0.0-pretty.json +0 -21
  214. ethpm/ethpm-spec/examples/transferable/1.0.0.json +0 -1
  215. ethpm/ethpm-spec/examples/transferable/contracts/Transferable.sol +0 -14
  216. ethpm/ethpm-spec/examples/transferable/v3-pretty.json +0 -27
  217. ethpm/ethpm-spec/examples/transferable/v3.json +0 -1
  218. ethpm/ethpm-spec/examples/wallet/1.0.0-pretty.json +0 -120
  219. ethpm/ethpm-spec/examples/wallet/1.0.0.json +0 -1
  220. ethpm/ethpm-spec/examples/wallet/contracts/Wallet.sol +0 -41
  221. ethpm/ethpm-spec/examples/wallet/v3-pretty.json +0 -181
  222. ethpm/ethpm-spec/examples/wallet/v3.json +0 -1
  223. ethpm/ethpm-spec/examples/wallet-with-send/1.0.0-pretty.json +0 -135
  224. ethpm/ethpm-spec/examples/wallet-with-send/1.0.0.json +0 -1
  225. ethpm/ethpm-spec/examples/wallet-with-send/contracts/WalletWithSend.sol +0 -18
  226. ethpm/ethpm-spec/examples/wallet-with-send/v3-pretty.json +0 -207
  227. ethpm/ethpm-spec/examples/wallet-with-send/v3.json +0 -1
  228. ethpm/ethpm-spec/spec/package.spec.json +0 -379
  229. ethpm/ethpm-spec/spec/v3.spec.json +0 -483
  230. ethpm/exceptions.py +0 -68
  231. ethpm/package.py +0 -438
  232. ethpm/tools/__init__.py +0 -4
  233. ethpm/tools/builder.py +0 -930
  234. ethpm/tools/checker.py +0 -312
  235. ethpm/tools/get_manifest.py +0 -19
  236. ethpm/uri.py +0 -141
  237. ethpm/validation/__init__.py +0 -0
  238. ethpm/validation/manifest.py +0 -146
  239. ethpm/validation/misc.py +0 -39
  240. ethpm/validation/package.py +0 -80
  241. ethpm/validation/uri.py +0 -163
  242. web3/_utils/contract_sources/contract_data/address_reflector.py +0 -29
  243. web3/_utils/miner.py +0 -88
  244. web3/_utils/module_testing/go_ethereum_personal_module.py +0 -323
  245. web3/_utils/request.py +0 -265
  246. web3/middleware/abi.py +0 -11
  247. web3/middleware/async_cache.py +0 -99
  248. web3/middleware/cache.py +0 -374
  249. web3/middleware/exception_handling.py +0 -49
  250. web3/middleware/exception_retry_request.py +0 -188
  251. web3/middleware/fixture.py +0 -190
  252. web3/middleware/geth_poa.py +0 -81
  253. web3/middleware/normalize_request_parameters.py +0 -11
  254. web3/middleware/simulate_unmined_transaction.py +0 -43
  255. web3/pm.py +0 -602
  256. web3/providers/async_rpc.py +0 -99
  257. web3/providers/rpc.py +0 -98
  258. web3/providers/websocket/__init__.py +0 -11
  259. web3/providers/websocket/websocket_connection.py +0 -42
  260. web3/tools/__init__.py +0 -4
  261. web3/tools/pytest_ethereum/__init__.py +0 -0
  262. web3/tools/pytest_ethereum/_utils.py +0 -145
  263. web3/tools/pytest_ethereum/deployer.py +0 -48
  264. web3/tools/pytest_ethereum/exceptions.py +0 -22
  265. web3/tools/pytest_ethereum/linker.py +0 -128
  266. web3/tools/pytest_ethereum/plugins.py +0 -33
  267. web3-6.20.2.dist-info/METADATA +0 -103
  268. web3-6.20.2.dist-info/RECORD +0 -283
  269. web3-6.20.2.dist-info/entry_points.txt +0 -2
  270. /web3/_utils/{function_identifiers.py → abi_element_identifiers.py} +0 -0
@@ -1,7 +1,7 @@
1
1
  from typing import (
2
2
  TYPE_CHECKING,
3
3
  Any,
4
- Callable,
4
+ cast,
5
5
  )
6
6
 
7
7
  from eth_utils.toolz import (
@@ -14,10 +14,11 @@ from web3._utils.async_transactions import (
14
14
  from web3._utils.transactions import (
15
15
  get_buffered_gas_estimate,
16
16
  )
17
+ from web3.middleware.base import (
18
+ Web3Middleware,
19
+ )
17
20
  from web3.types import (
18
- AsyncMiddlewareCoroutine,
19
21
  RPCEndpoint,
20
- RPCResponse,
21
22
  )
22
23
 
23
24
  if TYPE_CHECKING:
@@ -27,34 +28,32 @@ if TYPE_CHECKING:
27
28
  )
28
29
 
29
30
 
30
- def buffered_gas_estimate_middleware(
31
- make_request: Callable[[RPCEndpoint, Any], Any], w3: "Web3"
32
- ) -> Callable[[RPCEndpoint, Any], RPCResponse]:
33
- def middleware(method: RPCEndpoint, params: Any) -> RPCResponse:
31
+ class BufferedGasEstimateMiddleware(Web3Middleware):
32
+ """
33
+ Includes a gas estimate for all transactions that do not already have a gas value.
34
+ """
35
+
36
+ def request_processor(self, method: "RPCEndpoint", params: Any) -> Any:
34
37
  if method == "eth_sendTransaction":
35
38
  transaction = params[0]
36
39
  if "gas" not in transaction:
37
40
  transaction = assoc(
38
41
  transaction,
39
42
  "gas",
40
- hex(get_buffered_gas_estimate(w3, transaction)),
43
+ hex(get_buffered_gas_estimate(cast("Web3", self._w3), transaction)),
41
44
  )
42
- return make_request(method, [transaction])
43
- return make_request(method, params)
44
-
45
- return middleware
45
+ params = (transaction,)
46
+ return method, params
46
47
 
48
+ # -- async -- #
47
49
 
48
- async def async_buffered_gas_estimate_middleware(
49
- make_request: Callable[[RPCEndpoint, Any], Any], w3: "AsyncWeb3"
50
- ) -> AsyncMiddlewareCoroutine:
51
- async def middleware(method: RPCEndpoint, params: Any) -> RPCResponse:
50
+ async def async_request_processor(self, method: "RPCEndpoint", params: Any) -> Any:
52
51
  if method == "eth_sendTransaction":
53
52
  transaction = params[0]
54
53
  if "gas" not in transaction:
55
- gas_estimate = await async_get_buffered_gas_estimate(w3, transaction)
54
+ gas_estimate = await async_get_buffered_gas_estimate(
55
+ cast("AsyncWeb3", self._w3), transaction
56
+ )
56
57
  transaction = assoc(transaction, "gas", hex(gas_estimate))
57
- return await make_request(method, [transaction])
58
- return await make_request(method, params)
59
-
60
- return middleware
58
+ params = (transaction,)
59
+ return method, params
web3/middleware/filter.py CHANGED
@@ -5,7 +5,6 @@ from typing import (
5
5
  Any,
6
6
  AsyncIterable,
7
7
  AsyncIterator,
8
- Callable,
9
8
  Dict,
10
9
  Generator,
11
10
  Iterable,
@@ -43,18 +42,30 @@ from web3._utils.formatters import (
43
42
  from web3._utils.rpc_abi import (
44
43
  RPC,
45
44
  )
45
+ from web3.exceptions import (
46
+ Web3TypeError,
47
+ )
48
+ from web3.middleware.base import (
49
+ Web3Middleware,
50
+ )
46
51
  from web3.types import (
47
- Coroutine,
52
+ AsyncMakeRequestFn,
48
53
  FilterParams,
49
54
  LatestBlockParam,
50
55
  LogReceipt,
51
- RPCEndpoint,
52
- RPCResponse,
56
+ MakeRequestFn,
53
57
  _Hash32,
54
58
  )
55
59
 
56
60
  if TYPE_CHECKING:
57
- from web3 import Web3 # noqa: F401
61
+ from web3 import ( # noqa: F401
62
+ AsyncWeb3,
63
+ Web3,
64
+ )
65
+ from web3.types import ( # noqa: F401
66
+ RPCEndpoint,
67
+ RPCResponse,
68
+ )
58
69
 
59
70
  if "WEB3_MAX_BLOCK_REQUEST" in os.environ:
60
71
  MAX_BLOCK_REQUEST = to_int(text=os.environ["WEB3_MAX_BLOCK_REQUEST"])
@@ -63,7 +74,8 @@ else:
63
74
 
64
75
 
65
76
  def segment_count(start: int, stop: int, step: int = 5) -> Iterable[Tuple[int, int]]:
66
- """Creates a segment counting generator
77
+ """
78
+ Creates a segment counting generator
67
79
 
68
80
  The generator returns tuple pairs of integers
69
81
  that correspond to segments in the provided range.
@@ -76,6 +88,7 @@ def segment_count(start: int, stop: int, step: int = 5) -> Iterable[Tuple[int, i
76
88
 
77
89
 
78
90
  Example:
91
+ -------
79
92
 
80
93
  >>> segment_counter = segment_count(start=0, stop=10, step=3)
81
94
  >>> next(segment_counter)
@@ -86,6 +99,7 @@ def segment_count(start: int, stop: int, step: int = 5) -> Iterable[Tuple[int, i
86
99
  (6, 9)
87
100
  >>> next(segment_counter) # Remainder is also returned
88
101
  (9, 10)
102
+
89
103
  """
90
104
  return gen_bounded_segments(start, stop, step)
91
105
 
@@ -96,10 +110,9 @@ def gen_bounded_segments(start: int, stop: int, step: int) -> Iterable[Tuple[int
96
110
  if start + step >= stop:
97
111
  yield (start, stop)
98
112
  return
99
- for segment in zip(
113
+ yield from zip(
100
114
  range(start, stop - step + 1, step), range(start + step, stop + 1, step)
101
- ):
102
- yield segment
115
+ )
103
116
 
104
117
  remainder = (stop - start) % step
105
118
  # Handle the remainder
@@ -110,13 +123,14 @@ def gen_bounded_segments(start: int, stop: int, step: int) -> Iterable[Tuple[int
110
123
  def block_ranges(
111
124
  start_block: BlockNumber, last_block: Optional[BlockNumber], step: int = 5
112
125
  ) -> Iterable[Tuple[BlockNumber, BlockNumber]]:
113
- """Returns 2-tuple ranges describing ranges of block from start_block to last_block
126
+ """
127
+ Returns 2-tuple ranges describing ranges of block from start_block to last_block
114
128
 
115
129
  Ranges do not overlap to facilitate use as ``toBlock``, ``fromBlock``
116
130
  json-rpc arguments, which are both inclusive.
117
131
  """
118
132
  if last_block is not None and start_block > last_block:
119
- raise TypeError(
133
+ raise Web3TypeError(
120
134
  "Incompatible start and stop arguments.",
121
135
  "Start must be less than or equal to stop.",
122
136
  )
@@ -130,7 +144,8 @@ def block_ranges(
130
144
  def iter_latest_block(
131
145
  w3: "Web3", to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None
132
146
  ) -> Iterable[BlockNumber]:
133
- """Returns a generator that dispenses the latest block, if
147
+ """
148
+ Returns a generator that dispenses the latest block, if
134
149
  any new blocks have been mined since last iteration.
135
150
 
136
151
  If there are no new blocks or the latest block is greater than
@@ -152,8 +167,7 @@ def iter_latest_block(
152
167
 
153
168
  while True:
154
169
  latest_block = w3.eth.block_number
155
- # type ignored b/c is_bounded_range prevents unsupported comparison
156
- if is_bounded_range and latest_block > to_block: # type: ignore
170
+ if is_bounded_range and latest_block > cast(BlockNumber, to_block):
157
171
  yield None
158
172
  # No new blocks since last iteration.
159
173
  if _last is not None and _last == latest_block:
@@ -168,7 +182,8 @@ def iter_latest_block_ranges(
168
182
  from_block: BlockNumber,
169
183
  to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None,
170
184
  ) -> Iterable[Tuple[Optional[BlockNumber], Optional[BlockNumber]]]:
171
- """Returns an iterator unloading ranges of available blocks
185
+ """
186
+ Returns an iterator unloading ranges of available blocks
172
187
 
173
188
  starting from `fromBlock` to the latest mined block,
174
189
  until reaching toBlock. e.g.:
@@ -204,7 +219,8 @@ def get_logs_multipart(
204
219
  topics: List[Optional[Union[_Hash32, List[_Hash32]]]],
205
220
  max_blocks: int,
206
221
  ) -> Iterable[List[LogReceipt]]:
207
- """Used to break up requests to ``eth_getLogs``
222
+ """
223
+ Used to break up requests to ``eth_getLogs``
208
224
 
209
225
  The getLog request is partitioned into multiple calls of the max number of blocks
210
226
  ``max_blocks``.
@@ -239,9 +255,8 @@ class RequestLogs:
239
255
  if from_block is None or from_block == "latest":
240
256
  self._from_block = BlockNumber(w3.eth.block_number + 1)
241
257
  elif is_string(from_block) and is_hex(from_block):
242
- self._from_block = BlockNumber(hex_to_integer(from_block)) # type: ignore
258
+ self._from_block = BlockNumber(hex_to_integer(cast(HexStr, from_block)))
243
259
  else:
244
- # cast b/c LatestBlockParam is handled above
245
260
  self._from_block = from_block
246
261
  self._to_block = to_block
247
262
  self.filter_changes = self._get_filter_changes()
@@ -257,7 +272,7 @@ class RequestLogs:
257
272
  elif self._to_block == "latest":
258
273
  to_block = self.w3.eth.block_number
259
274
  elif is_string(self._to_block) and is_hex(self._to_block):
260
- to_block = BlockNumber(hex_to_integer(self._to_block)) # type: ignore
275
+ to_block = BlockNumber(hex_to_integer(cast(HexStr, self._to_block)))
261
276
  else:
262
277
  to_block = self._to_block
263
278
 
@@ -338,59 +353,14 @@ def block_hashes_in_range(
338
353
  yield getattr(w3.eth.get_block(BlockNumber(block_number)), "hash", None)
339
354
 
340
355
 
341
- def local_filter_middleware(
342
- make_request: Callable[[RPCEndpoint, Any], Any], w3: "Web3"
343
- ) -> Callable[[RPCEndpoint, Any], RPCResponse]:
344
- filters = {}
345
- filter_id_counter = map(to_hex, itertools.count())
346
-
347
- def middleware(method: RPCEndpoint, params: Any) -> RPCResponse:
348
- if method in NEW_FILTER_METHODS:
349
- filter_id = next(filter_id_counter)
350
-
351
- _filter: Union[RequestLogs, RequestBlocks]
352
- if method == RPC.eth_newFilter:
353
- _filter = RequestLogs(
354
- w3, **apply_key_map(FILTER_PARAMS_KEY_MAP, params[0])
355
- )
356
-
357
- elif method == RPC.eth_newBlockFilter:
358
- _filter = RequestBlocks(w3)
359
-
360
- else:
361
- raise NotImplementedError(method)
362
-
363
- filters[filter_id] = _filter
364
- return {"result": filter_id}
365
-
366
- elif method in FILTER_CHANGES_METHODS:
367
- filter_id = params[0]
368
- # Pass through to filters not created by middleware
369
- if filter_id not in filters:
370
- return make_request(method, params)
371
- _filter = filters[filter_id]
372
- if method == RPC.eth_getFilterChanges:
373
- return {"result": next(_filter.filter_changes)}
374
-
375
- elif method == RPC.eth_getFilterLogs:
376
- # type ignored b/c logic prevents RequestBlocks which
377
- # doesn't implement get_logs
378
- return {"result": _filter.get_logs()} # type: ignore
379
- else:
380
- raise NotImplementedError(method)
381
- else:
382
- return make_request(method, params)
383
-
384
- return middleware
385
-
386
-
387
356
  # --- async --- #
388
357
 
389
358
 
390
359
  async def async_iter_latest_block(
391
- w3: "Web3", to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None
360
+ w3: "AsyncWeb3", to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None
392
361
  ) -> AsyncIterable[BlockNumber]:
393
- """Returns a generator that dispenses the latest block, if
362
+ """
363
+ Returns a generator that dispenses the latest block, if
394
364
  any new blocks have been mined since last iteration.
395
365
 
396
366
  If there are no new blocks or the latest block is greater than
@@ -411,9 +381,9 @@ async def async_iter_latest_block(
411
381
  is_bounded_range = to_block is not None and to_block != "latest"
412
382
 
413
383
  while True:
414
- latest_block = await w3.eth.block_number # type: ignore
384
+ latest_block = await w3.eth.block_number
415
385
  # type ignored b/c is_bounded_range prevents unsupported comparison
416
- if is_bounded_range and latest_block > to_block:
386
+ if is_bounded_range and latest_block > cast(int, to_block):
417
387
  yield None
418
388
  # No new blocks since last iteration.
419
389
  if _last is not None and _last == latest_block:
@@ -424,11 +394,12 @@ async def async_iter_latest_block(
424
394
 
425
395
 
426
396
  async def async_iter_latest_block_ranges(
427
- w3: "Web3",
397
+ w3: "AsyncWeb3",
428
398
  from_block: BlockNumber,
429
399
  to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None,
430
400
  ) -> AsyncIterable[Tuple[Optional[BlockNumber], Optional[BlockNumber]]]:
431
- """Returns an iterator unloading ranges of available blocks
401
+ """
402
+ Returns an iterator unloading ranges of available blocks
432
403
 
433
404
  starting from `from_block` to the latest mined block,
434
405
  until reaching to_block. e.g.:
@@ -454,14 +425,15 @@ async def async_iter_latest_block_ranges(
454
425
 
455
426
 
456
427
  async def async_get_logs_multipart(
457
- w3: "Web3",
428
+ w3: "AsyncWeb3",
458
429
  start_block: BlockNumber,
459
430
  stop_block: BlockNumber,
460
431
  address: Union[Address, ChecksumAddress, List[Union[Address, ChecksumAddress]]],
461
432
  topics: List[Optional[Union[_Hash32, List[_Hash32]]]],
462
433
  max_blocks: int,
463
434
  ) -> AsyncIterable[List[LogReceipt]]:
464
- """Used to break up requests to ``eth_getLogs``
435
+ """
436
+ Used to break up requests to ``eth_getLogs``
465
437
 
466
438
  The getLog request is partitioned into multiple calls of the max number of blocks
467
439
  ``max_blocks``.
@@ -477,7 +449,7 @@ async def async_get_logs_multipart(
477
449
  params_with_none_dropped = cast(
478
450
  FilterParams, drop_items_with_none_value(params)
479
451
  )
480
- next_logs = await w3.eth.get_logs(params_with_none_dropped) # type: ignore
452
+ next_logs = await w3.eth.get_logs(params_with_none_dropped)
481
453
  yield next_logs
482
454
 
483
455
 
@@ -486,7 +458,7 @@ class AsyncRequestLogs:
486
458
 
487
459
  def __init__(
488
460
  self,
489
- w3: "Web3",
461
+ w3: "AsyncWeb3",
490
462
  from_block: Optional[Union[BlockNumber, LatestBlockParam]] = None,
491
463
  to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None,
492
464
  address: Optional[
@@ -504,7 +476,7 @@ class AsyncRequestLogs:
504
476
  def __await__(self) -> Generator[Any, None, "AsyncRequestLogs"]:
505
477
  async def closure() -> "AsyncRequestLogs":
506
478
  if self._from_block_arg is None or self._from_block_arg == "latest":
507
- self.block_number = await self.w3.eth.block_number # type: ignore
479
+ self.block_number = await self.w3.eth.block_number
508
480
  self._from_block = BlockNumber(self.block_number + 1)
509
481
  elif is_string(self._from_block_arg) and is_hex(self._from_block_arg):
510
482
  self._from_block = BlockNumber(
@@ -524,7 +496,7 @@ class AsyncRequestLogs:
524
496
  @property
525
497
  async def to_block(self) -> BlockNumber:
526
498
  if self._to_block is None or self._to_block == "latest":
527
- to_block = await self.w3.eth.block_number # type: ignore
499
+ to_block = await self.w3.eth.block_number
528
500
  elif is_string(self._to_block) and is_hex(self._to_block):
529
501
  to_block = BlockNumber(hex_to_integer(cast(HexStr, self._to_block)))
530
502
  else:
@@ -572,12 +544,12 @@ class AsyncRequestLogs:
572
544
 
573
545
 
574
546
  class AsyncRequestBlocks:
575
- def __init__(self, w3: "Web3") -> None:
547
+ def __init__(self, w3: "AsyncWeb3") -> None:
576
548
  self.w3 = w3
577
549
 
578
550
  def __await__(self) -> Generator[Any, None, "AsyncRequestBlocks"]:
579
551
  async def closure() -> "AsyncRequestBlocks":
580
- self.block_number = await self.w3.eth.block_number # type: ignore
552
+ self.block_number = await self.w3.eth.block_number
581
553
  self.start_block = BlockNumber(self.block_number + 1)
582
554
  return self
583
555
 
@@ -597,7 +569,7 @@ class AsyncRequestBlocks:
597
569
 
598
570
 
599
571
  async def async_block_hashes_in_range(
600
- w3: "Web3", block_range: Tuple[BlockNumber, BlockNumber]
572
+ w3: "AsyncWeb3", block_range: Tuple[BlockNumber, BlockNumber]
601
573
  ) -> List[Union[None, Hash32]]:
602
574
  from_block, to_block = block_range
603
575
  if from_block is None or to_block is None:
@@ -605,56 +577,124 @@ async def async_block_hashes_in_range(
605
577
 
606
578
  block_hashes = []
607
579
  for block_number in range(from_block, to_block + 1):
608
- w3_get_block = await w3.eth.get_block(BlockNumber(block_number)) # type: ignore
580
+ w3_get_block = await w3.eth.get_block(BlockNumber(block_number))
609
581
  block_hashes.append(getattr(w3_get_block, "hash", None))
610
582
 
611
583
  return block_hashes
612
584
 
613
585
 
614
- async def async_local_filter_middleware(
615
- make_request: Callable[[RPCEndpoint, Any], Any], w3: "Web3"
616
- ) -> Callable[[RPCEndpoint, Any], Coroutine[Any, Any, RPCResponse]]:
617
- filters = {}
618
- filter_id_counter = map(to_hex, itertools.count())
586
+ # -- middleware -- #
619
587
 
620
- async def middleware(method: RPCEndpoint, params: Any) -> RPCResponse:
621
- if method in NEW_FILTER_METHODS:
622
- filter_id = next(filter_id_counter)
588
+ SyncFilter = Union[RequestLogs, RequestBlocks]
589
+ AsyncFilter = Union[AsyncRequestLogs, AsyncRequestBlocks]
623
590
 
624
- _filter: Union[AsyncRequestLogs, AsyncRequestBlocks]
625
- if method == RPC.eth_newFilter:
626
- _filter = await AsyncRequestLogs(
627
- w3, **apply_key_map(FILTER_PARAMS_KEY_MAP, params[0])
628
- )
629
591
 
630
- elif method == RPC.eth_newBlockFilter:
631
- _filter = await AsyncRequestBlocks(w3)
592
+ def _simulate_rpc_response_with_result(filter_id: str) -> "RPCResponse":
593
+ return {"jsonrpc": "2.0", "id": -1, "result": filter_id}
594
+
595
+
596
+ class LocalFilterMiddleware(Web3Middleware):
597
+ def __init__(self, w3: Union["Web3", "AsyncWeb3"]):
598
+ self.filters: Dict[str, SyncFilter] = {}
599
+ self.async_filters: Dict[str, AsyncFilter] = {}
600
+ self.filter_id_counter = itertools.count()
601
+ super().__init__(w3)
602
+
603
+ def wrap_make_request(self, make_request: MakeRequestFn) -> MakeRequestFn:
604
+ def middleware(method: "RPCEndpoint", params: Any) -> "RPCResponse":
605
+ if method in NEW_FILTER_METHODS:
606
+ _filter: SyncFilter
607
+ filter_id = to_hex(next(self.filter_id_counter))
608
+
609
+ if method == RPC.eth_newFilter:
610
+ _filter = RequestLogs(
611
+ cast("Web3", self._w3),
612
+ **apply_key_map(FILTER_PARAMS_KEY_MAP, params[0])
613
+ )
614
+
615
+ elif method == RPC.eth_newBlockFilter:
616
+ _filter = RequestBlocks(cast("Web3", self._w3))
617
+
618
+ else:
619
+ raise NotImplementedError(method)
620
+
621
+ self.filters[filter_id] = _filter
622
+ return _simulate_rpc_response_with_result(filter_id)
623
+
624
+ elif method in FILTER_CHANGES_METHODS:
625
+ _filter_id = params[0]
626
+
627
+ # Pass through to filters not created by middleware
628
+ if _filter_id not in self.filters:
629
+ return make_request(method, params)
630
+
631
+ _filter = self.filters[_filter_id]
632
+ if method == RPC.eth_getFilterChanges:
633
+ return _simulate_rpc_response_with_result(
634
+ next(_filter.filter_changes) # type: ignore
635
+ )
632
636
 
637
+ elif method == RPC.eth_getFilterLogs:
638
+ # type ignored b/c logic prevents RequestBlocks which
639
+ # doesn't implement get_logs
640
+ return _simulate_rpc_response_with_result(
641
+ _filter.get_logs() # type: ignore
642
+ )
643
+ else:
644
+ raise NotImplementedError(method)
633
645
  else:
634
- raise NotImplementedError(method)
646
+ return make_request(method, params)
635
647
 
636
- filters[filter_id] = _filter
637
- return {"result": filter_id}
648
+ return middleware
638
649
 
639
- elif method in FILTER_CHANGES_METHODS:
640
- filter_id = params[0]
641
- # Pass through to filters not created by middleware
642
- if filter_id not in filters:
643
- return await make_request(method, params)
644
- _filter = filters[filter_id]
650
+ # -- async -- #
651
+
652
+ async def async_wrap_make_request(
653
+ self,
654
+ make_request: AsyncMakeRequestFn,
655
+ ) -> AsyncMakeRequestFn:
656
+ async def middleware(method: "RPCEndpoint", params: Any) -> "RPCResponse":
657
+ if method in NEW_FILTER_METHODS:
658
+ _filter: AsyncFilter
659
+ filter_id = to_hex(next(self.filter_id_counter))
660
+
661
+ if method == RPC.eth_newFilter:
662
+ _filter = await AsyncRequestLogs(
663
+ cast("AsyncWeb3", self._w3),
664
+ **apply_key_map(FILTER_PARAMS_KEY_MAP, params[0])
665
+ )
666
+
667
+ elif method == RPC.eth_newBlockFilter:
668
+ _filter = await AsyncRequestBlocks(cast("AsyncWeb3", self._w3))
645
669
 
646
- if method == RPC.eth_getFilterChanges:
647
- changes = await _filter.filter_changes.__anext__()
648
- return {"result": changes}
670
+ else:
671
+ raise NotImplementedError(method)
649
672
 
650
- elif method == RPC.eth_getFilterLogs:
651
- # type ignored b/c logic prevents RequestBlocks which
652
- # doesn't implement get_logs
653
- logs = await _filter.get_logs() # type: ignore
654
- return {"result": logs}
673
+ self.async_filters[filter_id] = _filter
674
+ return _simulate_rpc_response_with_result(filter_id)
675
+
676
+ elif method in FILTER_CHANGES_METHODS:
677
+ _filter_id = params[0]
678
+
679
+ # Pass through to filters not created by middleware
680
+ if _filter_id not in self.async_filters:
681
+ return await make_request(method, params)
682
+
683
+ _filter = self.async_filters[_filter_id]
684
+ if method == RPC.eth_getFilterChanges:
685
+ return _simulate_rpc_response_with_result(
686
+ await _filter.filter_changes.__anext__() # type: ignore
687
+ )
688
+
689
+ elif method == RPC.eth_getFilterLogs:
690
+ # type ignored b/c logic prevents RequestBlocks which
691
+ # doesn't implement get_logs
692
+ return _simulate_rpc_response_with_result(
693
+ await _filter.get_logs() # type: ignore
694
+ )
695
+ else:
696
+ raise NotImplementedError(method)
655
697
  else:
656
- raise NotImplementedError(method)
657
- else:
658
- return await make_request(method, params)
698
+ return await make_request(method, params)
659
699
 
660
- return middleware
700
+ return middleware