web3 7.0.0b2__py3-none-any.whl → 7.7.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 (144) hide show
  1. ens/__init__.py +13 -2
  2. ens/_normalization.py +4 -4
  3. ens/async_ens.py +27 -15
  4. ens/base_ens.py +3 -1
  5. ens/contract_data.py +2 -2
  6. ens/ens.py +10 -7
  7. ens/exceptions.py +16 -29
  8. ens/specs/nf.json +1 -1
  9. ens/specs/normalization_spec.json +1 -1
  10. ens/utils.py +24 -32
  11. web3/__init__.py +23 -12
  12. web3/_utils/abi.py +157 -263
  13. web3/_utils/async_transactions.py +34 -20
  14. web3/_utils/batching.py +217 -0
  15. web3/_utils/blocks.py +6 -2
  16. web3/_utils/caching/__init__.py +12 -0
  17. web3/_utils/caching/caching_utils.py +433 -0
  18. web3/_utils/caching/request_caching_validation.py +287 -0
  19. web3/_utils/compat/__init__.py +2 -3
  20. web3/_utils/contract_sources/compile_contracts.py +1 -1
  21. web3/_utils/contract_sources/contract_data/ambiguous_function_contract.py +42 -0
  22. web3/_utils/contract_sources/contract_data/arrays_contract.py +3 -3
  23. web3/_utils/contract_sources/contract_data/bytes_contracts.py +5 -5
  24. web3/_utils/contract_sources/contract_data/constructor_contracts.py +7 -7
  25. web3/_utils/contract_sources/contract_data/contract_caller_tester.py +3 -3
  26. web3/_utils/contract_sources/contract_data/emitter_contract.py +3 -3
  27. web3/_utils/contract_sources/contract_data/event_contracts.py +50 -5
  28. web3/_utils/contract_sources/contract_data/extended_resolver.py +3 -3
  29. web3/_utils/contract_sources/contract_data/fallback_function_contract.py +3 -3
  30. web3/_utils/contract_sources/contract_data/function_name_tester_contract.py +3 -3
  31. web3/_utils/contract_sources/contract_data/math_contract.py +3 -3
  32. web3/_utils/contract_sources/contract_data/offchain_lookup.py +3 -3
  33. web3/_utils/contract_sources/contract_data/offchain_resolver.py +3 -3
  34. web3/_utils/contract_sources/contract_data/panic_errors_contract.py +3 -3
  35. web3/_utils/contract_sources/contract_data/payable_tester.py +3 -3
  36. web3/_utils/contract_sources/contract_data/receive_function_contracts.py +5 -5
  37. web3/_utils/contract_sources/contract_data/reflector_contracts.py +3 -3
  38. web3/_utils/contract_sources/contract_data/revert_contract.py +3 -3
  39. web3/_utils/contract_sources/contract_data/simple_resolver.py +3 -3
  40. web3/_utils/contract_sources/contract_data/storage_contract.py +3 -3
  41. web3/_utils/contract_sources/contract_data/string_contract.py +3 -3
  42. web3/_utils/contract_sources/contract_data/tuple_contracts.py +5 -5
  43. web3/_utils/contracts.py +172 -220
  44. web3/_utils/datatypes.py +5 -1
  45. web3/_utils/decorators.py +6 -1
  46. web3/_utils/empty.py +1 -1
  47. web3/_utils/encoding.py +16 -12
  48. web3/_utils/error_formatters_utils.py +5 -3
  49. web3/_utils/events.py +78 -72
  50. web3/_utils/fee_utils.py +1 -3
  51. web3/_utils/filters.py +24 -22
  52. web3/_utils/formatters.py +2 -2
  53. web3/_utils/http.py +8 -2
  54. web3/_utils/http_session_manager.py +314 -0
  55. web3/_utils/math.py +14 -15
  56. web3/_utils/method_formatters.py +161 -34
  57. web3/_utils/module.py +2 -1
  58. web3/_utils/module_testing/__init__.py +3 -2
  59. web3/_utils/module_testing/eth_module.py +736 -583
  60. web3/_utils/module_testing/go_ethereum_debug_module.py +128 -0
  61. web3/_utils/module_testing/module_testing_utils.py +81 -24
  62. web3/_utils/module_testing/persistent_connection_provider.py +702 -220
  63. web3/_utils/module_testing/utils.py +114 -33
  64. web3/_utils/module_testing/web3_module.py +438 -17
  65. web3/_utils/normalizers.py +13 -11
  66. web3/_utils/rpc_abi.py +10 -22
  67. web3/_utils/threads.py +8 -7
  68. web3/_utils/transactions.py +32 -25
  69. web3/_utils/type_conversion.py +5 -1
  70. web3/_utils/validation.py +20 -17
  71. web3/beacon/__init__.py +5 -0
  72. web3/beacon/api_endpoints.py +3 -0
  73. web3/beacon/async_beacon.py +29 -6
  74. web3/beacon/beacon.py +24 -6
  75. web3/contract/__init__.py +7 -0
  76. web3/contract/async_contract.py +285 -82
  77. web3/contract/base_contract.py +556 -258
  78. web3/contract/contract.py +295 -84
  79. web3/contract/utils.py +251 -55
  80. web3/datastructures.py +49 -34
  81. web3/eth/__init__.py +7 -0
  82. web3/eth/async_eth.py +89 -69
  83. web3/eth/base_eth.py +7 -3
  84. web3/eth/eth.py +43 -66
  85. web3/exceptions.py +158 -83
  86. web3/gas_strategies/time_based.py +8 -6
  87. web3/geth.py +53 -184
  88. web3/main.py +77 -17
  89. web3/manager.py +362 -95
  90. web3/method.py +43 -15
  91. web3/middleware/__init__.py +17 -0
  92. web3/middleware/attrdict.py +12 -22
  93. web3/middleware/base.py +55 -2
  94. web3/middleware/filter.py +45 -23
  95. web3/middleware/formatting.py +6 -3
  96. web3/middleware/names.py +4 -1
  97. web3/middleware/signing.py +15 -6
  98. web3/middleware/stalecheck.py +2 -1
  99. web3/module.py +61 -25
  100. web3/providers/__init__.py +21 -0
  101. web3/providers/async_base.py +87 -32
  102. web3/providers/base.py +77 -32
  103. web3/providers/eth_tester/__init__.py +5 -0
  104. web3/providers/eth_tester/defaults.py +2 -55
  105. web3/providers/eth_tester/main.py +41 -15
  106. web3/providers/eth_tester/middleware.py +16 -17
  107. web3/providers/ipc.py +41 -17
  108. web3/providers/legacy_websocket.py +26 -1
  109. web3/providers/persistent/__init__.py +7 -0
  110. web3/providers/persistent/async_ipc.py +61 -121
  111. web3/providers/persistent/persistent.py +323 -16
  112. web3/providers/persistent/persistent_connection.py +54 -5
  113. web3/providers/persistent/request_processor.py +136 -56
  114. web3/providers/persistent/subscription_container.py +56 -0
  115. web3/providers/persistent/subscription_manager.py +233 -0
  116. web3/providers/persistent/websocket.py +29 -92
  117. web3/providers/rpc/__init__.py +5 -0
  118. web3/providers/rpc/async_rpc.py +73 -18
  119. web3/providers/rpc/rpc.py +73 -30
  120. web3/providers/rpc/utils.py +1 -13
  121. web3/scripts/install_pre_releases.py +33 -0
  122. web3/scripts/parse_pygeth_version.py +16 -0
  123. web3/testing.py +4 -4
  124. web3/tracing.py +9 -5
  125. web3/types.py +141 -74
  126. web3/utils/__init__.py +64 -5
  127. web3/utils/abi.py +790 -10
  128. web3/utils/address.py +8 -0
  129. web3/utils/async_exception_handling.py +20 -11
  130. web3/utils/caching.py +34 -4
  131. web3/utils/exception_handling.py +9 -12
  132. web3/utils/subscriptions.py +285 -0
  133. {web3-7.0.0b2.dist-info → web3-7.7.0.dist-info}/LICENSE +1 -1
  134. web3-7.7.0.dist-info/METADATA +130 -0
  135. web3-7.7.0.dist-info/RECORD +171 -0
  136. {web3-7.0.0b2.dist-info → web3-7.7.0.dist-info}/WHEEL +1 -1
  137. web3/_utils/caching.py +0 -155
  138. web3/_utils/contract_sources/contract_data/address_reflector.py +0 -29
  139. web3/_utils/module_testing/go_ethereum_personal_module.py +0 -300
  140. web3/_utils/request.py +0 -265
  141. web3-7.0.0b2.dist-info/METADATA +0 -106
  142. web3-7.0.0b2.dist-info/RECORD +0 -163
  143. /web3/_utils/{function_identifiers.py → abi_element_identifiers.py} +0 -0
  144. {web3-7.0.0b2.dist-info → web3-7.7.0.dist-info}/top_level.txt +0 -0
web3/method.py CHANGED
@@ -10,7 +10,6 @@ from typing import (
10
10
  Sequence,
11
11
  Tuple,
12
12
  Type,
13
- TypeVar,
14
13
  Union,
15
14
  )
16
15
  import warnings
@@ -22,6 +21,9 @@ from eth_utils.toolz import (
22
21
  pipe,
23
22
  )
24
23
 
24
+ from web3._utils.batching import (
25
+ RPC_METHODS_UNSUPPORTED_DURING_BATCH,
26
+ )
25
27
  from web3._utils.method_formatters import (
26
28
  get_error_formatters,
27
29
  get_null_result_formatters,
@@ -32,15 +34,22 @@ from web3._utils.rpc_abi import (
32
34
  RPC,
33
35
  )
34
36
  from web3.exceptions import (
37
+ MethodNotSupported,
38
+ Web3TypeError,
35
39
  Web3ValidationError,
40
+ Web3ValueError,
36
41
  )
37
42
  from web3.types import (
38
43
  RPCEndpoint,
44
+ TFunc,
39
45
  TReturn,
40
46
  )
41
47
 
42
48
  if TYPE_CHECKING:
43
- from web3 import Web3 # noqa: F401
49
+ from web3 import ( # noqa: F401
50
+ PersistentConnectionProvider,
51
+ Web3,
52
+ )
44
53
  from web3.module import Module # noqa: F401
45
54
 
46
55
 
@@ -66,7 +75,9 @@ def _set_mungers(
66
75
  return (
67
76
  mungers
68
77
  if mungers
69
- else [default_munger] if is_property else [default_root_munger]
78
+ else [default_munger]
79
+ if is_property
80
+ else [default_root_munger]
70
81
  )
71
82
 
72
83
 
@@ -80,11 +91,9 @@ def default_root_munger(_module: "Module", *args: Any) -> List[Any]:
80
91
  return [*args]
81
92
 
82
93
 
83
- TFunc = TypeVar("TFunc", bound=Callable[..., Any])
84
-
85
-
86
94
  class Method(Generic[TFunc]):
87
- """Method object for web3 module methods
95
+ """
96
+ Method object for web3 module methods
88
97
 
89
98
  Calls to the Method go through these steps:
90
99
 
@@ -144,15 +153,31 @@ class Method(Generic[TFunc]):
144
153
  self.is_property = is_property
145
154
 
146
155
  def __get__(
147
- self, obj: Optional["Module"] = None, obj_type: Optional[Type["Module"]] = None
156
+ self,
157
+ module: Optional["Module"] = None,
158
+ _type: Optional[Type["Module"]] = None,
148
159
  ) -> TFunc:
149
- if obj is None:
150
- raise TypeError(
160
+ self._module = module
161
+ if module is None:
162
+ raise Web3TypeError(
151
163
  "Direct calls to methods are not supported. "
152
- "Methods must be called from an module instance, "
164
+ "Methods must be called from a module instance, "
153
165
  "usually attached to a web3 instance."
154
166
  )
155
- return obj.retrieve_caller_fn(self)
167
+
168
+ provider = module.w3.provider
169
+ if hasattr(provider, "_is_batching") and provider._is_batching:
170
+ if self.json_rpc_method in RPC_METHODS_UNSUPPORTED_DURING_BATCH:
171
+ raise MethodNotSupported(
172
+ f"Method `{self.json_rpc_method}` is not supported within a batch "
173
+ "request."
174
+ )
175
+ return module.retrieve_request_information(self)
176
+ else:
177
+ return module.retrieve_caller_fn(self)
178
+
179
+ def __call__(self, *args: Any, **kwargs: Any) -> Any:
180
+ return self.__get__(self._module)(*args, **kwargs)
156
181
 
157
182
  @property
158
183
  def method_selector_fn(
@@ -163,7 +188,7 @@ class Method(Generic[TFunc]):
163
188
  return self.json_rpc_method
164
189
  elif isinstance(self.json_rpc_method, (str,)):
165
190
  return lambda *_: self.json_rpc_method
166
- raise ValueError(
191
+ raise Web3ValueError(
167
192
  "``json_rpc_method`` config invalid. May be a string or function"
168
193
  )
169
194
 
@@ -175,8 +200,10 @@ class Method(Generic[TFunc]):
175
200
  lambda args, munger: munger(module, *args, **kwargs), self.mungers, args
176
201
  )
177
202
 
178
- def process_params(self, module: "Module", *args: Any, **kwargs: Any) -> Tuple[
179
- Tuple[Union[RPCEndpoint, Callable[..., RPCEndpoint]], Tuple[Any, ...]],
203
+ def process_params(
204
+ self, module: "Module", *args: Any, **kwargs: Any
205
+ ) -> Tuple[
206
+ Tuple[Union[RPCEndpoint, Callable[..., RPCEndpoint]], Tuple[RPCEndpoint, ...]],
180
207
  Tuple[
181
208
  Union[TReturn, Dict[str, Callable[..., Any]]],
182
209
  Callable[..., Any],
@@ -226,5 +253,6 @@ class DeprecatedMethod:
226
253
  warnings.warn(
227
254
  f"{self.old_name} is deprecated in favor of {self.new_name}",
228
255
  category=DeprecationWarning,
256
+ stacklevel=2,
229
257
  )
230
258
  return self.method.__get__(obj, obj_type)
@@ -92,3 +92,20 @@ async def async_combine_middleware(
92
92
  initialized = mw(async_w3)
93
93
  accumulator_fn = await initialized.async_wrap_make_request(accumulator_fn)
94
94
  return accumulator_fn
95
+
96
+
97
+ __all__ = [
98
+ "AttributeDictMiddleware",
99
+ "Middleware",
100
+ "Web3Middleware",
101
+ "BufferedGasEstimateMiddleware",
102
+ "LocalFilterMiddleware",
103
+ "FormattingMiddlewareBuilder",
104
+ "GasPriceStrategyMiddleware",
105
+ "ENSNameToAddressMiddleware",
106
+ "ExtraDataToPOAMiddleware",
107
+ "PythonicMiddleware",
108
+ "SignAndSendRawMiddlewareBuilder",
109
+ "StalecheckMiddlewareBuilder",
110
+ "ValidationMiddleware",
111
+ ]
@@ -7,10 +7,6 @@ from typing import (
7
7
  cast,
8
8
  )
9
9
 
10
- from eth_utils.toolz import (
11
- assoc,
12
- )
13
-
14
10
  from web3.datastructures import (
15
11
  AttributeDict,
16
12
  )
@@ -33,21 +29,18 @@ if TYPE_CHECKING:
33
29
 
34
30
 
35
31
  def _handle_async_response(response: "RPCResponse") -> "RPCResponse":
32
+ """
33
+ Process the RPC response by converting nested dictionaries into AttributeDict.
34
+ """
36
35
  if "result" in response:
37
- return assoc(response, "result", AttributeDict.recursive(response["result"]))
36
+ response["result"] = AttributeDict.recursive(response["result"])
38
37
  elif "params" in response and "result" in response["params"]:
39
- # this is a subscription response
40
- return assoc(
41
- response,
42
- "params",
43
- assoc(
44
- response["params"],
45
- "result",
46
- AttributeDict.recursive(response["params"]["result"]),
47
- ),
38
+ # subscription response
39
+ response["params"]["result"] = AttributeDict.recursive(
40
+ response["params"]["result"]
48
41
  )
49
- else:
50
- return response
42
+
43
+ return response
51
44
 
52
45
 
53
46
  class AttributeDictMiddleware(Web3Middleware, ABC):
@@ -60,11 +53,9 @@ class AttributeDictMiddleware(Web3Middleware, ABC):
60
53
 
61
54
  def response_processor(self, method: "RPCEndpoint", response: "RPCResponse") -> Any:
62
55
  if "result" in response:
63
- return assoc(
64
- response, "result", AttributeDict.recursive(response["result"])
65
- )
66
- else:
67
- return response
56
+ new_result = AttributeDict.recursive(response["result"])
57
+ response = {**response, "result": new_result}
58
+ return response
68
59
 
69
60
  # -- async -- #
70
61
 
@@ -72,7 +63,6 @@ class AttributeDictMiddleware(Web3Middleware, ABC):
72
63
  self, method: "RPCEndpoint", response: "RPCResponse"
73
64
  ) -> Any:
74
65
  if self._w3.provider.has_persistent_connection:
75
- # asynchronous response processing
76
66
  provider = cast("PersistentConnectionProvider", self._w3.provider)
77
67
  provider._request_processor.append_middleware_response_processor(
78
68
  response, _handle_async_response
web3/middleware/base.py CHANGED
@@ -4,6 +4,8 @@ from abc import (
4
4
  from typing import (
5
5
  TYPE_CHECKING,
6
6
  Any,
7
+ List,
8
+ Tuple,
7
9
  Type,
8
10
  Union,
9
11
  )
@@ -18,7 +20,9 @@ if TYPE_CHECKING:
18
20
  Web3,
19
21
  )
20
22
  from web3.types import ( # noqa: F401
23
+ AsyncMakeBatchRequestFn,
21
24
  AsyncMakeRequestFn,
25
+ MakeBatchRequestFn,
22
26
  MakeRequestFn,
23
27
  RPCEndpoint,
24
28
  RPCResponse,
@@ -36,6 +40,14 @@ class Web3Middleware:
36
40
  def __init__(self, w3: Union["AsyncWeb3", "Web3"]) -> None:
37
41
  self._w3 = w3
38
42
 
43
+ def __hash__(self) -> int:
44
+ return hash(f"{self.__class__.__name__}({str(self.__dict__)})")
45
+
46
+ def __eq__(self, other: Any) -> bool:
47
+ if not isinstance(other, Web3Middleware):
48
+ return False
49
+ return self.__hash__() == other.__hash__()
50
+
39
51
  # -- sync -- #
40
52
 
41
53
  def wrap_make_request(self, make_request: "MakeRequestFn") -> "MakeRequestFn":
@@ -45,10 +57,31 @@ class Web3Middleware:
45
57
 
46
58
  return middleware
47
59
 
60
+ def wrap_make_batch_request(
61
+ self, make_batch_request: "MakeBatchRequestFn"
62
+ ) -> "MakeBatchRequestFn":
63
+ def middleware(
64
+ requests_info: List[Tuple["RPCEndpoint", Any]]
65
+ ) -> List["RPCResponse"]:
66
+ req_processed = [
67
+ self.request_processor(method, params)
68
+ for (method, params) in requests_info
69
+ ]
70
+ responses = make_batch_request(req_processed)
71
+ methods, _params = zip(*req_processed)
72
+ formatted_responses = [
73
+ self.response_processor(m, r) for m, r in zip(methods, responses)
74
+ ]
75
+ return formatted_responses
76
+
77
+ return middleware
78
+
48
79
  def request_processor(self, method: "RPCEndpoint", params: Any) -> Any:
49
80
  return method, params
50
81
 
51
- def response_processor(self, method: "RPCEndpoint", response: "RPCResponse") -> Any:
82
+ def response_processor(
83
+ self, method: "RPCEndpoint", response: "RPCResponse"
84
+ ) -> "RPCResponse":
52
85
  return response
53
86
 
54
87
  # -- async -- #
@@ -65,6 +98,26 @@ class Web3Middleware:
65
98
 
66
99
  return middleware
67
100
 
101
+ async def async_wrap_make_batch_request(
102
+ self, make_batch_request: "AsyncMakeBatchRequestFn"
103
+ ) -> "AsyncMakeBatchRequestFn":
104
+ async def middleware(
105
+ requests_info: List[Tuple["RPCEndpoint", Any]]
106
+ ) -> List["RPCResponse"]:
107
+ req_processed = [
108
+ await self.async_request_processor(method, params)
109
+ for (method, params) in requests_info
110
+ ]
111
+ responses = await make_batch_request(req_processed)
112
+ methods, _params = zip(*req_processed)
113
+ formatted_responses = [
114
+ await self.async_response_processor(m, r)
115
+ for m, r in zip(methods, responses)
116
+ ]
117
+ return formatted_responses
118
+
119
+ return middleware
120
+
68
121
  async def async_request_processor(
69
122
  self,
70
123
  method: "RPCEndpoint",
@@ -76,7 +129,7 @@ class Web3Middleware:
76
129
  self,
77
130
  method: "RPCEndpoint",
78
131
  response: "RPCResponse",
79
- ) -> Any:
132
+ ) -> "RPCResponse":
80
133
  return response
81
134
 
82
135
 
web3/middleware/filter.py CHANGED
@@ -42,6 +42,9 @@ from web3._utils.formatters import (
42
42
  from web3._utils.rpc_abi import (
43
43
  RPC,
44
44
  )
45
+ from web3.exceptions import (
46
+ Web3TypeError,
47
+ )
45
48
  from web3.middleware.base import (
46
49
  Web3Middleware,
47
50
  )
@@ -71,7 +74,8 @@ else:
71
74
 
72
75
 
73
76
  def segment_count(start: int, stop: int, step: int = 5) -> Iterable[Tuple[int, int]]:
74
- """Creates a segment counting generator
77
+ """
78
+ Creates a segment counting generator
75
79
 
76
80
  The generator returns tuple pairs of integers
77
81
  that correspond to segments in the provided range.
@@ -84,6 +88,7 @@ def segment_count(start: int, stop: int, step: int = 5) -> Iterable[Tuple[int, i
84
88
 
85
89
 
86
90
  Example:
91
+ -------
87
92
 
88
93
  >>> segment_counter = segment_count(start=0, stop=10, step=3)
89
94
  >>> next(segment_counter)
@@ -94,6 +99,7 @@ def segment_count(start: int, stop: int, step: int = 5) -> Iterable[Tuple[int, i
94
99
  (6, 9)
95
100
  >>> next(segment_counter) # Remainder is also returned
96
101
  (9, 10)
102
+
97
103
  """
98
104
  return gen_bounded_segments(start, stop, step)
99
105
 
@@ -104,10 +110,9 @@ def gen_bounded_segments(start: int, stop: int, step: int) -> Iterable[Tuple[int
104
110
  if start + step >= stop:
105
111
  yield (start, stop)
106
112
  return
107
- for segment in zip(
113
+ yield from zip(
108
114
  range(start, stop - step + 1, step), range(start + step, stop + 1, step)
109
- ):
110
- yield segment
115
+ )
111
116
 
112
117
  remainder = (stop - start) % step
113
118
  # Handle the remainder
@@ -118,13 +123,14 @@ def gen_bounded_segments(start: int, stop: int, step: int) -> Iterable[Tuple[int
118
123
  def block_ranges(
119
124
  start_block: BlockNumber, last_block: Optional[BlockNumber], step: int = 5
120
125
  ) -> Iterable[Tuple[BlockNumber, BlockNumber]]:
121
- """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
122
128
 
123
129
  Ranges do not overlap to facilitate use as ``toBlock``, ``fromBlock``
124
130
  json-rpc arguments, which are both inclusive.
125
131
  """
126
132
  if last_block is not None and start_block > last_block:
127
- raise TypeError(
133
+ raise Web3TypeError(
128
134
  "Incompatible start and stop arguments.",
129
135
  "Start must be less than or equal to stop.",
130
136
  )
@@ -138,7 +144,8 @@ def block_ranges(
138
144
  def iter_latest_block(
139
145
  w3: "Web3", to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None
140
146
  ) -> Iterable[BlockNumber]:
141
- """Returns a generator that dispenses the latest block, if
147
+ """
148
+ Returns a generator that dispenses the latest block, if
142
149
  any new blocks have been mined since last iteration.
143
150
 
144
151
  If there are no new blocks or the latest block is greater than
@@ -160,8 +167,7 @@ def iter_latest_block(
160
167
 
161
168
  while True:
162
169
  latest_block = w3.eth.block_number
163
- # type ignored b/c is_bounded_range prevents unsupported comparison
164
- if is_bounded_range and latest_block > to_block: # type: ignore
170
+ if is_bounded_range and latest_block > cast(BlockNumber, to_block):
165
171
  yield None
166
172
  # No new blocks since last iteration.
167
173
  if _last is not None and _last == latest_block:
@@ -176,7 +182,8 @@ def iter_latest_block_ranges(
176
182
  from_block: BlockNumber,
177
183
  to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None,
178
184
  ) -> Iterable[Tuple[Optional[BlockNumber], Optional[BlockNumber]]]:
179
- """Returns an iterator unloading ranges of available blocks
185
+ """
186
+ Returns an iterator unloading ranges of available blocks
180
187
 
181
188
  starting from `fromBlock` to the latest mined block,
182
189
  until reaching toBlock. e.g.:
@@ -212,7 +219,8 @@ def get_logs_multipart(
212
219
  topics: List[Optional[Union[_Hash32, List[_Hash32]]]],
213
220
  max_blocks: int,
214
221
  ) -> Iterable[List[LogReceipt]]:
215
- """Used to break up requests to ``eth_getLogs``
222
+ """
223
+ Used to break up requests to ``eth_getLogs``
216
224
 
217
225
  The getLog request is partitioned into multiple calls of the max number of blocks
218
226
  ``max_blocks``.
@@ -247,9 +255,8 @@ class RequestLogs:
247
255
  if from_block is None or from_block == "latest":
248
256
  self._from_block = BlockNumber(w3.eth.block_number + 1)
249
257
  elif is_string(from_block) and is_hex(from_block):
250
- self._from_block = BlockNumber(hex_to_integer(from_block)) # type: ignore
258
+ self._from_block = BlockNumber(hex_to_integer(cast(HexStr, from_block)))
251
259
  else:
252
- # cast b/c LatestBlockParam is handled above
253
260
  self._from_block = from_block
254
261
  self._to_block = to_block
255
262
  self.filter_changes = self._get_filter_changes()
@@ -265,7 +272,7 @@ class RequestLogs:
265
272
  elif self._to_block == "latest":
266
273
  to_block = self.w3.eth.block_number
267
274
  elif is_string(self._to_block) and is_hex(self._to_block):
268
- to_block = BlockNumber(hex_to_integer(self._to_block)) # type: ignore
275
+ to_block = BlockNumber(hex_to_integer(cast(HexStr, self._to_block)))
269
276
  else:
270
277
  to_block = self._to_block
271
278
 
@@ -352,7 +359,8 @@ def block_hashes_in_range(
352
359
  async def async_iter_latest_block(
353
360
  w3: "AsyncWeb3", to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None
354
361
  ) -> AsyncIterable[BlockNumber]:
355
- """Returns a generator that dispenses the latest block, if
362
+ """
363
+ Returns a generator that dispenses the latest block, if
356
364
  any new blocks have been mined since last iteration.
357
365
 
358
366
  If there are no new blocks or the latest block is greater than
@@ -390,7 +398,8 @@ async def async_iter_latest_block_ranges(
390
398
  from_block: BlockNumber,
391
399
  to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None,
392
400
  ) -> AsyncIterable[Tuple[Optional[BlockNumber], Optional[BlockNumber]]]:
393
- """Returns an iterator unloading ranges of available blocks
401
+ """
402
+ Returns an iterator unloading ranges of available blocks
394
403
 
395
404
  starting from `from_block` to the latest mined block,
396
405
  until reaching to_block. e.g.:
@@ -423,7 +432,8 @@ async def async_get_logs_multipart(
423
432
  topics: List[Optional[Union[_Hash32, List[_Hash32]]]],
424
433
  max_blocks: int,
425
434
  ) -> AsyncIterable[List[LogReceipt]]:
426
- """Used to break up requests to ``eth_getLogs``
435
+ """
436
+ Used to break up requests to ``eth_getLogs``
427
437
 
428
438
  The getLog request is partitioned into multiple calls of the max number of blocks
429
439
  ``max_blocks``.
@@ -579,6 +589,10 @@ SyncFilter = Union[RequestLogs, RequestBlocks]
579
589
  AsyncFilter = Union[AsyncRequestLogs, AsyncRequestBlocks]
580
590
 
581
591
 
592
+ def _simulate_rpc_response_with_result(filter_id: str) -> "RPCResponse":
593
+ return {"jsonrpc": "2.0", "id": -1, "result": filter_id}
594
+
595
+
582
596
  class LocalFilterMiddleware(Web3Middleware):
583
597
  def __init__(self, w3: Union["Web3", "AsyncWeb3"]):
584
598
  self.filters: Dict[str, SyncFilter] = {}
@@ -605,7 +619,7 @@ class LocalFilterMiddleware(Web3Middleware):
605
619
  raise NotImplementedError(method)
606
620
 
607
621
  self.filters[filter_id] = _filter
608
- return {"result": filter_id}
622
+ return _simulate_rpc_response_with_result(filter_id)
609
623
 
610
624
  elif method in FILTER_CHANGES_METHODS:
611
625
  _filter_id = params[0]
@@ -616,12 +630,16 @@ class LocalFilterMiddleware(Web3Middleware):
616
630
 
617
631
  _filter = self.filters[_filter_id]
618
632
  if method == RPC.eth_getFilterChanges:
619
- return {"result": next(_filter.filter_changes)}
633
+ return _simulate_rpc_response_with_result(
634
+ next(_filter.filter_changes) # type: ignore
635
+ )
620
636
 
621
637
  elif method == RPC.eth_getFilterLogs:
622
638
  # type ignored b/c logic prevents RequestBlocks which
623
639
  # doesn't implement get_logs
624
- return {"result": _filter.get_logs()} # type: ignore
640
+ return _simulate_rpc_response_with_result(
641
+ _filter.get_logs() # type: ignore
642
+ )
625
643
  else:
626
644
  raise NotImplementedError(method)
627
645
  else:
@@ -653,7 +671,7 @@ class LocalFilterMiddleware(Web3Middleware):
653
671
  raise NotImplementedError(method)
654
672
 
655
673
  self.async_filters[filter_id] = _filter
656
- return {"result": filter_id}
674
+ return _simulate_rpc_response_with_result(filter_id)
657
675
 
658
676
  elif method in FILTER_CHANGES_METHODS:
659
677
  _filter_id = params[0]
@@ -664,12 +682,16 @@ class LocalFilterMiddleware(Web3Middleware):
664
682
 
665
683
  _filter = self.async_filters[_filter_id]
666
684
  if method == RPC.eth_getFilterChanges:
667
- return {"result": await _filter.filter_changes.__anext__()}
685
+ return _simulate_rpc_response_with_result(
686
+ await _filter.filter_changes.__anext__() # type: ignore
687
+ )
668
688
 
669
689
  elif method == RPC.eth_getFilterLogs:
670
690
  # type ignored b/c logic prevents RequestBlocks which
671
691
  # doesn't implement get_logs
672
- return {"result": await _filter.get_logs()} # type: ignore
692
+ return _simulate_rpc_response_with_result(
693
+ await _filter.get_logs() # type: ignore
694
+ )
673
695
  else:
674
696
  raise NotImplementedError(method)
675
697
  else:
@@ -3,6 +3,7 @@ from typing import (
3
3
  Any,
4
4
  Callable,
5
5
  Coroutine,
6
+ Literal,
6
7
  Optional,
7
8
  Union,
8
9
  cast,
@@ -14,6 +15,9 @@ from eth_utils.toolz import (
14
15
  merge,
15
16
  )
16
17
 
18
+ from web3.exceptions import (
19
+ Web3ValueError,
20
+ )
17
21
  from web3.middleware.base import (
18
22
  Web3MiddlewareBuilder,
19
23
  )
@@ -21,7 +25,6 @@ from web3.types import (
21
25
  EthSubscriptionParams,
22
26
  Formatters,
23
27
  FormattersDict,
24
- Literal,
25
28
  RPCEndpoint,
26
29
  RPCResponse,
27
30
  )
@@ -118,7 +121,7 @@ class FormattingMiddlewareBuilder(Web3MiddlewareBuilder):
118
121
  if (
119
122
  sync_formatters_builder is None and async_formatters_builder is not None
120
123
  ) or (sync_formatters_builder is not None and async_formatters_builder is None):
121
- raise ValueError(
124
+ raise Web3ValueError(
122
125
  "Must specify both sync_formatters_builder and async_formatters_builder"
123
126
  )
124
127
 
@@ -128,7 +131,7 @@ class FormattingMiddlewareBuilder(Web3MiddlewareBuilder):
128
131
  or result_formatters is not None
129
132
  or error_formatters is not None
130
133
  ):
131
- raise ValueError(
134
+ raise Web3ValueError(
132
135
  "Cannot specify formatters_builder and formatters at the same time"
133
136
  )
134
137
 
web3/middleware/names.py CHANGED
@@ -31,6 +31,9 @@ from .._utils.abi import (
31
31
  from .._utils.formatters import (
32
32
  recursive_map,
33
33
  )
34
+ from ..exceptions import (
35
+ Web3TypeError,
36
+ )
34
37
  from .base import (
35
38
  Web3Middleware,
36
39
  )
@@ -92,7 +95,7 @@ async def async_apply_ens_to_address_conversion(
92
95
  return (formatted_params_dict, *params[1:])
93
96
 
94
97
  else:
95
- raise TypeError(
98
+ raise Web3TypeError(
96
99
  f"ABI definitions must be a list or dictionary, "
97
100
  f"got {abi_types_for_method!r}"
98
101
  )
@@ -19,6 +19,9 @@ from eth_account import (
19
19
  from eth_account.signers.local import (
20
20
  LocalAccount,
21
21
  )
22
+ from eth_account.types import (
23
+ TransactionDictType as EthAccountTxParams,
24
+ )
22
25
  from eth_keys.datatypes import (
23
26
  PrivateKey,
24
27
  )
@@ -55,6 +58,9 @@ from web3._utils.transactions import (
55
58
  fill_nonce,
56
59
  fill_transaction_defaults,
57
60
  )
61
+ from web3.exceptions import (
62
+ Web3TypeError,
63
+ )
58
64
  from web3.middleware.base import (
59
65
  Web3MiddlewareBuilder,
60
66
  )
@@ -108,7 +114,7 @@ def gen_normalized_accounts(
108
114
 
109
115
  @singledispatch
110
116
  def to_account(val: Any) -> LocalAccount:
111
- raise TypeError(
117
+ raise Web3TypeError(
112
118
  "key must be one of the types: "
113
119
  "eth_keys.datatype.PrivateKey, eth_account.signers.local.LocalAccount, "
114
120
  "or raw private key as a hex string or byte string. "
@@ -132,7 +138,8 @@ to_account.register(bytes, private_key_to_account)
132
138
 
133
139
 
134
140
  def format_transaction(transaction: TxParams) -> TxParams:
135
- """Format transaction so that it can be used correctly in the signing middleware.
141
+ """
142
+ Format transaction so that it can be used correctly in the signing middleware.
136
143
 
137
144
  Converts bytes to hex strings and other types that can be passed to
138
145
  the underlying layers. Also has the effect of normalizing 'from' for
@@ -178,11 +185,11 @@ class SignAndSendRawMiddlewareBuilder(Web3MiddlewareBuilder):
178
185
  return method, params
179
186
  else:
180
187
  account = self._accounts[to_checksum_address(tx_from)]
181
- raw_tx = account.sign_transaction(filled_transaction).rawTransaction
188
+ raw_tx = account.sign_transaction(filled_transaction).raw_transaction
182
189
 
183
190
  return (
184
191
  RPCEndpoint("eth_sendRawTransaction"),
185
- [raw_tx.hex()],
192
+ [raw_tx.to_0x_hex()],
186
193
  )
187
194
 
188
195
  # -- async -- #
@@ -207,9 +214,11 @@ class SignAndSendRawMiddlewareBuilder(Web3MiddlewareBuilder):
207
214
  return method, params
208
215
  else:
209
216
  account = self._accounts[to_checksum_address(tx_from)]
210
- raw_tx = account.sign_transaction(filled_transaction).rawTransaction
217
+ raw_tx = account.sign_transaction(
218
+ cast(EthAccountTxParams, filled_transaction)
219
+ ).raw_transaction
211
220
 
212
221
  return (
213
222
  RPCEndpoint("eth_sendRawTransaction"),
214
- [raw_tx.hex()],
223
+ [raw_tx.to_0x_hex()],
215
224
  )
@@ -16,6 +16,7 @@ from toolz import (
16
16
 
17
17
  from web3.exceptions import (
18
18
  StaleBlockchain,
19
+ Web3ValueError,
19
20
  )
20
21
  from web3.middleware.base import (
21
22
  Web3Middleware,
@@ -54,7 +55,7 @@ class StalecheckMiddlewareBuilder(Web3MiddlewareBuilder):
54
55
  skip_stalecheck_for_methods: Collection[str] = SKIP_STALECHECK_FOR_METHODS,
55
56
  ) -> Web3Middleware:
56
57
  if allowable_delay <= 0:
57
- raise ValueError(
58
+ raise Web3ValueError(
58
59
  "You must set a positive allowable_delay in seconds for this middleware"
59
60
  )
60
61
  middleware = StalecheckMiddlewareBuilder(w3)