web3 7.0.0b4__py3-none-any.whl → 7.0.0b6__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 (50) hide show
  1. web3/_utils/batching.py +217 -0
  2. web3/_utils/caching.py +26 -2
  3. web3/_utils/compat/__init__.py +1 -0
  4. web3/_utils/contracts.py +5 -5
  5. web3/_utils/events.py +20 -20
  6. web3/_utils/filters.py +6 -6
  7. web3/_utils/method_formatters.py +0 -23
  8. web3/_utils/module_testing/__init__.py +0 -3
  9. web3/_utils/module_testing/eth_module.py +442 -373
  10. web3/_utils/module_testing/module_testing_utils.py +13 -0
  11. web3/_utils/module_testing/web3_module.py +438 -17
  12. web3/_utils/rpc_abi.py +0 -18
  13. web3/contract/async_contract.py +11 -11
  14. web3/contract/base_contract.py +19 -18
  15. web3/contract/contract.py +13 -13
  16. web3/contract/utils.py +112 -4
  17. web3/eth/async_eth.py +10 -8
  18. web3/eth/eth.py +7 -6
  19. web3/exceptions.py +75 -21
  20. web3/gas_strategies/time_based.py +2 -2
  21. web3/geth.py +0 -188
  22. web3/main.py +21 -13
  23. web3/manager.py +237 -74
  24. web3/method.py +29 -9
  25. web3/middleware/base.py +43 -0
  26. web3/middleware/filter.py +18 -6
  27. web3/middleware/signing.py +2 -2
  28. web3/module.py +47 -7
  29. web3/providers/async_base.py +55 -23
  30. web3/providers/base.py +59 -26
  31. web3/providers/eth_tester/defaults.py +0 -48
  32. web3/providers/eth_tester/main.py +36 -11
  33. web3/providers/eth_tester/middleware.py +3 -8
  34. web3/providers/ipc.py +23 -8
  35. web3/providers/legacy_websocket.py +26 -1
  36. web3/providers/persistent/async_ipc.py +60 -76
  37. web3/providers/persistent/persistent.py +134 -10
  38. web3/providers/persistent/request_processor.py +98 -14
  39. web3/providers/persistent/websocket.py +43 -66
  40. web3/providers/rpc/async_rpc.py +20 -2
  41. web3/providers/rpc/rpc.py +22 -2
  42. web3/providers/rpc/utils.py +1 -10
  43. web3/tools/benchmark/node.py +2 -8
  44. web3/types.py +8 -2
  45. {web3-7.0.0b4.dist-info → web3-7.0.0b6.dist-info}/LICENSE +1 -1
  46. {web3-7.0.0b4.dist-info → web3-7.0.0b6.dist-info}/METADATA +32 -21
  47. {web3-7.0.0b4.dist-info → web3-7.0.0b6.dist-info}/RECORD +49 -49
  48. web3/_utils/module_testing/go_ethereum_personal_module.py +0 -300
  49. {web3-7.0.0b4.dist-info → web3-7.0.0b6.dist-info}/WHEEL +0 -0
  50. {web3-7.0.0b4.dist-info → web3-7.0.0b6.dist-info}/top_level.txt +0 -0
@@ -204,9 +204,9 @@ class BaseContractEvent:
204
204
  self,
205
205
  abi: ABIEvent,
206
206
  argument_filters: Optional[Dict[str, Any]] = None,
207
- fromBlock: Optional[BlockIdentifier] = None,
208
- toBlock: Optional[BlockIdentifier] = None,
209
- blockHash: Optional[HexBytes] = None,
207
+ from_block: Optional[BlockIdentifier] = None,
208
+ to_block: Optional[BlockIdentifier] = None,
209
+ block_hash: Optional[HexBytes] = None,
210
210
  ) -> FilterParams:
211
211
  if not self.address:
212
212
  raise Web3TypeError(
@@ -219,11 +219,12 @@ class BaseContractEvent:
219
219
 
220
220
  _filters = dict(**argument_filters)
221
221
 
222
- blkhash_set = blockHash is not None
223
- blknum_set = fromBlock is not None or toBlock is not None
222
+ blkhash_set = block_hash is not None
223
+ blknum_set = from_block is not None or to_block is not None
224
224
  if blkhash_set and blknum_set:
225
225
  raise Web3ValidationError(
226
- "blockHash cannot be set at the same time as fromBlock or toBlock"
226
+ "`block_hash` cannot be set at the same time as "
227
+ "`from_block` or `to_block`"
227
228
  )
228
229
 
229
230
  # Construct JSON-RPC raw filter presentation based on human readable
@@ -233,13 +234,13 @@ class BaseContractEvent:
233
234
  self.w3.codec,
234
235
  contract_address=self.address,
235
236
  argument_filters=_filters,
236
- fromBlock=fromBlock,
237
- toBlock=toBlock,
237
+ from_block=from_block,
238
+ to_block=to_block,
238
239
  address=self.address,
239
240
  )
240
241
 
241
- if blockHash is not None:
242
- event_filter_params["blockHash"] = blockHash
242
+ if block_hash is not None:
243
+ event_filter_params["blockHash"] = block_hash
243
244
 
244
245
  return event_filter_params
245
246
 
@@ -319,15 +320,15 @@ class BaseContractEvent:
319
320
  def _set_up_filter_builder(
320
321
  self,
321
322
  argument_filters: Optional[Dict[str, Any]] = None,
322
- fromBlock: Optional[BlockIdentifier] = None,
323
- toBlock: BlockIdentifier = "latest",
323
+ from_block: Optional[BlockIdentifier] = None,
324
+ to_block: BlockIdentifier = "latest",
324
325
  address: Optional[ChecksumAddress] = None,
325
326
  topics: Optional[Sequence[Any]] = None,
326
327
  filter_builder: Union[EventFilterBuilder, AsyncEventFilterBuilder] = None,
327
328
  ) -> None:
328
- if fromBlock is None:
329
+ if from_block is None:
329
330
  raise Web3TypeError(
330
- "Missing mandatory keyword argument to create_filter: fromBlock"
331
+ "Missing mandatory keyword argument to create_filter: `from_block`"
331
332
  )
332
333
 
333
334
  if argument_filters is None:
@@ -344,8 +345,8 @@ class BaseContractEvent:
344
345
  self.w3.codec,
345
346
  contract_address=self.address,
346
347
  argument_filters=_filters,
347
- fromBlock=fromBlock,
348
- toBlock=toBlock,
348
+ from_block=from_block,
349
+ to_block=to_block,
349
350
  address=address,
350
351
  topics=topics,
351
352
  )
@@ -353,8 +354,8 @@ class BaseContractEvent:
353
354
  filter_builder.address = cast(
354
355
  ChecksumAddress, event_filter_params.get("address")
355
356
  )
356
- filter_builder.fromBlock = event_filter_params.get("fromBlock")
357
- filter_builder.toBlock = event_filter_params.get("toBlock")
357
+ filter_builder.from_block = event_filter_params.get("fromBlock")
358
+ filter_builder.to_block = event_filter_params.get("toBlock")
358
359
  match_any_vals = {
359
360
  arg: value
360
361
  for arg, value in _filters.items()
web3/contract/contract.py CHANGED
@@ -110,8 +110,8 @@ class ContractEvent(BaseContractEvent):
110
110
  def get_logs(
111
111
  self,
112
112
  argument_filters: Optional[Dict[str, Any]] = None,
113
- fromBlock: Optional[BlockIdentifier] = None,
114
- toBlock: Optional[BlockIdentifier] = None,
113
+ from_block: Optional[BlockIdentifier] = None,
114
+ to_block: Optional[BlockIdentifier] = None,
115
115
  block_hash: Optional[HexBytes] = None,
116
116
  ) -> Iterable[EventData]:
117
117
  """
@@ -131,10 +131,10 @@ class ContractEvent(BaseContractEvent):
131
131
 
132
132
  .. code-block:: python
133
133
 
134
- from = max(mycontract.web3.eth.block_number - 10, 1)
135
- to = mycontract.web3.eth.block_number
134
+ from = max(my_contract.web3.eth.block_number - 10, 1)
135
+ to = my_contract.web3.eth.block_number
136
136
 
137
- events = mycontract.events.Transfer.get_logs(fromBlock=from, toBlock=to)
137
+ events = my_contract.events.Transfer.get_logs(from_block=from, to_block=to)
138
138
 
139
139
  for e in events:
140
140
  print(e["args"]["from"],
@@ -164,10 +164,10 @@ class ContractEvent(BaseContractEvent):
164
164
 
165
165
  :param argument_filters: Filter by argument values. Indexed arguments are
166
166
  filtered by the node while non-indexed arguments are filtered by the library.
167
- :param fromBlock: block number or "latest", defaults to "latest"
168
- :param toBlock: block number or "latest". Defaults to "latest"
167
+ :param from_block: block number or "latest", defaults to "latest"
168
+ :param to_block: block number or "latest". Defaults to "latest"
169
169
  :param block_hash: block hash. block_hash cannot be set at the
170
- same time as fromBlock or toBlock
170
+ same time as ``from_block`` or ``to_block``
171
171
  :yield: Tuple of :class:`AttributeDict` instances
172
172
  """
173
173
  event_abi = self._get_event_abi()
@@ -182,7 +182,7 @@ class ContractEvent(BaseContractEvent):
182
182
  )
183
183
 
184
184
  _filter_params = self._get_event_filter_params(
185
- event_abi, argument_filters, fromBlock, toBlock, block_hash
185
+ event_abi, argument_filters, from_block, to_block, block_hash
186
186
  )
187
187
  # call JSON-RPC API
188
188
  logs = self.w3.eth.get_logs(_filter_params)
@@ -205,8 +205,8 @@ class ContractEvent(BaseContractEvent):
205
205
  self,
206
206
  *, # PEP 3102
207
207
  argument_filters: Optional[Dict[str, Any]] = None,
208
- fromBlock: Optional[BlockIdentifier] = None,
209
- toBlock: BlockIdentifier = "latest",
208
+ from_block: Optional[BlockIdentifier] = None,
209
+ to_block: BlockIdentifier = "latest",
210
210
  address: Optional[ChecksumAddress] = None,
211
211
  topics: Optional[Sequence[Any]] = None,
212
212
  ) -> LogFilter:
@@ -216,8 +216,8 @@ class ContractEvent(BaseContractEvent):
216
216
  filter_builder = EventFilterBuilder(self._get_event_abi(), self.w3.codec)
217
217
  self._set_up_filter_builder(
218
218
  argument_filters,
219
- fromBlock,
220
- toBlock,
219
+ from_block,
220
+ to_block,
221
221
  address,
222
222
  topics,
223
223
  filter_builder,
web3/contract/utils.py CHANGED
@@ -9,6 +9,7 @@ from typing import (
9
9
  Tuple,
10
10
  Type,
11
11
  Union,
12
+ cast,
12
13
  )
13
14
 
14
15
  from eth_abi.exceptions import (
@@ -16,6 +17,11 @@ from eth_abi.exceptions import (
16
17
  )
17
18
  from eth_typing import (
18
19
  ChecksumAddress,
20
+ TypeStr,
21
+ )
22
+ from eth_utils.toolz import (
23
+ compose,
24
+ curry,
19
25
  )
20
26
  from hexbytes import (
21
27
  HexBytes,
@@ -60,10 +66,50 @@ if TYPE_CHECKING:
60
66
  AsyncWeb3,
61
67
  Web3,
62
68
  )
69
+ from web3.providers.persistent import ( # noqa: F401
70
+ PersistentConnectionProvider,
71
+ )
63
72
 
64
73
  ACCEPTABLE_EMPTY_STRINGS = ["0x", b"0x", "", b""]
65
74
 
66
75
 
76
+ @curry
77
+ def format_contract_call_return_data_curried(
78
+ async_w3: Union["AsyncWeb3", "Web3"],
79
+ decode_tuples: bool,
80
+ fn_abi: ABIFunction,
81
+ function_identifier: FunctionIdentifier,
82
+ normalizers: Tuple[Callable[..., Any], ...],
83
+ output_types: Sequence[TypeStr],
84
+ return_data: Any,
85
+ ) -> Any:
86
+ """
87
+ Helper function for formatting contract call return data for batch requests. Curry
88
+ with all arguments except `return_data` and process `return_data` once it is
89
+ available.
90
+ """
91
+ try:
92
+ output_data = async_w3.codec.decode(output_types, return_data)
93
+ except DecodingError as e:
94
+ msg = (
95
+ f"Could not decode contract function call to {function_identifier} "
96
+ f"with return data: {str(return_data)}, output_types: {output_types}"
97
+ )
98
+ raise BadFunctionCallOutput(msg) from e
99
+
100
+ _normalizers = itertools.chain(
101
+ BASE_RETURN_NORMALIZERS,
102
+ normalizers,
103
+ )
104
+ normalized_data = map_abi_data(_normalizers, output_types, output_data)
105
+
106
+ if decode_tuples:
107
+ decoded = named_tree(fn_abi["outputs"], normalized_data)
108
+ normalized_data = recursive_dict_to_namedtuple(decoded)
109
+
110
+ return normalized_data[0] if len(normalized_data) == 1 else normalized_data
111
+
112
+
67
113
  def call_contract_function(
68
114
  w3: "Web3",
69
115
  address: ChecksumAddress,
@@ -108,6 +154,34 @@ def call_contract_function(
108
154
 
109
155
  output_types = get_abi_output_types(fn_abi)
110
156
 
157
+ provider = w3.provider
158
+ if hasattr(provider, "_is_batching") and provider._is_batching:
159
+ # request_information == ((method, params), response_formatters)
160
+ request_information = tuple(return_data)
161
+ method_and_params = request_information[0]
162
+
163
+ # append return data formatting to result formatters
164
+ current_response_formatters = request_information[1]
165
+ current_result_formatters = current_response_formatters[0]
166
+ updated_result_formatters = compose(
167
+ # contract call return data formatter
168
+ format_contract_call_return_data_curried(
169
+ w3,
170
+ decode_tuples,
171
+ fn_abi,
172
+ function_identifier,
173
+ normalizers,
174
+ output_types,
175
+ ),
176
+ current_result_formatters,
177
+ )
178
+ response_formatters = (
179
+ updated_result_formatters, # result formatters
180
+ current_response_formatters[1], # error formatters
181
+ current_response_formatters[2], # null result formatters
182
+ )
183
+ return (method_and_params, response_formatters)
184
+
111
185
  try:
112
186
  output_data = w3.codec.decode(output_types, return_data)
113
187
  except DecodingError as e:
@@ -319,6 +393,43 @@ async def async_call_contract_function(
319
393
 
320
394
  output_types = get_abi_output_types(fn_abi)
321
395
 
396
+ if async_w3.provider._is_batching:
397
+ contract_call_return_data_formatter = format_contract_call_return_data_curried(
398
+ async_w3,
399
+ decode_tuples,
400
+ fn_abi,
401
+ function_identifier,
402
+ normalizers,
403
+ output_types,
404
+ )
405
+ if async_w3.provider.has_persistent_connection:
406
+ # get the current request id
407
+ provider = cast("PersistentConnectionProvider", async_w3.provider)
408
+ current_request_id = provider._batch_request_counter - 1
409
+ provider._request_processor.append_result_formatter_for_request(
410
+ current_request_id, contract_call_return_data_formatter
411
+ )
412
+ else:
413
+ # request_information == ((method, params), response_formatters)
414
+ request_information = tuple(return_data)
415
+ method_and_params = request_information[0]
416
+
417
+ # append return data formatter to result formatters
418
+ current_response_formatters = request_information[1]
419
+ current_result_formatters = current_response_formatters[0]
420
+ updated_result_formatters = compose(
421
+ contract_call_return_data_formatter,
422
+ current_result_formatters,
423
+ )
424
+ response_formatters = (
425
+ updated_result_formatters, # result formatters
426
+ current_response_formatters[1], # error formatters
427
+ current_response_formatters[2], # null result formatters
428
+ )
429
+ return (method_and_params, response_formatters)
430
+
431
+ return return_data
432
+
322
433
  try:
323
434
  output_data = async_w3.codec.decode(output_types, return_data)
324
435
  except DecodingError as e:
@@ -350,10 +461,7 @@ async def async_call_contract_function(
350
461
  decoded = named_tree(fn_abi["outputs"], normalized_data)
351
462
  normalized_data = recursive_dict_to_namedtuple(decoded)
352
463
 
353
- if len(normalized_data) == 1:
354
- return normalized_data[0]
355
- else:
356
- return normalized_data
464
+ return normalized_data[0] if len(normalized_data) == 1 else normalized_data
357
465
 
358
466
 
359
467
  async def async_transact_with_contract_function(
web3/eth/async_eth.py CHANGED
@@ -35,6 +35,9 @@ from web3._utils.async_transactions import (
35
35
  from web3._utils.blocks import (
36
36
  select_method_for_block_identifier,
37
37
  )
38
+ from web3._utils.compat import (
39
+ Unpack,
40
+ )
38
41
  from web3._utils.fee_utils import (
39
42
  async_fee_history_priority_fee,
40
43
  )
@@ -57,12 +60,13 @@ from web3.eth.base_eth import (
57
60
  BaseEth,
58
61
  )
59
62
  from web3.exceptions import (
60
- MethodUnavailable,
63
+ MethodNotSupported,
61
64
  OffchainLookup,
62
65
  TimeExhausted,
63
66
  TooManyRequests,
64
67
  TransactionIndexingInProgress,
65
68
  TransactionNotFound,
69
+ Web3RPCError,
66
70
  Web3ValueError,
67
71
  )
68
72
  from web3.method import (
@@ -194,7 +198,7 @@ class AsyncEth(BaseEth):
194
198
  """
195
199
  try:
196
200
  return await self._max_priority_fee()
197
- except (ValueError, MethodUnavailable):
201
+ except Web3RPCError:
198
202
  warnings.warn(
199
203
  "There was an issue with the method eth_maxPriorityFeePerGas. "
200
204
  "Calculating using eth_feeHistory.",
@@ -593,10 +597,8 @@ class AsyncEth(BaseEth):
593
597
  self.w3, current_transaction, new_transaction
594
598
  )
595
599
 
596
- # todo: Update Any to stricter kwarg checking with TxParams
597
- # https://github.com/python/mypy/issues/4441
598
600
  async def modify_transaction(
599
- self, transaction_hash: _Hash32, **transaction_params: Any
601
+ self, transaction_hash: _Hash32, **transaction_params: Unpack[TxParams]
600
602
  ) -> HexBytes:
601
603
  assert_valid_transaction_params(cast(TxParams, transaction_params))
602
604
 
@@ -736,7 +738,7 @@ class AsyncEth(BaseEth):
736
738
  ] = None,
737
739
  ) -> HexStr:
738
740
  if not isinstance(self.w3.provider, PersistentConnectionProvider):
739
- raise MethodUnavailable(
741
+ raise MethodNotSupported(
740
742
  "eth_subscribe is only supported with providers that support "
741
743
  "persistent connections."
742
744
  )
@@ -753,7 +755,7 @@ class AsyncEth(BaseEth):
753
755
 
754
756
  async def unsubscribe(self, subscription_id: HexStr) -> bool:
755
757
  if not isinstance(self.w3.provider, PersistentConnectionProvider):
756
- raise MethodUnavailable(
758
+ raise MethodNotSupported(
757
759
  "eth_unsubscribe is only supported with providers that support "
758
760
  "persistent connections."
759
761
  )
@@ -764,7 +766,7 @@ class AsyncEth(BaseEth):
764
766
 
765
767
  @overload
766
768
  # mypy error: Overloaded function signatures 1 and 2 overlap with incompatible return types # noqa: E501
767
- def contract(self, address: None = None, **kwargs: Any) -> Type[AsyncContract]: # type: ignore[misc] # noqa: E501
769
+ def contract(self, address: None = None, **kwargs: Any) -> Type[AsyncContract]: # type: ignore[overload-overlap] # noqa: E501
768
770
  ...
769
771
 
770
772
  @overload
web3/eth/eth.py CHANGED
@@ -30,6 +30,9 @@ from hexbytes import (
30
30
  from web3._utils.blocks import (
31
31
  select_method_for_block_identifier,
32
32
  )
33
+ from web3._utils.compat import (
34
+ Unpack,
35
+ )
33
36
  from web3._utils.fee_utils import (
34
37
  fee_history_priority_fee,
35
38
  )
@@ -57,12 +60,12 @@ from web3.eth.base_eth import (
57
60
  BaseEth,
58
61
  )
59
62
  from web3.exceptions import (
60
- MethodUnavailable,
61
63
  OffchainLookup,
62
64
  TimeExhausted,
63
65
  TooManyRequests,
64
66
  TransactionIndexingInProgress,
65
67
  TransactionNotFound,
68
+ Web3RPCError,
66
69
  Web3ValueError,
67
70
  )
68
71
  from web3.method import (
@@ -187,7 +190,7 @@ class Eth(BaseEth):
187
190
  """
188
191
  try:
189
192
  return self._max_priority_fee()
190
- except (ValueError, MethodUnavailable):
193
+ except Web3RPCError:
191
194
  warnings.warn(
192
195
  "There was an issue with the method eth_maxPriorityFeePerGas. "
193
196
  "Calculating using eth_feeHistory.",
@@ -596,10 +599,8 @@ class Eth(BaseEth):
596
599
  current_transaction = get_required_transaction(self.w3, transaction_hash)
597
600
  return replace_transaction(self.w3, current_transaction, new_transaction)
598
601
 
599
- # todo: Update Any to stricter kwarg checking with TxParams
600
- # https://github.com/python/mypy/issues/4441
601
602
  def modify_transaction(
602
- self, transaction_hash: _Hash32, **transaction_params: Any
603
+ self, transaction_hash: _Hash32, **transaction_params: Unpack[TxParams]
603
604
  ) -> HexBytes:
604
605
  assert_valid_transaction_params(cast(TxParams, transaction_params))
605
606
  current_transaction = get_required_transaction(self.w3, transaction_hash)
@@ -680,7 +681,7 @@ class Eth(BaseEth):
680
681
 
681
682
  @overload
682
683
  # type error: Overloaded function signatures 1 and 2 overlap with incompatible return types # noqa: E501
683
- def contract(self, address: None = None, **kwargs: Any) -> Type[Contract]: # type: ignore[misc] # noqa: E501
684
+ def contract(self, address: None = None, **kwargs: Any) -> Type[Contract]: # type: ignore[overload-overlap] # noqa: E501
684
685
  ...
685
686
 
686
687
  @overload
web3/exceptions.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import datetime
2
2
  import time
3
3
  from typing import (
4
+ TYPE_CHECKING,
4
5
  Any,
5
6
  Dict,
6
7
  Optional,
@@ -13,8 +14,12 @@ from eth_utils import (
13
14
 
14
15
  from web3.types import (
15
16
  BlockData,
17
+ RPCResponse,
16
18
  )
17
19
 
20
+ if TYPE_CHECKING:
21
+ import asyncio
22
+
18
23
 
19
24
  class Web3Exception(Exception):
20
25
  """
@@ -30,6 +35,8 @@ class Web3Exception(Exception):
30
35
  # deal with other exceptions
31
36
  """
32
37
 
38
+ user_message: Optional[str] = None
39
+
33
40
  def __init__(
34
41
  self,
35
42
  *args: Any,
@@ -69,6 +76,12 @@ class Web3TypeError(Web3Exception, TypeError):
69
76
  """
70
77
 
71
78
 
79
+ class MethodNotSupported(Web3Exception):
80
+ """
81
+ Raised when a method is not supported by the provider.
82
+ """
83
+
84
+
72
85
  class BadFunctionCallOutput(Web3Exception):
73
86
  """
74
87
  We failed to decode ABI output.
@@ -77,7 +90,7 @@ class BadFunctionCallOutput(Web3Exception):
77
90
  """
78
91
 
79
92
 
80
- class BlockNumberOutofRange(Web3Exception):
93
+ class BlockNumberOutOfRange(Web3Exception):
81
94
  """
82
95
  block_identifier passed does not match known block.
83
96
  """
@@ -216,25 +229,6 @@ class TimeExhausted(Web3Exception):
216
229
  """
217
230
 
218
231
 
219
- class TransactionNotFound(Web3Exception):
220
- """
221
- Raised when a tx hash used to lookup a tx in a jsonrpc call cannot be found.
222
- """
223
-
224
-
225
- class TransactionIndexingInProgress(Web3Exception):
226
- """
227
- Raised when a transaction receipt is not yet available due to transaction indexing
228
- still being in progress.
229
- """
230
-
231
-
232
- class BlockNotFound(Web3Exception):
233
- """
234
- Raised when the block id used to lookup a block in a jsonrpc call cannot be found.
235
- """
236
-
237
-
238
232
  class InfuraProjectIdNotFound(Web3Exception):
239
233
  """
240
234
  Raised when there is no Infura Project Id set.
@@ -317,7 +311,67 @@ class BadResponseFormat(Web3Exception):
317
311
  """
318
312
 
319
313
 
320
- class MethodUnavailable(Web3Exception):
314
+ class TaskNotRunning(Web3Exception):
315
+ """
316
+ Used to signal between asyncio contexts that a task that is being awaited
317
+ is not currently running.
318
+ """
319
+
320
+ def __init__(
321
+ self, task: "asyncio.Task[Any]", message: Optional[str] = None
322
+ ) -> None:
323
+ self.task = task
324
+ if message is None:
325
+ message = f"Task {task} is not running."
326
+ self.message = message
327
+ super().__init__(message)
328
+
329
+
330
+ class Web3RPCError(Web3Exception):
331
+ """
332
+ Raised when a JSON-RPC response contains an error field.
333
+ """
334
+
335
+ def __init__(
336
+ self,
337
+ message: str,
338
+ rpc_response: Optional[RPCResponse] = None,
339
+ user_message: Optional[str] = None,
340
+ ) -> None:
341
+ if user_message is None:
342
+ user_message = (
343
+ "An RPC error was returned by the node. Check the message provided in "
344
+ "the error and any available logs for more information."
345
+ )
346
+
347
+ super().__init__(
348
+ message,
349
+ user_message=user_message,
350
+ )
351
+ self.message = message
352
+ self.rpc_response = rpc_response
353
+
354
+
355
+ class MethodUnavailable(Web3RPCError):
321
356
  """
322
357
  Raised when the method is not available on the node
323
358
  """
359
+
360
+
361
+ class TransactionNotFound(Web3RPCError):
362
+ """
363
+ Raised when a tx hash used to look up a tx in a jsonrpc call cannot be found.
364
+ """
365
+
366
+
367
+ class TransactionIndexingInProgress(Web3RPCError):
368
+ """
369
+ Raised when a transaction receipt is not yet available due to transaction indexing
370
+ still being in progress.
371
+ """
372
+
373
+
374
+ class BlockNotFound(Web3RPCError):
375
+ """
376
+ Raised when the block id used to look up a block in a jsonrpc call cannot be found.
377
+ """
@@ -110,11 +110,11 @@ def _aggregate_miner_data(
110
110
  # types ignored b/c mypy has trouble inferring gas_prices: Sequence[Wei]
111
111
  price_percentile = percentile(gas_prices, percentile=20) # type: ignore
112
112
  except InsufficientData:
113
- price_percentile = min(gas_prices) # type: ignore
113
+ price_percentile = min(gas_prices)
114
114
  yield MinerData(
115
115
  miner,
116
116
  len(set(block_hashes)),
117
- min(gas_prices), # type: ignore
117
+ min(gas_prices),
118
118
  price_percentile,
119
119
  )
120
120