web3 7.0.0b2__py3-none-any.whl → 7.0.0b3__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.
ens/async_ens.py CHANGED
@@ -89,7 +89,7 @@ class AsyncENS(BaseENS):
89
89
  like getting the address for a name.
90
90
 
91
91
  Unless otherwise specified, all addresses are assumed to be a `str` in
92
- `checksum format <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md>`_,
92
+ `checksum format <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md>`_, # blocklint: pragma # noqa: E501
93
93
  like: ``"0x314159265dD8dbb310642f98f50C066173C1259b"``
94
94
  """
95
95
 
@@ -490,7 +490,7 @@ class AsyncENS(BaseENS):
490
490
  ):
491
491
  contract_func_with_args = (fn_name, [node])
492
492
 
493
- calldata = resolver.encodeABI(*contract_func_with_args)
493
+ calldata = resolver.encode_abi(*contract_func_with_args)
494
494
  contract_call_result = await resolver.caller.resolve(
495
495
  ens_encode_name(normal_name),
496
496
  calldata,
ens/ens.py CHANGED
@@ -88,7 +88,7 @@ class ENS(BaseENS):
88
88
  like getting the address for a name.
89
89
 
90
90
  Unless otherwise specified, all addresses are assumed to be a `str` in
91
- `checksum format <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md>`_,
91
+ `checksum format <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md>`_, # blocklint: pragma # noqa: E501
92
92
  like: ``"0x314159265dD8dbb310642f98f50C066173C1259b"``
93
93
  """
94
94
 
@@ -477,7 +477,7 @@ class ENS(BaseENS):
477
477
  if _resolver_supports_interface(resolver, ENS_EXTENDED_RESOLVER_INTERFACE_ID):
478
478
  contract_func_with_args = (fn_name, [node])
479
479
 
480
- calldata = resolver.encodeABI(*contract_func_with_args)
480
+ calldata = resolver.encode_abi(*contract_func_with_args)
481
481
  contract_call_result = resolver.caller.resolve(
482
482
  ens_encode_name(normal_name),
483
483
  calldata,
ens/utils.py CHANGED
@@ -35,9 +35,6 @@ from hexbytes import (
35
35
  HexBytes,
36
36
  )
37
37
 
38
- from ._normalization import (
39
- normalize_name_ensip15,
40
- )
41
38
  from .constants import (
42
39
  ACCEPTABLE_STALE_HOURS,
43
40
  AUCTION_START_GAS_CONSTANT,
@@ -117,13 +114,18 @@ def customize_web3(w3: "_Web3") -> "_Web3":
117
114
  def normalize_name(name: str) -> str:
118
115
  """
119
116
  Clean the fully qualified name, as defined in ENS `EIP-137
120
- <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md#name-syntax>`_
117
+ <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md#name-syntax>`_ # blocklint: pragma # noqa: E501
121
118
 
122
119
  This does *not* enforce whether ``name`` is a label or fully qualified domain.
123
120
 
124
121
  :param str name: the dot-separated ENS name
125
122
  :raises InvalidName: if ``name`` has invalid syntax
126
123
  """
124
+ # Defer import because module initialization takes > 0.1 ms
125
+ from ._normalization import (
126
+ normalize_name_ensip15,
127
+ )
128
+
127
129
  if is_empty_name(name):
128
130
  return ""
129
131
  elif isinstance(name, (bytes, bytearray)):
@@ -169,7 +171,7 @@ def ens_encode_name(name: str) -> bytes:
169
171
  def is_valid_name(name: str) -> bool:
170
172
  """
171
173
  Validate whether the fully qualified name is valid, as defined in ENS `EIP-137
172
- <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md#name-syntax>`_
174
+ <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md#name-syntax>`_ # blocklint: pragma # noqa: E501
173
175
 
174
176
  :param str name: the dot-separated ENS name
175
177
  :returns: True if ``name`` is set, and :meth:`~ens.ENS.nameprep` will not
@@ -229,7 +231,7 @@ def raw_name_to_hash(name: str) -> HexBytes:
229
231
  behind the scenes. For advanced usage, it is a helpful utility.
230
232
 
231
233
  This normalizes the name with `nameprep
232
- <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md#name-syntax>`_
234
+ <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md#name-syntax>`_ # blocklint: pragma # noqa: E501
233
235
  before hashing.
234
236
 
235
237
  :param str name: ENS name to hash
web3/_utils/events.py CHANGED
@@ -29,6 +29,7 @@ from eth_abi.codec import (
29
29
  from eth_typing import (
30
30
  ChecksumAddress,
31
31
  HexStr,
32
+ Primitives,
32
33
  TypeStr,
33
34
  )
34
35
  from eth_utils import (
@@ -99,6 +100,12 @@ if TYPE_CHECKING:
99
100
  )
100
101
 
101
102
 
103
+ def _log_entry_data_to_bytes(
104
+ log_entry_data: Union[Primitives, HexStr, str],
105
+ ) -> bytes:
106
+ return hexstr_if_str(to_bytes, log_entry_data)
107
+
108
+
102
109
  def construct_event_topic_set(
103
110
  event_abi: ABIEvent,
104
111
  abi_codec: ABICodec,
@@ -228,23 +235,25 @@ def get_event_data(
228
235
  log_topics = log_entry["topics"]
229
236
  elif not log_entry["topics"]:
230
237
  raise MismatchedABI("Expected non-anonymous event to have 1 or more topics")
231
- # type ignored b/c event_abi_to_log_topic(event_abi: Dict[str, Any])
232
- elif event_abi_to_log_topic(event_abi) != log_entry["topics"][0]: # type: ignore
238
+ elif event_abi_to_log_topic(dict(event_abi)) != _log_entry_data_to_bytes(
239
+ log_entry["topics"][0]
240
+ ):
233
241
  raise MismatchedABI("The event signature did not match the provided ABI")
234
242
  else:
235
243
  log_topics = log_entry["topics"][1:]
236
244
 
245
+ log_topics_bytes = [_log_entry_data_to_bytes(topic) for topic in log_topics]
237
246
  log_topics_abi = get_indexed_event_inputs(event_abi)
238
247
  log_topic_normalized_inputs = normalize_event_input_types(log_topics_abi)
239
248
  log_topic_types = get_event_abi_types_for_decoding(log_topic_normalized_inputs)
240
249
  log_topic_names = get_abi_input_names(ABIEvent({"inputs": log_topics_abi}))
241
250
 
242
- if len(log_topics) != len(log_topic_types):
251
+ if len(log_topics_bytes) != len(log_topic_types):
243
252
  raise LogTopicError(
244
- f"Expected {len(log_topic_types)} log topics. Got {len(log_topics)}"
253
+ f"Expected {len(log_topic_types)} log topics. Got {len(log_topics_bytes)}"
245
254
  )
246
255
 
247
- log_data = hexstr_if_str(to_bytes, log_entry["data"])
256
+ log_data = _log_entry_data_to_bytes(log_entry["data"])
248
257
  log_data_abi = exclude_indexed_event_inputs(event_abi)
249
258
  log_data_normalized_inputs = normalize_event_input_types(log_data_abi)
250
259
  log_data_types = get_event_abi_types_for_decoding(log_data_normalized_inputs)
@@ -270,7 +279,7 @@ def get_event_data(
270
279
 
271
280
  decoded_topic_data = [
272
281
  abi_codec.decode([topic_type], topic_data)[0]
273
- for topic_type, topic_data in zip(log_topic_types, log_topics)
282
+ for topic_type, topic_data in zip(log_topic_types, log_topics_bytes)
274
283
  ]
275
284
  normalized_topic_data = map_abi_data(
276
285
  BASE_RETURN_NORMALIZERS, log_topic_types, decoded_topic_data
web3/_utils/math.py CHANGED
@@ -18,22 +18,20 @@ def percentile(
18
18
  )
19
19
  if percentile is None:
20
20
  raise ValueError(f"Expected a percentile choice, got {percentile}")
21
+ if percentile < 0 or percentile > 100:
22
+ raise ValueError("percentile must be in the range [0, 100]")
21
23
 
22
24
  sorted_values = sorted(values)
23
25
 
24
- rank = len(values) * percentile / 100
25
- if rank > 0:
26
- index = rank - 1
27
- if index < 0:
28
- return sorted_values[0]
29
- else:
30
- index = rank
26
+ index = len(values) * percentile / 100 - 1
27
+ if index < 0:
28
+ return sorted_values[0]
31
29
 
32
- if index % 1 == 0:
30
+ fractional = index % 1
31
+ if fractional == 0:
33
32
  return sorted_values[int(index)]
34
- else:
35
- fractional = index % 1
36
- integer = int(index - fractional)
37
- lower = sorted_values[integer]
38
- higher = sorted_values[integer + 1]
39
- return lower + fractional * (higher - lower)
33
+
34
+ integer = int(index - fractional)
35
+ lower = sorted_values[integer]
36
+ higher = sorted_values[integer + 1]
37
+ return lower + fractional * (higher - lower)
@@ -233,6 +233,10 @@ TRANSACTION_RESULT_FORMATTERS = {
233
233
  ),
234
234
  "input": HexBytes,
235
235
  "data": HexBytes, # Nethermind, for example, returns both `input` and `data`
236
+ "maxFeePerBlobGas": to_integer_if_hex,
237
+ "blobVersionedHashes": apply_formatter_if(
238
+ is_not_null, apply_formatter_to_array(to_hexbytes(32))
239
+ ),
236
240
  }
237
241
 
238
242
 
@@ -516,6 +520,7 @@ PYTHONIC_REQUEST_FORMATTERS: Dict[RPCEndpoint, Callable[..., Any]] = {
516
520
  ),
517
521
  RPC.eth_getBalance: apply_formatter_at_index(to_hex_if_integer, 1),
518
522
  RPC.eth_getBlockByNumber: apply_formatter_at_index(to_hex_if_integer, 0),
523
+ RPC.eth_getBlockReceipts: apply_formatter_at_index(to_hex_if_integer, 0),
519
524
  RPC.eth_getBlockTransactionCountByNumber: apply_formatter_at_index(
520
525
  to_hex_if_integer,
521
526
  0,
@@ -723,6 +728,7 @@ PYTHONIC_RESULT_FORMATTERS: Dict[RPCEndpoint, Callable[..., Any]] = {
723
728
  RPC.eth_getBalance: to_integer_if_hex,
724
729
  RPC.eth_getBlockByHash: apply_formatter_if(is_not_null, block_formatter),
725
730
  RPC.eth_getBlockByNumber: apply_formatter_if(is_not_null, block_formatter),
731
+ RPC.eth_getBlockReceipts: apply_formatter_to_array(receipt_formatter),
726
732
  RPC.eth_getBlockTransactionCountByHash: to_integer_if_hex,
727
733
  RPC.eth_getBlockTransactionCountByNumber: to_integer_if_hex,
728
734
  RPC.eth_getCode: HexBytes,
@@ -900,6 +906,7 @@ def raise_transaction_not_found_with_index(
900
906
  NULL_RESULT_FORMATTERS: Dict[RPCEndpoint, Callable[..., Any]] = {
901
907
  RPC.eth_getBlockByHash: raise_block_not_found,
902
908
  RPC.eth_getBlockByNumber: raise_block_not_found,
909
+ RPC.eth_getBlockReceipts: raise_block_not_found,
903
910
  RPC.eth_getBlockTransactionCountByHash: raise_block_not_found,
904
911
  RPC.eth_getBlockTransactionCountByNumber: raise_block_not_found,
905
912
  RPC.eth_getUncleCountByBlockHash: raise_block_not_found,
@@ -977,6 +977,39 @@ class AsyncEthModuleTest:
977
977
  assert block is not None
978
978
  assert isinstance(block["number"], int)
979
979
 
980
+ @pytest.mark.asyncio
981
+ async def test_eth_getBlockReceipts_hash(
982
+ self, async_w3: "AsyncWeb3", async_empty_block: BlockData
983
+ ) -> None:
984
+ receipts = await async_w3.eth.get_block_receipts(async_empty_block["hash"])
985
+ assert isinstance(receipts, list)
986
+
987
+ @pytest.mark.asyncio
988
+ async def test_eth_getBlockReceipts_not_found(self, async_w3: "AsyncWeb3") -> None:
989
+ with pytest.raises(BlockNotFound):
990
+ await async_w3.eth.get_block_receipts(UNKNOWN_HASH)
991
+
992
+ @pytest.mark.asyncio
993
+ async def test_eth_getBlockReceipts_with_integer(
994
+ self, async_w3: "AsyncWeb3", async_empty_block: BlockData
995
+ ) -> None:
996
+ receipts = await async_w3.eth.get_block_receipts(async_empty_block["number"])
997
+ assert isinstance(receipts, list)
998
+
999
+ @pytest.mark.asyncio
1000
+ async def test_eth_getBlockReceipts_safe(
1001
+ self, async_w3: "AsyncWeb3", async_empty_block: BlockData
1002
+ ) -> None:
1003
+ receipts = await async_w3.eth.get_block_receipts("safe")
1004
+ assert isinstance(receipts, list)
1005
+
1006
+ @pytest.mark.asyncio
1007
+ async def test_eth_getBlockReceipts_finalized(
1008
+ self, async_w3: "AsyncWeb3", async_empty_block: BlockData
1009
+ ) -> None:
1010
+ receipts = await async_w3.eth.get_block_receipts("finalized")
1011
+ assert isinstance(receipts, list)
1012
+
980
1013
  @pytest.mark.asyncio
981
1014
  async def test_eth_get_block_by_number_full_transactions(
982
1015
  self, async_w3: "AsyncWeb3", async_block_with_txn: BlockData
@@ -1303,7 +1336,7 @@ class AsyncEthModuleTest:
1303
1336
  async_revert_contract: "Contract",
1304
1337
  async_unlocked_account: ChecksumAddress,
1305
1338
  ) -> None:
1306
- data = async_revert_contract.encodeABI(
1339
+ data = async_revert_contract.encode_abi(
1307
1340
  fn_name="UnauthorizedWithMessage", args=["You are not authorized"]
1308
1341
  )
1309
1342
  txn_params = async_revert_contract._prepare_transaction(
@@ -1323,7 +1356,7 @@ class AsyncEthModuleTest:
1323
1356
  async_revert_contract: "Contract",
1324
1357
  async_unlocked_account: ChecksumAddress,
1325
1358
  ) -> None:
1326
- data = async_revert_contract.encodeABI(fn_name="Unauthorized")
1359
+ data = async_revert_contract.encode_abi(fn_name="Unauthorized")
1327
1360
  txn_params = async_revert_contract._prepare_transaction(
1328
1361
  fn_name="customErrorWithoutMessage",
1329
1362
  transaction={
@@ -3755,7 +3788,7 @@ class EthModuleTest:
3755
3788
  revert_contract: "Contract",
3756
3789
  unlocked_account: ChecksumAddress,
3757
3790
  ) -> None:
3758
- data = revert_contract.encodeABI(
3791
+ data = revert_contract.encode_abi(
3759
3792
  fn_name="UnauthorizedWithMessage", args=["You are not authorized"]
3760
3793
  )
3761
3794
  txn_params = revert_contract._prepare_transaction(
@@ -3775,7 +3808,7 @@ class EthModuleTest:
3775
3808
  revert_contract: "Contract",
3776
3809
  unlocked_account: ChecksumAddress,
3777
3810
  ) -> None:
3778
- data = revert_contract.encodeABI(fn_name="Unauthorized")
3811
+ data = revert_contract.encode_abi(fn_name="Unauthorized")
3779
3812
  txn_params = revert_contract._prepare_transaction(
3780
3813
  fn_name="customErrorWithoutMessage",
3781
3814
  transaction={
@@ -4064,7 +4097,7 @@ class EthModuleTest:
4064
4097
  revert_contract: "Contract",
4065
4098
  unlocked_account: ChecksumAddress,
4066
4099
  ) -> None:
4067
- data = revert_contract.encodeABI(
4100
+ data = revert_contract.encode_abi(
4068
4101
  fn_name="UnauthorizedWithMessage", args=["You are not authorized"]
4069
4102
  )
4070
4103
  txn_params = revert_contract._prepare_transaction(
@@ -4084,7 +4117,7 @@ class EthModuleTest:
4084
4117
  revert_contract: "Contract",
4085
4118
  unlocked_account: ChecksumAddress,
4086
4119
  ) -> None:
4087
- data = revert_contract.encodeABI(fn_name="Unauthorized")
4120
+ data = revert_contract.encode_abi(fn_name="Unauthorized")
4088
4121
  txn_params = revert_contract._prepare_transaction(
4089
4122
  fn_name="customErrorWithoutMessage",
4090
4123
  transaction={
@@ -4224,6 +4257,34 @@ class EthModuleTest:
4224
4257
  transaction = block["transactions"][0]
4225
4258
  assert transaction["hash"] == block_with_txn["transactions"][0] # type: ignore
4226
4259
 
4260
+ def test_eth_getBlockReceipts_hash(
4261
+ self, w3: "Web3", empty_block: BlockData
4262
+ ) -> None:
4263
+ receipts = w3.eth.get_block_receipts(empty_block["hash"])
4264
+ assert isinstance(receipts, list)
4265
+
4266
+ def test_eth_getBlockReceipts_not_found(self, w3: "Web3") -> None:
4267
+ with pytest.raises(BlockNotFound):
4268
+ w3.eth.get_block_receipts(UNKNOWN_HASH)
4269
+
4270
+ def test_eth_getBlockReceipts_with_integer(
4271
+ self, w3: "Web3", empty_block: BlockData
4272
+ ) -> None:
4273
+ receipts = w3.eth.get_block_receipts(empty_block["number"])
4274
+ assert isinstance(receipts, list)
4275
+
4276
+ def test_eth_getBlockReceipts_safe(
4277
+ self, w3: "Web3", empty_block: BlockData
4278
+ ) -> None:
4279
+ receipts = w3.eth.get_block_receipts("safe")
4280
+ assert isinstance(receipts, list)
4281
+
4282
+ def test_eth_getBlockReceipts_finalized(
4283
+ self, w3: "Web3", empty_block: BlockData
4284
+ ) -> None:
4285
+ receipts = w3.eth.get_block_receipts("finalized")
4286
+ assert isinstance(receipts, list)
4287
+
4227
4288
  def test_eth_getTransactionByHash(self, w3: "Web3", mined_txn_hash: HexStr) -> None:
4228
4289
  transaction = w3.eth.get_transaction(mined_txn_hash)
4229
4290
  assert is_dict(transaction)
web3/_utils/rpc_abi.py CHANGED
@@ -57,6 +57,7 @@ class RPC:
57
57
  eth_getBalance = RPCEndpoint("eth_getBalance")
58
58
  eth_getBlockByHash = RPCEndpoint("eth_getBlockByHash")
59
59
  eth_getBlockByNumber = RPCEndpoint("eth_getBlockByNumber")
60
+ eth_getBlockReceipts = RPCEndpoint("eth_getBlockReceipts")
60
61
  eth_getBlockTransactionCountByHash = RPCEndpoint(
61
62
  "eth_getBlockTransactionCountByHash"
62
63
  )
@@ -49,6 +49,8 @@ TX_PARAM_LITERALS = Literal[
49
49
  "nonce",
50
50
  "chainId",
51
51
  "accessList",
52
+ "maxFeePerBlobGas",
53
+ "blobVersionedHashes",
52
54
  ]
53
55
 
54
56
  VALID_TRANSACTION_PARAMS: List[TX_PARAM_LITERALS] = [
@@ -64,6 +66,8 @@ VALID_TRANSACTION_PARAMS: List[TX_PARAM_LITERALS] = [
64
66
  "data",
65
67
  "nonce",
66
68
  "chainId",
69
+ "maxFeePerBlobGas",
70
+ "blobVersionedHashes",
67
71
  ]
68
72
 
69
73
  TRANSACTION_DEFAULTS = {
@@ -723,7 +723,7 @@ class BaseContract:
723
723
  # Public API
724
724
  #
725
725
  @combomethod
726
- def encodeABI(
726
+ def encode_abi(
727
727
  cls,
728
728
  fn_name: str,
729
729
  args: Optional[Any] = None,
web3/eth/async_eth.py CHANGED
@@ -4,6 +4,7 @@ from typing import (
4
4
  Any,
5
5
  Awaitable,
6
6
  Callable,
7
+ Dict,
7
8
  List,
8
9
  Optional,
9
10
  Tuple,
@@ -75,6 +76,7 @@ from web3.types import (
75
76
  BlockData,
76
77
  BlockIdentifier,
77
78
  BlockParams,
79
+ BlockReceipts,
78
80
  CreateAccessListResponse,
79
81
  FeeHistory,
80
82
  FilterParams,
@@ -440,6 +442,20 @@ class AsyncEth(BaseEth):
440
442
  ) -> BlockData:
441
443
  return await self._get_block(block_identifier, full_transactions)
442
444
 
445
+ # eth_getBlockReceipts
446
+
447
+ _get_block_receipts: Method[
448
+ Callable[[BlockIdentifier], Awaitable[BlockReceipts]]
449
+ ] = Method(
450
+ RPC.eth_getBlockReceipts,
451
+ mungers=[default_root_munger],
452
+ )
453
+
454
+ async def get_block_receipts(
455
+ self, block_identifier: BlockIdentifier
456
+ ) -> BlockReceipts:
457
+ return await self._get_block_receipts(block_identifier)
458
+
443
459
  # eth_getBalance
444
460
 
445
461
  _get_balance: Method[
@@ -622,14 +638,16 @@ class AsyncEth(BaseEth):
622
638
  # eth_signTypedData
623
639
 
624
640
  _sign_typed_data: Method[
625
- Callable[[Union[Address, ChecksumAddress, ENS], str], Awaitable[HexStr]]
641
+ Callable[
642
+ [Union[Address, ChecksumAddress, ENS], Dict[str, Any]], Awaitable[HexStr]
643
+ ]
626
644
  ] = Method(
627
645
  RPC.eth_signTypedData,
628
646
  mungers=[default_root_munger],
629
647
  )
630
648
 
631
649
  async def sign_typed_data(
632
- self, account: Union[Address, ChecksumAddress, ENS], data: str
650
+ self, account: Union[Address, ChecksumAddress, ENS], data: Dict[str, Any]
633
651
  ) -> HexStr:
634
652
  return await self._sign_typed_data(account, data)
635
653
 
web3/eth/eth.py CHANGED
@@ -2,6 +2,7 @@ from typing import (
2
2
  TYPE_CHECKING,
3
3
  Any,
4
4
  Callable,
5
+ Dict,
5
6
  List,
6
7
  Optional,
7
8
  Sequence,
@@ -72,6 +73,7 @@ from web3.types import (
72
73
  BlockData,
73
74
  BlockIdentifier,
74
75
  BlockParams,
76
+ BlockReceipts,
75
77
  CreateAccessListResponse,
76
78
  FeeHistory,
77
79
  FilterParams,
@@ -411,6 +413,16 @@ class Eth(BaseEth):
411
413
  ) -> BlockData:
412
414
  return self._get_block(block_identifier, full_transactions)
413
415
 
416
+ # eth_getBlockReceipts
417
+
418
+ _get_block_receipts: Method[Callable[[BlockIdentifier], BlockReceipts]] = Method(
419
+ RPC.eth_getBlockReceipts,
420
+ mungers=[default_root_munger],
421
+ )
422
+
423
+ def get_block_receipts(self, block_identifier: BlockIdentifier) -> BlockReceipts:
424
+ return self._get_block_receipts(block_identifier)
425
+
414
426
  # eth_getBalance
415
427
 
416
428
  _get_balance: Method[
@@ -611,7 +623,7 @@ class Eth(BaseEth):
611
623
  # eth_signTypedData
612
624
 
613
625
  sign_typed_data: Method[
614
- Callable[[Union[Address, ChecksumAddress, ENS], str], HexStr]
626
+ Callable[[Union[Address, ChecksumAddress, ENS], Dict[str, Any]], HexStr]
615
627
  ] = Method(
616
628
  RPC.eth_signTypedData,
617
629
  mungers=[default_root_munger],
web3/exceptions.py CHANGED
@@ -30,6 +30,16 @@ class Web3Exception(Exception):
30
30
  # deal with other exceptions
31
31
  """
32
32
 
33
+ def __init__(
34
+ self,
35
+ *args: Any,
36
+ user_message: Optional[str] = None,
37
+ ):
38
+ super().__init__(*args)
39
+
40
+ # Assign properties of Web3Exception
41
+ self.user_message = user_message
42
+
33
43
 
34
44
  class BadFunctionCallOutput(Web3Exception):
35
45
  """
@@ -274,6 +284,7 @@ class ContractLogicError(Web3Exception):
274
284
  message: Optional[str] = None,
275
285
  data: Optional[Union[str, Dict[str, str]]] = None,
276
286
  ):
287
+ super().__init__(message, data)
277
288
  self.message = message
278
289
  self.data = data
279
290
 
web3/manager.py CHANGED
@@ -1,4 +1,3 @@
1
- import asyncio
2
1
  import logging
3
2
  from typing import (
4
3
  TYPE_CHECKING,
@@ -246,7 +245,11 @@ class RequestManager:
246
245
  if not isinstance(code, int):
247
246
  _raise_bad_response_format(response, "error['code'] must be an integer")
248
247
  elif code == METHOD_NOT_FOUND:
249
- raise MethodUnavailable(error)
248
+ raise MethodUnavailable(
249
+ error,
250
+ user_message="Check your node provider's API docs to see what "
251
+ "methods are supported",
252
+ )
250
253
 
251
254
  # Errors must include a message
252
255
  if not isinstance(error.get("message"), str):
@@ -345,11 +348,7 @@ class RequestManager:
345
348
  )
346
349
 
347
350
  while True:
348
- # sleep(0) here seems to be the most efficient way to yield control
349
- # back to the event loop while waiting for the response in the queue.
350
- await asyncio.sleep(0)
351
-
352
- response = self._request_processor.pop_raw_response(subscription=True)
351
+ response = await self._request_processor.pop_raw_response(subscription=True)
353
352
  if (
354
353
  response is not None
355
354
  and response.get("params", {}).get("subscription")
@@ -78,7 +78,7 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
78
78
  self.logger.debug(
79
79
  f"Popping response for id {request_id} from cache."
80
80
  )
81
- popped_response = self._request_processor.pop_raw_response(
81
+ popped_response = await self._request_processor.pop_raw_response(
82
82
  cache_key=request_cache_key,
83
83
  )
84
84
  return popped_response
@@ -235,19 +235,17 @@ class RequestProcessor:
235
235
  )
236
236
  self._request_response_cache.cache(cache_key, raw_response)
237
237
 
238
- def pop_raw_response(
238
+ async def pop_raw_response(
239
239
  self, cache_key: str = None, subscription: bool = False
240
240
  ) -> Any:
241
241
  if subscription:
242
242
  qsize = self._subscription_response_queue.qsize()
243
- if qsize == 0:
244
- return None
243
+ raw_response = await self._subscription_response_queue.get()
245
244
 
246
245
  if not self._provider._listen_event.is_set():
247
246
  self._provider._listen_event.set()
248
247
 
249
- raw_response = self._subscription_response_queue.get_nowait()
250
- if qsize == 1:
248
+ if qsize == 0:
251
249
  if not self._subscription_queue_synced_with_ws_stream:
252
250
  self._subscription_queue_synced_with_ws_stream = True
253
251
  self._provider.logger.info(
File without changes
@@ -0,0 +1,185 @@
1
+ import argparse
2
+ import asyncio
3
+ from collections import (
4
+ defaultdict,
5
+ )
6
+ import logging
7
+ import sys
8
+ import timeit
9
+ from typing import (
10
+ Any,
11
+ Callable,
12
+ Dict,
13
+ Union,
14
+ )
15
+
16
+ from web3 import (
17
+ AsyncHTTPProvider,
18
+ AsyncWeb3,
19
+ HTTPProvider,
20
+ Web3,
21
+ )
22
+ from web3.middleware import (
23
+ BufferedGasEstimateMiddleware,
24
+ GasPriceStrategyMiddleware,
25
+ )
26
+ from web3.tools.benchmark.node import (
27
+ GethBenchmarkFixture,
28
+ )
29
+ from web3.tools.benchmark.reporting import (
30
+ print_entry,
31
+ print_footer,
32
+ print_header,
33
+ )
34
+ from web3.tools.benchmark.utils import (
35
+ wait_for_aiohttp,
36
+ wait_for_http,
37
+ )
38
+ from web3.types import (
39
+ Wei,
40
+ )
41
+
42
+ KEYFILE_PW = "web3py-test"
43
+
44
+ parser = argparse.ArgumentParser()
45
+ parser.add_argument(
46
+ "--num-calls",
47
+ type=int,
48
+ default=10,
49
+ help="The number of RPC calls to make",
50
+ )
51
+
52
+ # TODO - layers to test:
53
+ # contract.functions.method(...).call()
54
+ # w3.eth.call(...)
55
+ # HTTPProvider.make_request(...)
56
+
57
+
58
+ def build_web3_http(endpoint_uri: str) -> Web3:
59
+ wait_for_http(endpoint_uri)
60
+ _w3 = Web3(
61
+ HTTPProvider(endpoint_uri),
62
+ middleware=[GasPriceStrategyMiddleware, BufferedGasEstimateMiddleware],
63
+ )
64
+ return _w3
65
+
66
+
67
+ async def build_async_w3_http(endpoint_uri: str) -> AsyncWeb3:
68
+ await wait_for_aiohttp(endpoint_uri)
69
+ _w3 = AsyncWeb3(
70
+ AsyncHTTPProvider(endpoint_uri),
71
+ middleware=[GasPriceStrategyMiddleware, BufferedGasEstimateMiddleware],
72
+ )
73
+ return _w3
74
+
75
+
76
+ def sync_benchmark(func: Callable[..., Any], n: int) -> Union[float, str]:
77
+ try:
78
+ starttime = timeit.default_timer()
79
+ for _ in range(n):
80
+ func()
81
+ endtime = timeit.default_timer()
82
+ execution_time = endtime - starttime
83
+ return execution_time
84
+ except Exception:
85
+ return "N/A"
86
+
87
+
88
+ async def async_benchmark(func: Callable[..., Any], n: int) -> Union[float, str]:
89
+ try:
90
+ starttime = timeit.default_timer()
91
+ for result in asyncio.as_completed([func() for _ in range(n)]):
92
+ await result
93
+ execution_time = timeit.default_timer() - starttime
94
+ return execution_time
95
+ except Exception:
96
+ return "N/A"
97
+
98
+
99
+ def main(logger: logging.Logger, num_calls: int) -> None:
100
+ fixture = GethBenchmarkFixture()
101
+ for built_fixture in fixture.build():
102
+ for _ in built_fixture:
103
+ w3_http = build_web3_http(fixture.endpoint_uri)
104
+ try:
105
+ loop = asyncio.get_running_loop()
106
+ except RuntimeError:
107
+ loop = asyncio.new_event_loop()
108
+ asyncio.set_event_loop(loop)
109
+
110
+ # -- sync -- #
111
+ coinbase = w3_http.eth.coinbase
112
+
113
+ # -- async -- #
114
+ async_w3_http = loop.run_until_complete(
115
+ build_async_w3_http(fixture.endpoint_uri)
116
+ )
117
+ async_coinbase = loop.run_until_complete(async_w3_http.eth.coinbase)
118
+
119
+ methods = [
120
+ {
121
+ "name": "eth_gasPrice",
122
+ "params": {},
123
+ "exec": lambda: w3_http.eth.gas_price,
124
+ "async_exec": lambda: async_w3_http.eth.gas_price,
125
+ },
126
+ {
127
+ "name": "eth_sendTransaction",
128
+ "params": {},
129
+ "exec": lambda: w3_http.eth.send_transaction(
130
+ {
131
+ "to": "0xd3CdA913deB6f67967B99D67aCDFa1712C293601",
132
+ "from": coinbase,
133
+ "value": Wei(1),
134
+ }
135
+ ),
136
+ "async_exec": lambda: async_w3_http.eth.send_transaction(
137
+ {
138
+ "to": "0xd3CdA913deB6f67967B99D67aCDFa1712C293601",
139
+ "from": async_coinbase,
140
+ "value": Wei(1),
141
+ }
142
+ ),
143
+ },
144
+ {
145
+ "name": "eth_blockNumber",
146
+ "params": {},
147
+ "exec": lambda: w3_http.eth.block_number,
148
+ "async_exec": lambda: async_w3_http.eth.block_number,
149
+ },
150
+ {
151
+ "name": "eth_getBlock",
152
+ "params": {},
153
+ "exec": lambda: w3_http.eth.get_block(1),
154
+ "async_exec": lambda: async_w3_http.eth.get_block(1),
155
+ },
156
+ ]
157
+
158
+ def benchmark(method: Dict[str, Any]) -> None:
159
+ outcomes: Dict[str, Union[str, float]] = defaultdict(lambda: "N/A")
160
+ outcomes["name"] = method["name"]
161
+ outcomes["HTTPProvider"] = sync_benchmark(
162
+ method["exec"],
163
+ num_calls,
164
+ )
165
+ outcomes["AsyncHTTPProvider"] = loop.run_until_complete(
166
+ async_benchmark(method["async_exec"], num_calls)
167
+ )
168
+ print_entry(logger, outcomes)
169
+
170
+ print_header(logger, num_calls)
171
+
172
+ for method in methods:
173
+ benchmark(method)
174
+
175
+ print_footer(logger)
176
+
177
+
178
+ if __name__ == "__main__":
179
+ args = parser.parse_args()
180
+
181
+ logger = logging.getLogger()
182
+ logger.setLevel(logging.INFO)
183
+ logger.addHandler(logging.StreamHandler(sys.stdout))
184
+
185
+ main(logger, args.num_calls)
@@ -0,0 +1,126 @@
1
+ import os
2
+ import socket
3
+ from subprocess import (
4
+ PIPE,
5
+ Popen,
6
+ check_output,
7
+ )
8
+ from tempfile import (
9
+ TemporaryDirectory,
10
+ )
11
+ from typing import (
12
+ Any,
13
+ Generator,
14
+ Sequence,
15
+ )
16
+ import zipfile
17
+
18
+ from geth.install import (
19
+ get_executable_path,
20
+ install_geth,
21
+ )
22
+
23
+ from web3.tools.benchmark.utils import (
24
+ kill_proc_gracefully,
25
+ )
26
+
27
+ GETH_FIXTURE_ZIP = "geth-1.13.11-fixture.zip"
28
+
29
+ # use same coinbase value as in `web3.py/tests/integration/generate_fixtures/common.py`
30
+ COINBASE = "0xdc544d1aa88ff8bbd2f2aec754b1f1e99e1812fd"
31
+
32
+
33
+ class GethBenchmarkFixture:
34
+ def __init__(self) -> None:
35
+ self.rpc_port = self._rpc_port()
36
+ self.endpoint_uri = self._endpoint_uri()
37
+ self.geth_binary = self._geth_binary()
38
+
39
+ def build(self) -> Generator[Any, None, None]:
40
+ with TemporaryDirectory() as base_dir:
41
+ zipfile_path = os.path.abspath(
42
+ os.path.join(
43
+ os.path.dirname(__file__),
44
+ "../../../tests/integration/",
45
+ GETH_FIXTURE_ZIP,
46
+ )
47
+ )
48
+ tmp_datadir = os.path.join(str(base_dir), "datadir")
49
+ with zipfile.ZipFile(zipfile_path, "r") as zip_ref:
50
+ zip_ref.extractall(tmp_datadir)
51
+ self.datadir = tmp_datadir
52
+
53
+ genesis_file = os.path.join(self.datadir, "genesis.json")
54
+
55
+ yield self._geth_process(self.datadir, genesis_file, self.rpc_port)
56
+
57
+ def _rpc_port(self) -> str:
58
+ sock = socket.socket()
59
+ sock.bind(("127.0.0.1", 0))
60
+ port = sock.getsockname()[1]
61
+ sock.close()
62
+ return str(port)
63
+
64
+ def _endpoint_uri(self) -> str:
65
+ return f"http://localhost:{self.rpc_port}"
66
+
67
+ def _geth_binary(self) -> str:
68
+ if "GETH_BINARY" in os.environ:
69
+ return os.environ["GETH_BINARY"]
70
+ elif "GETH_VERSION" in os.environ:
71
+ geth_version = os.environ["GETH_VERSION"]
72
+ _geth_binary = get_executable_path(geth_version)
73
+ if not os.path.exists(_geth_binary):
74
+ install_geth(geth_version)
75
+ assert os.path.exists(_geth_binary)
76
+ return _geth_binary
77
+ else:
78
+ return "geth"
79
+
80
+ def _geth_command_arguments(self, datadir: str) -> Sequence[str]:
81
+ return (
82
+ self.geth_binary,
83
+ "--dev",
84
+ "--dev.period",
85
+ "100",
86
+ "--datadir",
87
+ str(datadir),
88
+ "--nodiscover",
89
+ "--http",
90
+ "--http.port",
91
+ self.rpc_port,
92
+ "--http.api",
93
+ "admin,eth,net,web3",
94
+ "--ipcdisable",
95
+ "--allow-insecure-unlock",
96
+ "--miner.etherbase",
97
+ COINBASE[2:],
98
+ "--password",
99
+ os.path.join(datadir, "keystore", "pw.txt"),
100
+ )
101
+
102
+ def _geth_process(
103
+ self, datadir: str, genesis_file: str, rpc_port: str
104
+ ) -> Generator[Any, None, None]:
105
+ init_datadir_command = (
106
+ self.geth_binary,
107
+ "--datadir",
108
+ str(datadir),
109
+ "init",
110
+ str(genesis_file),
111
+ )
112
+ check_output(
113
+ init_datadir_command,
114
+ stdin=PIPE,
115
+ stderr=PIPE,
116
+ )
117
+ proc = Popen(
118
+ self._geth_command_arguments(datadir),
119
+ stdin=PIPE,
120
+ stdout=PIPE,
121
+ stderr=PIPE,
122
+ )
123
+ try:
124
+ yield proc
125
+ finally:
126
+ kill_proc_gracefully(proc)
@@ -0,0 +1,39 @@
1
+ from logging import (
2
+ Logger,
3
+ )
4
+ from typing import (
5
+ Any,
6
+ Dict,
7
+ )
8
+
9
+
10
+ def print_header(logger: Logger, num_calls: int) -> None:
11
+ logger.info(
12
+ "|{:^26}|{:^20}|{:^20}|{:^20}|{:^20}|".format(
13
+ f"Method ({num_calls} calls)",
14
+ "HTTPProvider",
15
+ "AsyncHTTProvider",
16
+ "IPCProvider",
17
+ "WebSocketProvider",
18
+ )
19
+ )
20
+ logger.info("-" * 112)
21
+
22
+
23
+ def print_entry(
24
+ logger: Logger,
25
+ method_benchmarks: Dict[str, Any],
26
+ ) -> None:
27
+ logger.info(
28
+ "|{:^26}|{:^20.10}|{:^20.10}|{:^20.10}|{:^20.10}|".format(
29
+ method_benchmarks["name"],
30
+ method_benchmarks["HTTPProvider"],
31
+ method_benchmarks["AsyncHTTPProvider"],
32
+ method_benchmarks["IPCProvider"],
33
+ method_benchmarks["WebSocketProvider"],
34
+ )
35
+ )
36
+
37
+
38
+ def print_footer(logger: Logger) -> None:
39
+ logger.info("-" * 112)
@@ -0,0 +1,69 @@
1
+ import asyncio
2
+ import signal
3
+ import socket
4
+ import time
5
+ from typing import (
6
+ Any,
7
+ )
8
+
9
+ import aiohttp
10
+ import requests
11
+
12
+
13
+ def wait_for_socket(ipc_path: str, timeout: int = 30) -> None:
14
+ start = time.time()
15
+ while time.time() < start + timeout:
16
+ try:
17
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
18
+ sock.connect(ipc_path)
19
+ sock.settimeout(timeout)
20
+ except (FileNotFoundError, socket.error):
21
+ time.sleep(0.01)
22
+ else:
23
+ break
24
+
25
+
26
+ def wait_for_http(endpoint_uri: str, timeout: int = 60) -> None:
27
+ start = time.time()
28
+ while time.time() < start + timeout:
29
+ try:
30
+ requests.get(endpoint_uri)
31
+ except requests.ConnectionError:
32
+ time.sleep(0.01)
33
+ else:
34
+ break
35
+
36
+
37
+ async def wait_for_aiohttp(endpoint_uri: str, timeout: int = 60) -> None:
38
+ start = time.time()
39
+ while time.time() < start + timeout:
40
+ try:
41
+ async with aiohttp.ClientSession() as session:
42
+ await session.get(endpoint_uri)
43
+ except aiohttp.client_exceptions.ClientConnectorError:
44
+ await asyncio.sleep(0.01)
45
+ else:
46
+ break
47
+
48
+
49
+ def wait_for_popen(proc: Any, timeout: int) -> None:
50
+ start = time.time()
51
+ while time.time() < start + timeout:
52
+ if proc.poll() is None:
53
+ time.sleep(0.01)
54
+ else:
55
+ break
56
+
57
+
58
+ def kill_proc_gracefully(proc: Any) -> None:
59
+ if proc.poll() is None:
60
+ proc.send_signal(signal.SIGINT)
61
+ wait_for_popen(proc, 13)
62
+
63
+ if proc.poll() is None:
64
+ proc.terminate()
65
+ wait_for_popen(proc, 5)
66
+
67
+ if proc.poll() is None:
68
+ proc.kill()
69
+ wait_for_popen(proc, 2)
web3/types.py CHANGED
@@ -135,6 +135,7 @@ TxData = TypedDict(
135
135
  "TxData",
136
136
  {
137
137
  "accessList": AccessList,
138
+ "blobVersionedHashes": Sequence[HexBytes],
138
139
  "blockHash": HexBytes,
139
140
  "blockNumber": BlockNumber,
140
141
  "chainId": int,
@@ -142,6 +143,7 @@ TxData = TypedDict(
142
143
  "from": ChecksumAddress,
143
144
  "gas": int,
144
145
  "gasPrice": Wei,
146
+ "maxFeePerBlobGas": Wei,
145
147
  "maxFeePerGas": Wei,
146
148
  "maxPriorityFeePerGas": Wei,
147
149
  "hash": HexBytes,
@@ -381,6 +383,8 @@ TxReceipt = TypedDict(
381
383
  },
382
384
  )
383
385
 
386
+ BlockReceipts = List[TxReceipt]
387
+
384
388
 
385
389
  class SignedTx(TypedDict, total=False):
386
390
  raw: bytes
web3/utils/caching.py CHANGED
@@ -16,22 +16,20 @@ class SimpleCache:
16
16
  self._data: OrderedDict[str, Any] = OrderedDict()
17
17
 
18
18
  def cache(self, key: str, value: Any) -> Tuple[Any, Dict[str, Any]]:
19
- evicted_items = None
19
+ evicted_items = {}
20
20
  # If the key is already in the OrderedDict just update it
21
21
  # and don't evict any values. Ideally, we could still check to see
22
22
  # if there are too many items in the OrderedDict but that may rearrange
23
23
  # the order it should be unlikely that the size could grow over the limit
24
24
  if key not in self._data:
25
25
  while len(self._data) >= self._size:
26
- if evicted_items is None:
27
- evicted_items = {}
28
26
  k, v = self._data.popitem(last=False)
29
27
  evicted_items[k] = v
30
28
  self._data[key] = value
31
29
 
32
30
  # Return the cached value along with the evicted items at the same time. No
33
31
  # need to reach back into the cache to grab the value.
34
- return value, evicted_items
32
+ return value, evicted_items or None
35
33
 
36
34
  def get_cache_entry(self, key: str) -> Optional[Any]:
37
35
  return self._data[key] if key in self._data else None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: web3
3
- Version: 7.0.0b2
3
+ Version: 7.0.0b3
4
4
  Summary: web3.py
5
5
  Home-page: https://github.com/ethereum/web3.py
6
6
  Author: The Ethereum Foundation
@@ -36,6 +36,7 @@ Provides-Extra: dev
36
36
  Requires-Dist: eth-tester[py-evm] ==v0.10.0-b.3 ; extra == 'dev'
37
37
  Requires-Dist: py-geth >=4.1.0 ; extra == 'dev'
38
38
  Requires-Dist: black >=22.1.0 ; extra == 'dev'
39
+ Requires-Dist: blocklint >=0.2.4 ; extra == 'dev'
39
40
  Requires-Dist: flake8 ==3.8.3 ; extra == 'dev'
40
41
  Requires-Dist: isort >=5.11.0 ; extra == 'dev'
41
42
  Requires-Dist: mypy ==1.4.1 ; extra == 'dev'
@@ -64,6 +65,7 @@ Requires-Dist: sphinx-rtd-theme >=1.0.0 ; extra == 'docs'
64
65
  Requires-Dist: towncrier <22,>=21 ; extra == 'docs'
65
66
  Provides-Extra: linter
66
67
  Requires-Dist: black >=22.1.0 ; extra == 'linter'
68
+ Requires-Dist: blocklint >=0.2.4 ; extra == 'linter'
67
69
  Requires-Dist: flake8 ==3.8.3 ; extra == 'linter'
68
70
  Requires-Dist: isort >=5.11.0 ; extra == 'linter'
69
71
  Requires-Dist: mypy ==1.4.1 ; extra == 'linter'
@@ -1,31 +1,31 @@
1
1
  ens/__init__.py,sha256=Dtb57dzb4nLJbtR-XCziJs075vqNpmNfiDSIVe5EPnE,285
2
2
  ens/_normalization.py,sha256=cj9EWUFtKwiYEoX-2PfrcVv5VRYm-oy-CX9cDjegZrE,16788
3
3
  ens/abis.py,sha256=0Ec_lqe7HBsVpQrID3ccFMhx8Vb7S0TGFbeuRdXhuCE,34745
4
- ens/async_ens.py,sha256=Nns377sjU9RwsbnkjSLaaXp6r9VbXBxSgNrTbc9h4rY,22298
4
+ ens/async_ens.py,sha256=j0BoBfik1FeLui26GI9S-rUBE1zPpeBnBZL5bDDTwWU,22333
5
5
  ens/auto.py,sha256=w_E6Ua5ZmJVxfdii2aG5I_kQG5B9U5Y2qIFKVNhXo98,41
6
6
  ens/base_ens.py,sha256=BTYB5SCkif5r08Aou7haMhJABaggOHn3S4tUW4MLsVo,3477
7
7
  ens/constants.py,sha256=XCO4Pntwdnw10K_AZ86V0cqcvdUoOkEZvRqoDdFPE_w,913
8
8
  ens/contract_data.py,sha256=ZF8wMZDXbhd3q1Qn5ishjbASQf4QoDAMUet9ySTwmVU,148604
9
- ens/ens.py,sha256=GJSbTD64-X7Uf06OikeutuRcx4pZaHzOIY-7XxJMmII,21570
9
+ ens/ens.py,sha256=XlVZ7k9hC_HOiOFD7LCZQ-rroVfq2TTle_oSfrXSbmc,21605
10
10
  ens/exceptions.py,sha256=g15oQhT3cbhniGjAmboC2M7xKGGNDfMutSnfK0LMqvs,2326
11
- ens/utils.py,sha256=9tl1mH2c3VHxubQkCcNRc4yMKx7dLNm8vgpJ89OMUAQ,9138
11
+ ens/utils.py,sha256=Ah9EVu-ch8nWMzMoFSYrkGMzJA61-zwT5Qc5Homs1JI,9317
12
12
  ens/specs/nf.json,sha256=EnLJQWU7usNO-EBe1SessY2CioM4H_HXTRvxU__0Ufw,48402
13
13
  ens/specs/normalization_spec.json,sha256=liMWlkVT_OYYjiWlFmpMHpBjM631O98pZMcd7cD44sg,3115333
14
14
  web3/__init__.py,sha256=ZKNvCbdKGK7fBlUIGBOiIoBaEsvnKIjF0GpZZpNF5h4,1068
15
15
  web3/constants.py,sha256=eQLRQVMFPbgpOjjkPTMHkY-syncJuO-sPX5UrCSRjzQ,564
16
16
  web3/datastructures.py,sha256=ylvV3sgXsovIwbg9cXiHXdIZHdCIMzPwxMY1SeJVUSM,10716
17
- web3/exceptions.py,sha256=vJsP5sXeUeeUUFd7GaodGh-k1YH6CfwFTWyT-EZFMu0,6641
17
+ web3/exceptions.py,sha256=u0qTr7mS9wEmh-0jSfXNlEzJ-Sfigr4MwF6HxE7_wUw,6904
18
18
  web3/geth.py,sha256=1DRMSCErpCxL7l0406z5K46P8ORmtS87ZMyLowwK9LI,11329
19
19
  web3/logs.py,sha256=ROs-mDMH_ZOecE7hfbWA5yp27G38FbLjX4lO_WtlZxQ,198
20
20
  web3/main.py,sha256=-75d38t4aGjJNbbcUOnlE2s0jdIw34UDODHjVVzaBTo,13987
21
- web3/manager.py,sha256=-0Ce0zO9HZr3XenPYhATscrkrCmow8p60vPM5nBquTc,15069
21
+ web3/manager.py,sha256=Sz2xseY3WxppPXLPpBoIvK51FqiN9VstY1UK69LlTgU,15030
22
22
  web3/method.py,sha256=3q8SnB6z3KKVfYYlDHoPCuQd-gYdjYkQWy8Q4Y5_L0U,7766
23
23
  web3/module.py,sha256=zonvW0meqdfG82-KgtYTF9ketsCShK2m9b-HYRBJRZg,4793
24
24
  web3/net.py,sha256=Y3vPzHWVFkfHEZoJxjDOt4tp5ERmZrMuyi4ZFOLmIeA,1562
25
25
  web3/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
26
  web3/testing.py,sha256=X7rKGcuEbRCvwXlWuJOfzZvXHboIEeoK-bIWnF_zn1A,951
27
27
  web3/tracing.py,sha256=OBRKLfoSSstzUrk-oqkrbPYPTNGTaPX7-VO5iEt1FwY,2968
28
- web3/types.py,sha256=Eq5MeHp497dx_I4kbdZMvy91zBdsy4XdgHWMBphYzEw,12417
28
+ web3/types.py,sha256=Cf-YKolEoS39PQxahxccyhdUcPYHFq6-S06KXn26cDk,12534
29
29
  web3/_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
30
  web3/_utils/abi.py,sha256=OOnpQSGVAPgbgCXcxGypmhMMj1tq27HXyqPYrTqkchU,30587
31
31
  web3/_utils/async_caching.py,sha256=2XnaKCHBTTDK6B2R_YZvjJqIRUpbMDIU1uYrq-Lcyp8,486
@@ -39,21 +39,21 @@ web3/_utils/empty.py,sha256=jd7-bwIhNLfBjns5WRDCeN1aT1reGgTZ1XlT6olTs3U,144
39
39
  web3/_utils/encoding.py,sha256=VW_-lDqQsEjqrA34Ea8v4Lj8_y3ZHL6EnTGJK-jt5rw,9117
40
40
  web3/_utils/ens.py,sha256=2BvzfegBkR7vH3Fq7lo_LsgfT912Zj-mR8eUt6o_lBA,2434
41
41
  web3/_utils/error_formatters_utils.py,sha256=0D1Dc6QojWgG2JSJmdjnFjs3k-ylKItygTulI7XZXco,6809
42
- web3/_utils/events.py,sha256=yDkzxWqT--KZN2MFo4F_ERsgOHRvUuc0z1vr4GH6uj0,17278
42
+ web3/_utils/events.py,sha256=6vebSk4klDRHykZ_9Dv0N9omam8OQOU8EWUdVEv2TAY,17498
43
43
  web3/_utils/fee_utils.py,sha256=65Z6pPaPz39gsCVIyQwM2y1qfOUNc-4hlGbYAqAteVA,2145
44
44
  web3/_utils/filters.py,sha256=MTgJGMw2hHmrxtaJmWO-0DjQ5OCbwY0kOoT-OglgPDc,11996
45
45
  web3/_utils/formatters.py,sha256=xcLQIRxL07vHHTwfsdGEGS7LGzY1_tf5mSnTS9KTfoM,3071
46
46
  web3/_utils/function_identifiers.py,sha256=m305lsvUZk-jkPixT0IJd9P5sXqMvmwlwlLeBgEAnBQ,55
47
47
  web3/_utils/http.py,sha256=GDHmbeWt7UoHkRBvFt9Py5Vzr2ZLzH9WxAqEYZCJ53s,205
48
48
  web3/_utils/hypothesis.py,sha256=4Cm4iOWv-uP9irg_Pv63kYNDYUAGhnUH6fOPWRw3A0g,209
49
- web3/_utils/math.py,sha256=Tl-EhmKXtPM7t5tkj2VKrJYTtl5DJoTHiKIL95kzQHc,1047
50
- web3/_utils/method_formatters.py,sha256=Dl6TbwkuL-5LhRpUdjQG6XVNJ2p-o5sA93WQJedJdZo,33552
49
+ web3/_utils/math.py,sha256=g6iSVKaKgCofjAC60MC2yTtlhNoezHQppJ3EAbpLwXs,1055
50
+ web3/_utils/method_formatters.py,sha256=kg4xkDXyH-a4CnB-vXL1pYgQWhanVudSNYjVFmkdGC4,33918
51
51
  web3/_utils/module.py,sha256=s3oqAZpR5hlbGrHkFNNtqavNqciAQjNkMrMYke-mYlg,3147
52
52
  web3/_utils/normalizers.py,sha256=jb-tMhWyNKWv1TJyrECwOeyDGAGON67jKb0Iz-Rxlcw,7447
53
53
  web3/_utils/request.py,sha256=PC_UMluqlaJECfiqEyLAiLKff_lz49sOqK0-77iVpw8,8881
54
- web3/_utils/rpc_abi.py,sha256=6-6r7oybsB7delHgZ2w0CXWayYYFIjR0qb7b2X6o98I,9294
54
+ web3/_utils/rpc_abi.py,sha256=IYKHWrHOHpEajZP0mAx4xE5Qr-UzVlF-8SbFzsXBCwg,9357
55
55
  web3/_utils/threads.py,sha256=ZaBg_daNU_eI3nWtyAR8aQYM-ETTSoNchpfRyw6lEbQ,4208
56
- web3/_utils/transactions.py,sha256=5bWHkXvA1RYQlgSOEEZN6QbAl7AqoNQPVp6m3lA8bV0,8737
56
+ web3/_utils/transactions.py,sha256=YaFDLXS69F75WJ9ccXkUJHZLebAJactHFpWR12y7jFk,8839
57
57
  web3/_utils/type_conversion.py,sha256=P9ojTqFASnlFEIA_Pf_BA3YJB4Ok4P0E_aGJw7FinNc,816
58
58
  web3/_utils/utility_methods.py,sha256=7VCpo5ysvPoGjFuDj5gT1Niva2l3BADUvNeJFlL3Yvg,2559
59
59
  web3/_utils/validation.py,sha256=5JBDbu8Azw4bgmN-QARRh6WFiZiX2VABl2zVsv9z0rc,6291
@@ -86,7 +86,7 @@ web3/_utils/contract_sources/contract_data/storage_contract.py,sha256=NhoWNlWltN
86
86
  web3/_utils/contract_sources/contract_data/string_contract.py,sha256=zZdglZ6se_aqMIUKN3-3zR57h8zyDyUQIgtSIXtdSzg,11586
87
87
  web3/_utils/contract_sources/contract_data/tuple_contracts.py,sha256=qt0cGM1Kh-LlRYn04-fpSPQJAWcGrvP8EKPCJvsrnvE,23180
88
88
  web3/_utils/module_testing/__init__.py,sha256=_AuZ0S4xesS7ocRdMHeTN6zju7KqpSsG4NXgmccJonU,455
89
- web3/_utils/module_testing/eth_module.py,sha256=tY5ei3oE0x-kttHXxorYgu_Vr6Qo6ZmzbQRWSL7TcDA,181815
89
+ web3/_utils/module_testing/eth_module.py,sha256=yEYd-at1TFPOWMw2yFd2sRQidkCeMUuwfyjcAoEOeBU,184153
90
90
  web3/_utils/module_testing/go_ethereum_admin_module.py,sha256=_c-6SyzZkfAJ-7ySXUpw9FEr4cg-ShRdAGSAHWanCtY,3406
91
91
  web3/_utils/module_testing/go_ethereum_personal_module.py,sha256=PRX1dxqxGydHWyzcGVa0EP0IUoiSQyDYaszbmmXDKTU,10432
92
92
  web3/_utils/module_testing/go_ethereum_txpool_module.py,sha256=5f8XL8-2x3keyGRaITxMQYl9oQzjgqGn8zobB-j9BPs,1176
@@ -103,13 +103,13 @@ web3/beacon/async_beacon.py,sha256=y7cvbsDYjRNDZftzcJyXaSLCsRrASAGxfyCwE53oCG4,7
103
103
  web3/beacon/beacon.py,sha256=wgSmF-5hu_95L6onnlA33ADDoASFf9OZf-YWnqnY0VY,6640
104
104
  web3/contract/__init__.py,sha256=EX_RmT8D2DDKKsk1U8grCNdLq9b1rF-8xWaR53CBiew,187
105
105
  web3/contract/async_contract.py,sha256=oxxq5Pse4JkrRvPnecbF5eYwKg_FX17ltiHLvxiRj6Q,20392
106
- web3/contract/base_contract.py,sha256=TmG2l61YkX4lFN8u1e4PoqpNp5irx2HA3BfiX_LSVaA,37551
106
+ web3/contract/base_contract.py,sha256=KuexzVWApCVL5c1VTMPZHDI40K20SR_JrqHWfjZJd0o,37552
107
107
  web3/contract/contract.py,sha256=mNrGoMvxdKHRecoMxT7KDEWK0hCKqPoH6DX7yqD78As,19997
108
108
  web3/contract/utils.py,sha256=ozHDwk1JoCYlFV6LX2upYlgQhcW6zOP4eQ0jOHJzboA,12462
109
109
  web3/eth/__init__.py,sha256=CrYZXIlIdKTmznnLNUaA-C3eLvftBnmlVt9uxm-dwAI,124
110
- web3/eth/async_eth.py,sha256=peNTqwrN3whyWQdYJQR6P9oGz8tlriEVWbbctzTOLag,23466
110
+ web3/eth/async_eth.py,sha256=4Ook7jJD93KAk-qs4QNOR-R6ct5F7AvQx3fqQhoMBIY,23929
111
111
  web3/eth/base_eth.py,sha256=WC1BRE1QOhPV417Od2NSu28fnyXTjKQ9YVqTU3W3N0A,6822
112
- web3/eth/eth.py,sha256=MLReiFi2VeFMrgYU706CPXRArsReMuZsD38p1cvWDNw,20460
112
+ web3/eth/eth.py,sha256=4hSSI0bIoGnOdc4yJz2dMH_Wrt3jxcB-3hMqlwU7xI4,20839
113
113
  web3/gas_strategies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
114
114
  web3/gas_strategies/rpc.py,sha256=3Va-32jdmHkX7tzQCmh17ms2D6te5zZcqHP1326BdpY,352
115
115
  web3/gas_strategies/time_based.py,sha256=xWj3WyA8UL76KTNAbMWLiWwD-UYuWyFttclHoXuP1gg,9169
@@ -138,9 +138,9 @@ web3/providers/eth_tester/main.py,sha256=I7NuZT8fA2CoSN-I-3UekcXrY-P1wb7sa6tzeQy
138
138
  web3/providers/eth_tester/middleware.py,sha256=ZV8JFObcCzIKi_Xkne00qW-ttDmp30iTveXJps5IOvU,12882
139
139
  web3/providers/persistent/__init__.py,sha256=S1s8m1cjPOjD-CCrWrLDP0PGlP1FUqgEw2KdrDeMPgk,283
140
140
  web3/providers/persistent/async_ipc.py,sha256=FW01Z5hzT0NE0izCN5AVMZIYbHxpqCR62tzt2xNO6Dw,7277
141
- web3/providers/persistent/persistent.py,sha256=wQpQC-7c268KrUqopgX2EAvwJmt-grHQHjbmKrTyDlA,3550
141
+ web3/providers/persistent/persistent.py,sha256=qvozc8VX8Xv0JFPUcHdHsi6FpdD-QrAirKFinSl2i_I,3556
142
142
  web3/providers/persistent/persistent_connection.py,sha256=56yjpwDMM2phkJ_M5_QB-A6_CjZc5VrkWhNDweA70d0,1109
143
- web3/providers/persistent/request_processor.py,sha256=SLrclcWs7QKL8Cx4K3amGjneB836qYszapmvMyBZwWM,11545
143
+ web3/providers/persistent/request_processor.py,sha256=zneKvSK7nopN0V2qo7O5halnXTUgneJteSibss06YSI,11495
144
144
  web3/providers/persistent/utils.py,sha256=gfY7w1HB8xuE7OujSrbwWYjQuQ8nzRBoxoL8ESinqWM,1140
145
145
  web3/providers/persistent/websocket.py,sha256=N70-qqitPT5eqNdlQrvZXgETabG3ZImTv99111LkgX8,6914
146
146
  web3/providers/rpc/__init__.py,sha256=d20CaZ6vOXlud5sh6I5JnT_zEGBMpbXl-vCDFMxBNoY,89
@@ -150,14 +150,19 @@ web3/providers/rpc/utils.py,sha256=hjw0_tzBvJ6eBsQak9xzo37ODMGhKTAlLjeSoSZk39k,2
150
150
  web3/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
151
151
  web3/scripts/release/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
152
152
  web3/scripts/release/test_package.py,sha256=DH0AryllcF4zfpWSd0NLPSQGHNoC-Qng5WYYbS5_4c8,1534
153
+ web3/tools/benchmark/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
154
+ web3/tools/benchmark/main.py,sha256=OAT7klotT1vnFO5AKo4PB9D9nRTb4BeLl7Lcj55yzcw,5356
155
+ web3/tools/benchmark/node.py,sha256=IYyXmVyACF6R0xch9_9Ow24a7HuH8aOcZ2iA2sxOYvo,3501
156
+ web3/tools/benchmark/reporting.py,sha256=G2bj_Eo2kBV06GARDYK9zr0VqesiR0_5JLKvhAo6zRM,912
157
+ web3/tools/benchmark/utils.py,sha256=GjSofFEq3ugFtpyBlAx7n6cgZrQ5Xu4-hN_36bQBwnA,1722
153
158
  web3/utils/__init__.py,sha256=pswH3MW_mro5zrHn_q8Pto-iS1jrbtEH3UtQ9qioiKM,455
154
159
  web3/utils/abi.py,sha256=naNkD7_XQGV8hd4CkxytLKWCcgzUjkb7q3ERwRVNICI,498
155
160
  web3/utils/address.py,sha256=KC_IpEbixSCuMhaW6V2QCyyJTYKYGS9c8QtI9_aH7zQ,967
156
161
  web3/utils/async_exception_handling.py,sha256=gfLuzP7Y5rc21jZVjWEYAOZUMJkJd9CmsL297UKReow,3096
157
- web3/utils/caching.py,sha256=udHytI9q1i0UdELR5B4DB95yNn1Hzu3AL0Skz2Zul0I,1693
162
+ web3/utils/caching.py,sha256=4U-vh61m1dlslwEn_Nl7ybIlMF4W2IAcvMTH-iFzrNM,1618
158
163
  web3/utils/exception_handling.py,sha256=12xkzIqMAOx0Jcm6PYL98PmWlLPKFll0p9YoLGS_ZNg,3052
159
- web3-7.0.0b2.dist-info/LICENSE,sha256=ulnXiEqqFp9VyWe8yMFdtDi70RMBJk3mpY3FKujv6l8,1090
160
- web3-7.0.0b2.dist-info/METADATA,sha256=icThzoL5lnZpzD97-_-ljvg7XJS6P1TvjhnBWNjcsTw,4502
161
- web3-7.0.0b2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
162
- web3-7.0.0b2.dist-info/top_level.txt,sha256=iwupuJh7wgypXrpk_awszyri3TahRr5vxSphNyvt1bU,9
163
- web3-7.0.0b2.dist-info/RECORD,,
164
+ web3-7.0.0b3.dist-info/LICENSE,sha256=ulnXiEqqFp9VyWe8yMFdtDi70RMBJk3mpY3FKujv6l8,1090
165
+ web3-7.0.0b3.dist-info/METADATA,sha256=thR0SIhg9znLbCimjfWjHS2iwW5OodxYkbSh-8PqV6c,4605
166
+ web3-7.0.0b3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
167
+ web3-7.0.0b3.dist-info/top_level.txt,sha256=iwupuJh7wgypXrpk_awszyri3TahRr5vxSphNyvt1bU,9
168
+ web3-7.0.0b3.dist-info/RECORD,,
File without changes