web3 7.0.0b9__py3-none-any.whl → 7.1.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.
- web3/beacon/api_endpoints.py +3 -0
- web3/beacon/async_beacon.py +18 -2
- web3/beacon/beacon.py +18 -2
- web3/contract/async_contract.py +8 -8
- web3/contract/contract.py +10 -8
- web3/datastructures.py +21 -11
- web3/middleware/base.py +8 -0
- web3/scripts/install_pre_releases.py +33 -0
- web3/scripts/parse_pygeth_version.py +16 -0
- web3/tools/benchmark/__init__.py +0 -0
- web3/tools/benchmark/main.py +190 -0
- web3/tools/benchmark/node.py +120 -0
- web3/tools/benchmark/reporting.py +39 -0
- web3/tools/benchmark/utils.py +69 -0
- {web3-7.0.0b9.dist-info → web3-7.1.0.dist-info}/METADATA +6 -8
- {web3-7.0.0b9.dist-info → web3-7.1.0.dist-info}/RECORD +19 -12
- {web3-7.0.0b9.dist-info → web3-7.1.0.dist-info}/WHEEL +1 -1
- {web3-7.0.0b9.dist-info → web3-7.1.0.dist-info}/LICENSE +0 -0
- {web3-7.0.0b9.dist-info → web3-7.1.0.dist-info}/top_level.txt +0 -0
web3/beacon/api_endpoints.py
CHANGED
|
@@ -26,6 +26,9 @@ GET_BLINDED_BLOCKS = "/eth/v1/beacon/blinded_blocks/{0}"
|
|
|
26
26
|
# rewards
|
|
27
27
|
GET_REWARDS = "/eth/v1/beacon/rewards/blocks/{0}"
|
|
28
28
|
|
|
29
|
+
# blobs
|
|
30
|
+
GET_BLOB_SIDECARS = "/eth/v1/beacon/blob_sidecars/{0}"
|
|
31
|
+
|
|
29
32
|
# light client
|
|
30
33
|
GET_LIGHT_CLIENT_BOOTSTRAP_STRUCTURE = "/eth/v1/beacon/light_client/bootstrap/{0}"
|
|
31
34
|
GET_LIGHT_CLIENT_UPDATES = "/eth/v1/beacon/light_client/updates"
|
web3/beacon/async_beacon.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from typing import (
|
|
2
2
|
Any,
|
|
3
3
|
Dict,
|
|
4
|
+
List,
|
|
5
|
+
Optional,
|
|
4
6
|
)
|
|
5
7
|
|
|
6
8
|
from eth_typing import (
|
|
@@ -17,6 +19,7 @@ from web3.beacon.api_endpoints import (
|
|
|
17
19
|
GET_BEACON_HEADS,
|
|
18
20
|
GET_BEACON_STATE,
|
|
19
21
|
GET_BLINDED_BLOCKS,
|
|
22
|
+
GET_BLOB_SIDECARS,
|
|
20
23
|
GET_BLOCK,
|
|
21
24
|
GET_BLOCK_ATTESTATIONS,
|
|
22
25
|
GET_BLOCK_HEADER,
|
|
@@ -64,10 +67,12 @@ class AsyncBeacon:
|
|
|
64
67
|
self.request_timeout = request_timeout
|
|
65
68
|
self._request_session_manager = HTTPSessionManager()
|
|
66
69
|
|
|
67
|
-
async def _async_make_get_request(
|
|
70
|
+
async def _async_make_get_request(
|
|
71
|
+
self, endpoint_uri: str, params: Optional[Dict[str, str]] = None
|
|
72
|
+
) -> Dict[str, Any]:
|
|
68
73
|
uri = URI(self.base_url + endpoint_uri)
|
|
69
74
|
return await self._request_session_manager.async_json_make_get_request(
|
|
70
|
-
uri, timeout=self.request_timeout
|
|
75
|
+
uri, params=params, timeout=self.request_timeout
|
|
71
76
|
)
|
|
72
77
|
|
|
73
78
|
# [ BEACON endpoints ]
|
|
@@ -220,3 +225,14 @@ class AsyncBeacon:
|
|
|
220
225
|
|
|
221
226
|
async def get_syncing(self) -> Dict[str, Any]:
|
|
222
227
|
return await self._async_make_get_request(GET_SYNCING)
|
|
228
|
+
|
|
229
|
+
# [ BLOB endpoints ]
|
|
230
|
+
|
|
231
|
+
async def get_blob_sidecars(
|
|
232
|
+
self, block_id: str, indices: Optional[List[int]] = None
|
|
233
|
+
) -> Dict[str, Any]:
|
|
234
|
+
indices_param = {"indices": ",".join(map(str, indices))} if indices else None
|
|
235
|
+
return await self._async_make_get_request(
|
|
236
|
+
GET_BLOB_SIDECARS.format(block_id),
|
|
237
|
+
params=indices_param,
|
|
238
|
+
)
|
web3/beacon/beacon.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from typing import (
|
|
2
2
|
Any,
|
|
3
3
|
Dict,
|
|
4
|
+
List,
|
|
5
|
+
Optional,
|
|
4
6
|
)
|
|
5
7
|
|
|
6
8
|
from eth_typing import (
|
|
@@ -17,6 +19,7 @@ from web3.beacon.api_endpoints import (
|
|
|
17
19
|
GET_BEACON_HEADS,
|
|
18
20
|
GET_BEACON_STATE,
|
|
19
21
|
GET_BLINDED_BLOCKS,
|
|
22
|
+
GET_BLOB_SIDECARS,
|
|
20
23
|
GET_BLOCK,
|
|
21
24
|
GET_BLOCK_ATTESTATIONS,
|
|
22
25
|
GET_BLOCK_HEADER,
|
|
@@ -62,10 +65,12 @@ class Beacon:
|
|
|
62
65
|
self.request_timeout = request_timeout
|
|
63
66
|
self._request_session_manager = HTTPSessionManager()
|
|
64
67
|
|
|
65
|
-
def _make_get_request(
|
|
68
|
+
def _make_get_request(
|
|
69
|
+
self, endpoint_url: str, params: Optional[Dict[str, str]] = None
|
|
70
|
+
) -> Dict[str, Any]:
|
|
66
71
|
uri = URI(self.base_url + endpoint_url)
|
|
67
72
|
return self._request_session_manager.json_make_get_request(
|
|
68
|
-
uri, timeout=self.request_timeout
|
|
73
|
+
uri, params=params, timeout=self.request_timeout
|
|
69
74
|
)
|
|
70
75
|
|
|
71
76
|
# [ BEACON endpoints ]
|
|
@@ -206,3 +211,14 @@ class Beacon:
|
|
|
206
211
|
|
|
207
212
|
def get_syncing(self) -> Dict[str, Any]:
|
|
208
213
|
return self._make_get_request(GET_SYNCING)
|
|
214
|
+
|
|
215
|
+
# [ BLOB endpoints ]
|
|
216
|
+
|
|
217
|
+
def get_blob_sidecars(
|
|
218
|
+
self, block_id: str, indices: Optional[List[int]] = None
|
|
219
|
+
) -> Dict[str, Any]:
|
|
220
|
+
indices_param = {"indices": ",".join(map(str, indices))} if indices else None
|
|
221
|
+
return self._make_get_request(
|
|
222
|
+
GET_BLOB_SIDECARS.format(block_id),
|
|
223
|
+
params=indices_param,
|
|
224
|
+
)
|
web3/contract/async_contract.py
CHANGED
|
@@ -319,8 +319,8 @@ class AsyncContractFunction(BaseContractFunction):
|
|
|
319
319
|
state_override,
|
|
320
320
|
ccip_read_enabled,
|
|
321
321
|
self.decode_tuples,
|
|
322
|
-
*self.args,
|
|
323
|
-
**self.kwargs,
|
|
322
|
+
*self.args or (),
|
|
323
|
+
**self.kwargs or {},
|
|
324
324
|
)
|
|
325
325
|
|
|
326
326
|
async def transact(self, transaction: Optional[TxParams] = None) -> HexBytes:
|
|
@@ -332,8 +332,8 @@ class AsyncContractFunction(BaseContractFunction):
|
|
|
332
332
|
setup_transaction,
|
|
333
333
|
self.contract_abi,
|
|
334
334
|
self.abi,
|
|
335
|
-
*self.args,
|
|
336
|
-
**self.kwargs,
|
|
335
|
+
*self.args or (),
|
|
336
|
+
**self.kwargs or {},
|
|
337
337
|
)
|
|
338
338
|
|
|
339
339
|
async def estimate_gas(
|
|
@@ -352,8 +352,8 @@ class AsyncContractFunction(BaseContractFunction):
|
|
|
352
352
|
self.abi,
|
|
353
353
|
block_identifier,
|
|
354
354
|
state_override,
|
|
355
|
-
*self.args,
|
|
356
|
-
**self.kwargs,
|
|
355
|
+
*self.args or (),
|
|
356
|
+
**self.kwargs or {},
|
|
357
357
|
)
|
|
358
358
|
|
|
359
359
|
async def build_transaction(
|
|
@@ -367,8 +367,8 @@ class AsyncContractFunction(BaseContractFunction):
|
|
|
367
367
|
built_transaction,
|
|
368
368
|
self.contract_abi,
|
|
369
369
|
self.abi,
|
|
370
|
-
*self.args,
|
|
371
|
-
**self.kwargs,
|
|
370
|
+
*self.args or (),
|
|
371
|
+
**self.kwargs or {},
|
|
372
372
|
)
|
|
373
373
|
|
|
374
374
|
@staticmethod
|
web3/contract/contract.py
CHANGED
|
@@ -318,12 +318,13 @@ class ContractFunction(BaseContractFunction):
|
|
|
318
318
|
state_override,
|
|
319
319
|
ccip_read_enabled,
|
|
320
320
|
self.decode_tuples,
|
|
321
|
-
*self.args,
|
|
322
|
-
**self.kwargs,
|
|
321
|
+
*self.args or (),
|
|
322
|
+
**self.kwargs or {},
|
|
323
323
|
)
|
|
324
324
|
|
|
325
325
|
def transact(self, transaction: Optional[TxParams] = None) -> HexBytes:
|
|
326
326
|
setup_transaction = self._transact(transaction)
|
|
327
|
+
|
|
327
328
|
return transact_with_contract_function(
|
|
328
329
|
self.address,
|
|
329
330
|
self.w3,
|
|
@@ -331,8 +332,8 @@ class ContractFunction(BaseContractFunction):
|
|
|
331
332
|
setup_transaction,
|
|
332
333
|
self.contract_abi,
|
|
333
334
|
self.abi,
|
|
334
|
-
*self.args,
|
|
335
|
-
**self.kwargs,
|
|
335
|
+
*self.args or (),
|
|
336
|
+
**self.kwargs or {},
|
|
336
337
|
)
|
|
337
338
|
|
|
338
339
|
def estimate_gas(
|
|
@@ -351,12 +352,13 @@ class ContractFunction(BaseContractFunction):
|
|
|
351
352
|
self.abi,
|
|
352
353
|
block_identifier,
|
|
353
354
|
state_override,
|
|
354
|
-
*self.args,
|
|
355
|
-
**self.kwargs,
|
|
355
|
+
*self.args or (),
|
|
356
|
+
**self.kwargs or {},
|
|
356
357
|
)
|
|
357
358
|
|
|
358
359
|
def build_transaction(self, transaction: Optional[TxParams] = None) -> TxParams:
|
|
359
360
|
built_transaction = self._build_transaction(transaction)
|
|
361
|
+
|
|
360
362
|
return build_transaction_for_function(
|
|
361
363
|
self.address,
|
|
362
364
|
self.w3,
|
|
@@ -364,8 +366,8 @@ class ContractFunction(BaseContractFunction):
|
|
|
364
366
|
built_transaction,
|
|
365
367
|
self.contract_abi,
|
|
366
368
|
self.abi,
|
|
367
|
-
*self.args,
|
|
368
|
-
**self.kwargs,
|
|
369
|
+
*self.args or (),
|
|
370
|
+
**self.kwargs or {},
|
|
369
371
|
)
|
|
370
372
|
|
|
371
373
|
@staticmethod
|
web3/datastructures.py
CHANGED
|
@@ -182,7 +182,7 @@ class NamedElementOnion(Mapping[TKey, TValue]):
|
|
|
182
182
|
if name is None:
|
|
183
183
|
name = cast(TKey, element)
|
|
184
184
|
|
|
185
|
-
name = self.
|
|
185
|
+
name = self._build_name(name)
|
|
186
186
|
|
|
187
187
|
if name in self._queue:
|
|
188
188
|
if name is element:
|
|
@@ -219,7 +219,7 @@ class NamedElementOnion(Mapping[TKey, TValue]):
|
|
|
219
219
|
if name is None:
|
|
220
220
|
name = cast(TKey, element)
|
|
221
221
|
|
|
222
|
-
name = self.
|
|
222
|
+
name = self._build_name(name)
|
|
223
223
|
|
|
224
224
|
self._queue.move_to_end(name, last=False)
|
|
225
225
|
elif layer == len(self._queue):
|
|
@@ -233,7 +233,7 @@ class NamedElementOnion(Mapping[TKey, TValue]):
|
|
|
233
233
|
self._queue.clear()
|
|
234
234
|
|
|
235
235
|
def replace(self, old: TKey, new: TKey) -> TValue:
|
|
236
|
-
old_name = self.
|
|
236
|
+
old_name = self._build_name(old)
|
|
237
237
|
|
|
238
238
|
if old_name not in self._queue:
|
|
239
239
|
raise Web3ValueError(
|
|
@@ -248,15 +248,25 @@ class NamedElementOnion(Mapping[TKey, TValue]):
|
|
|
248
248
|
self._queue[old_name] = new
|
|
249
249
|
return to_be_replaced
|
|
250
250
|
|
|
251
|
-
|
|
251
|
+
@staticmethod
|
|
252
|
+
def _build_name(value: TKey) -> TKey:
|
|
252
253
|
try:
|
|
253
254
|
value.__hash__()
|
|
255
|
+
return value
|
|
254
256
|
except TypeError:
|
|
255
|
-
|
|
256
|
-
|
|
257
|
+
# unhashable, unnamed elements
|
|
258
|
+
if not callable(value):
|
|
259
|
+
raise Web3TypeError(
|
|
260
|
+
f"Expected a callable or hashable type, got {type(value)}"
|
|
261
|
+
)
|
|
262
|
+
# This will either be ``Web3Middleware`` class or the ``build`` method of a
|
|
263
|
+
# ``Web3MiddlewareBuilder``. Instantiate with empty ``Web3`` and use a
|
|
264
|
+
# unique identifier with the ``__hash__()`` as the name.
|
|
265
|
+
v = value(None)
|
|
266
|
+
return cast(TKey, f"{v.__class__}<{v.__hash__()}>")
|
|
257
267
|
|
|
258
268
|
def remove(self, old: TKey) -> None:
|
|
259
|
-
old_name = self.
|
|
269
|
+
old_name = self._build_name(old)
|
|
260
270
|
if old_name not in self._queue:
|
|
261
271
|
raise Web3ValueError("You can only remove something that has been added")
|
|
262
272
|
del self._queue[old_name]
|
|
@@ -270,8 +280,8 @@ class NamedElementOnion(Mapping[TKey, TValue]):
|
|
|
270
280
|
return [(val, key) for key, val in reversed(self._queue.items())]
|
|
271
281
|
|
|
272
282
|
def _replace_with_new_name(self, old: TKey, new: TKey) -> None:
|
|
273
|
-
old_name = self.
|
|
274
|
-
new_name = self.
|
|
283
|
+
old_name = self._build_name(old)
|
|
284
|
+
new_name = self._build_name(new)
|
|
275
285
|
|
|
276
286
|
self._queue[new_name] = new
|
|
277
287
|
found_old = False
|
|
@@ -293,11 +303,11 @@ class NamedElementOnion(Mapping[TKey, TValue]):
|
|
|
293
303
|
return NamedElementOnion(cast(List[Any], combined.items()))
|
|
294
304
|
|
|
295
305
|
def __contains__(self, element: Any) -> bool:
|
|
296
|
-
element_name = self.
|
|
306
|
+
element_name = self._build_name(element)
|
|
297
307
|
return element_name in self._queue
|
|
298
308
|
|
|
299
309
|
def __getitem__(self, element: TKey) -> TValue:
|
|
300
|
-
element_name = self.
|
|
310
|
+
element_name = self._build_name(element)
|
|
301
311
|
return self._queue[element_name]
|
|
302
312
|
|
|
303
313
|
def __len__(self) -> int:
|
web3/middleware/base.py
CHANGED
|
@@ -40,6 +40,14 @@ class Web3Middleware:
|
|
|
40
40
|
def __init__(self, w3: Union["AsyncWeb3", "Web3"]) -> None:
|
|
41
41
|
self._w3 = w3
|
|
42
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
|
+
|
|
43
51
|
# -- sync -- #
|
|
44
52
|
|
|
45
53
|
def wrap_make_request(self, make_request: "MakeRequestFn") -> "MakeRequestFn":
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The goal of this script is to install the latest versions, including pre-releases, for
|
|
3
|
+
libraries that we maintain (and therefore control the release process) during our CI
|
|
4
|
+
runs. This helps us test pre-releases before they cause any issues once stable versions
|
|
5
|
+
are released.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import subprocess
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
ETHEREUM_LIBRARIES = [
|
|
12
|
+
"eth-account",
|
|
13
|
+
"eth-abi",
|
|
14
|
+
"eth-account",
|
|
15
|
+
"eth-hash[pycryptodome]",
|
|
16
|
+
"eth-typing",
|
|
17
|
+
"eth-utils",
|
|
18
|
+
"hexbytes",
|
|
19
|
+
"eth-tester[py-evm]",
|
|
20
|
+
"py-geth",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def install_eth_pre_releases() -> None:
|
|
25
|
+
for lib in ETHEREUM_LIBRARIES:
|
|
26
|
+
print(f"Installing {lib} with `--pre` and `-U`")
|
|
27
|
+
subprocess.check_call(
|
|
28
|
+
[sys.executable, "-m", "pip", "install", "--pre", "-U", lib]
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
if __name__ == "__main__":
|
|
33
|
+
install_eth_pre_releases()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_pygeth_version() -> str:
|
|
5
|
+
with open("setup.py") as f:
|
|
6
|
+
setup_contents = f.read()
|
|
7
|
+
version_match = re.search(r"py-geth\s*([><=~!]+)\s*([\d.]+)", setup_contents)
|
|
8
|
+
if version_match:
|
|
9
|
+
return "".join(version_match.group(1, 2))
|
|
10
|
+
else:
|
|
11
|
+
raise ValueError("py-geth not found in setup.py")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
if __name__ == "__main__":
|
|
15
|
+
version = get_pygeth_version()
|
|
16
|
+
print(version)
|
|
File without changes
|
|
@@ -0,0 +1,190 @@
|
|
|
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
|
+
account = w3_http.eth.accounts[0]
|
|
112
|
+
|
|
113
|
+
# -- async -- #
|
|
114
|
+
async_w3_http = loop.run_until_complete(
|
|
115
|
+
build_async_w3_http(fixture.endpoint_uri)
|
|
116
|
+
)
|
|
117
|
+
async_accounts = loop.run_until_complete(async_w3_http.eth.accounts)
|
|
118
|
+
async_account = async_accounts[0]
|
|
119
|
+
|
|
120
|
+
methods = [
|
|
121
|
+
{
|
|
122
|
+
"name": "eth_gasPrice",
|
|
123
|
+
"params": {},
|
|
124
|
+
"exec": lambda w3_http=w3_http: w3_http.eth.gas_price,
|
|
125
|
+
"async_exec": lambda async_w3_http=async_w3_http: async_w3_http.eth.gas_price, # noqa: E501
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"name": "eth_sendTransaction",
|
|
129
|
+
"params": {},
|
|
130
|
+
"exec": lambda w3_http=w3_http, account=account: w3_http.eth.send_transaction( # noqa: E501
|
|
131
|
+
{
|
|
132
|
+
"to": "0xd3CdA913deB6f67967B99D67aCDFa1712C293601",
|
|
133
|
+
"from": account,
|
|
134
|
+
"value": Wei(1),
|
|
135
|
+
}
|
|
136
|
+
),
|
|
137
|
+
"async_exec": lambda async_w3_http=async_w3_http, async_account=async_account: async_w3_http.eth.send_transaction( # noqa: E501
|
|
138
|
+
{
|
|
139
|
+
"to": "0xd3CdA913deB6f67967B99D67aCDFa1712C293601",
|
|
140
|
+
"from": async_account,
|
|
141
|
+
"value": Wei(1),
|
|
142
|
+
}
|
|
143
|
+
),
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"name": "eth_blockNumber",
|
|
147
|
+
"params": {},
|
|
148
|
+
"exec": lambda w3_http=w3_http: w3_http.eth.block_number,
|
|
149
|
+
"async_exec": lambda async_w3_http=async_w3_http: async_w3_http.eth.block_number, # noqa: E501
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"name": "eth_getBlock",
|
|
153
|
+
"params": {},
|
|
154
|
+
"exec": lambda w3_http=w3_http: w3_http.eth.get_block(1),
|
|
155
|
+
"async_exec": lambda async_w3_http=async_w3_http: async_w3_http.eth.get_block( # noqa: E501
|
|
156
|
+
1
|
|
157
|
+
),
|
|
158
|
+
},
|
|
159
|
+
]
|
|
160
|
+
|
|
161
|
+
def benchmark(
|
|
162
|
+
method: Dict[str, Any], loop: asyncio.AbstractEventLoop = loop
|
|
163
|
+
) -> None:
|
|
164
|
+
outcomes: Dict[str, Union[str, float]] = defaultdict(lambda: "N/A")
|
|
165
|
+
outcomes["name"] = method["name"]
|
|
166
|
+
outcomes["HTTPProvider"] = sync_benchmark(
|
|
167
|
+
method["exec"],
|
|
168
|
+
num_calls,
|
|
169
|
+
)
|
|
170
|
+
outcomes["AsyncHTTPProvider"] = loop.run_until_complete(
|
|
171
|
+
async_benchmark(method["async_exec"], num_calls)
|
|
172
|
+
)
|
|
173
|
+
print_entry(logger, outcomes)
|
|
174
|
+
|
|
175
|
+
print_header(logger, num_calls)
|
|
176
|
+
|
|
177
|
+
for method in methods:
|
|
178
|
+
benchmark(method)
|
|
179
|
+
|
|
180
|
+
print_footer(logger)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
if __name__ == "__main__":
|
|
184
|
+
args = parser.parse_args()
|
|
185
|
+
|
|
186
|
+
logger = logging.getLogger()
|
|
187
|
+
logger.setLevel(logging.INFO)
|
|
188
|
+
logger.addHandler(logging.StreamHandler(sys.stdout))
|
|
189
|
+
|
|
190
|
+
main(logger, args.num_calls)
|
|
@@ -0,0 +1,120 @@
|
|
|
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.14.5-fixture.zip"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class GethBenchmarkFixture:
|
|
31
|
+
def __init__(self) -> None:
|
|
32
|
+
self.rpc_port = self._rpc_port()
|
|
33
|
+
self.endpoint_uri = self._endpoint_uri()
|
|
34
|
+
self.geth_binary = self._geth_binary()
|
|
35
|
+
|
|
36
|
+
def build(self) -> Generator[Any, None, None]:
|
|
37
|
+
with TemporaryDirectory() as base_dir:
|
|
38
|
+
zipfile_path = os.path.abspath(
|
|
39
|
+
os.path.join(
|
|
40
|
+
os.path.dirname(__file__),
|
|
41
|
+
"../../../tests/integration/",
|
|
42
|
+
GETH_FIXTURE_ZIP,
|
|
43
|
+
)
|
|
44
|
+
)
|
|
45
|
+
tmp_datadir = os.path.join(str(base_dir), "datadir")
|
|
46
|
+
with zipfile.ZipFile(zipfile_path, "r") as zip_ref:
|
|
47
|
+
zip_ref.extractall(tmp_datadir)
|
|
48
|
+
self.datadir = tmp_datadir
|
|
49
|
+
|
|
50
|
+
genesis_file = os.path.join(self.datadir, "genesis.json")
|
|
51
|
+
|
|
52
|
+
yield self._geth_process(self.datadir, genesis_file, self.rpc_port)
|
|
53
|
+
|
|
54
|
+
def _rpc_port(self) -> str:
|
|
55
|
+
sock = socket.socket()
|
|
56
|
+
sock.bind(("127.0.0.1", 0))
|
|
57
|
+
port = sock.getsockname()[1]
|
|
58
|
+
sock.close()
|
|
59
|
+
return str(port)
|
|
60
|
+
|
|
61
|
+
def _endpoint_uri(self) -> str:
|
|
62
|
+
return f"http://localhost:{self.rpc_port}"
|
|
63
|
+
|
|
64
|
+
def _geth_binary(self) -> str:
|
|
65
|
+
if "GETH_BINARY" in os.environ:
|
|
66
|
+
return os.environ["GETH_BINARY"]
|
|
67
|
+
elif "GETH_VERSION" in os.environ:
|
|
68
|
+
geth_version = os.environ["GETH_VERSION"]
|
|
69
|
+
_geth_binary = get_executable_path(geth_version)
|
|
70
|
+
if not os.path.exists(_geth_binary):
|
|
71
|
+
install_geth(geth_version)
|
|
72
|
+
assert os.path.exists(_geth_binary)
|
|
73
|
+
return _geth_binary
|
|
74
|
+
else:
|
|
75
|
+
return "geth"
|
|
76
|
+
|
|
77
|
+
def _geth_command_arguments(self, datadir: str) -> Sequence[str]:
|
|
78
|
+
return (
|
|
79
|
+
self.geth_binary,
|
|
80
|
+
"--dev",
|
|
81
|
+
"--dev.period",
|
|
82
|
+
"100",
|
|
83
|
+
"--datadir",
|
|
84
|
+
datadir,
|
|
85
|
+
"--nodiscover",
|
|
86
|
+
"--http",
|
|
87
|
+
"--http.port",
|
|
88
|
+
self.rpc_port,
|
|
89
|
+
"--http.api",
|
|
90
|
+
"admin,eth,net,web3",
|
|
91
|
+
"--ipcdisable",
|
|
92
|
+
"--password",
|
|
93
|
+
os.path.join(datadir, "keystore", "pw.txt"),
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
def _geth_process(
|
|
97
|
+
self, datadir: str, genesis_file: str, rpc_port: str
|
|
98
|
+
) -> Generator[Any, None, None]:
|
|
99
|
+
init_datadir_command = (
|
|
100
|
+
self.geth_binary,
|
|
101
|
+
"--datadir",
|
|
102
|
+
str(datadir),
|
|
103
|
+
"init",
|
|
104
|
+
str(genesis_file),
|
|
105
|
+
)
|
|
106
|
+
check_output(
|
|
107
|
+
init_datadir_command,
|
|
108
|
+
stdin=PIPE,
|
|
109
|
+
stderr=PIPE,
|
|
110
|
+
)
|
|
111
|
+
proc = Popen(
|
|
112
|
+
self._geth_command_arguments(datadir),
|
|
113
|
+
stdin=PIPE,
|
|
114
|
+
stdout=PIPE,
|
|
115
|
+
stderr=PIPE,
|
|
116
|
+
)
|
|
117
|
+
try:
|
|
118
|
+
yield proc
|
|
119
|
+
finally:
|
|
120
|
+
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 OSError:
|
|
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)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: web3
|
|
3
|
-
Version: 7.0
|
|
3
|
+
Version: 7.1.0
|
|
4
4
|
Summary: web3: A Python library for interacting with Ethereum
|
|
5
5
|
Home-page: https://github.com/ethereum/web3.py
|
|
6
6
|
Author: The Ethereum Foundation
|
|
@@ -20,13 +20,13 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
20
20
|
Requires-Python: >=3.8, <4
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
License-File: LICENSE
|
|
23
|
-
Requires-Dist: aiohttp >=3.7.4.post0
|
|
24
23
|
Requires-Dist: eth-abi >=5.0.1
|
|
25
24
|
Requires-Dist: eth-account >=0.13.1
|
|
26
25
|
Requires-Dist: eth-hash[pycryptodome] >=0.5.1
|
|
27
|
-
Requires-Dist: eth-typing >=5.0.
|
|
28
|
-
Requires-Dist: eth-utils >=5.0.
|
|
26
|
+
Requires-Dist: eth-typing >=5.0.0
|
|
27
|
+
Requires-Dist: eth-utils >=5.0.0
|
|
29
28
|
Requires-Dist: hexbytes >=1.2.0
|
|
29
|
+
Requires-Dist: aiohttp >=3.7.4.post0
|
|
30
30
|
Requires-Dist: pydantic >=2.4.0
|
|
31
31
|
Requires-Dist: requests >=2.23.0
|
|
32
32
|
Requires-Dist: typing-extensions >=4.0.1
|
|
@@ -53,9 +53,8 @@ Requires-Dist: sphinx >=6.0.0 ; extra == 'dev'
|
|
|
53
53
|
Requires-Dist: sphinx-autobuild >=2021.3.14 ; extra == 'dev'
|
|
54
54
|
Requires-Dist: sphinx-rtd-theme >=1.0.0 ; extra == 'dev'
|
|
55
55
|
Requires-Dist: towncrier <22,>=21 ; extra == 'dev'
|
|
56
|
-
Requires-Dist: eth-account >=0.13.0 ; extra == 'dev'
|
|
57
56
|
Requires-Dist: eth-tester[py-evm] <0.13.0b1,>=0.11.0b1 ; extra == 'dev'
|
|
58
|
-
Requires-Dist: py-geth >=5.0.
|
|
57
|
+
Requires-Dist: py-geth >=5.0.0 ; extra == 'dev'
|
|
59
58
|
Requires-Dist: pytest-asyncio <0.23,>=0.18.1 ; extra == 'dev'
|
|
60
59
|
Requires-Dist: pytest-xdist >=2.4.0 ; extra == 'dev'
|
|
61
60
|
Requires-Dist: pytest >=7.0.0 ; extra == 'dev'
|
|
@@ -64,10 +63,9 @@ Requires-Dist: sphinx >=6.0.0 ; extra == 'docs'
|
|
|
64
63
|
Requires-Dist: sphinx-autobuild >=2021.3.14 ; extra == 'docs'
|
|
65
64
|
Requires-Dist: sphinx-rtd-theme >=1.0.0 ; extra == 'docs'
|
|
66
65
|
Requires-Dist: towncrier <22,>=21 ; extra == 'docs'
|
|
67
|
-
Requires-Dist: eth-account >=0.13.0 ; extra == 'docs'
|
|
68
66
|
Provides-Extra: test
|
|
69
67
|
Requires-Dist: eth-tester[py-evm] <0.13.0b1,>=0.11.0b1 ; extra == 'test'
|
|
70
|
-
Requires-Dist: py-geth >=5.0.
|
|
68
|
+
Requires-Dist: py-geth >=5.0.0 ; extra == 'test'
|
|
71
69
|
Requires-Dist: pytest-asyncio <0.23,>=0.18.1 ; extra == 'test'
|
|
72
70
|
Requires-Dist: pytest-mock >=1.10 ; extra == 'test'
|
|
73
71
|
Requires-Dist: pytest-xdist >=2.4.0 ; extra == 'test'
|
|
@@ -13,7 +13,7 @@ ens/specs/nf.json,sha256=kGZcTE_UxTl3WZwMUP6m8KbQQOKdw7PWzmuW7ewQSUs,48403
|
|
|
13
13
|
ens/specs/normalization_spec.json,sha256=xn3N9a-6KHMLu3MeCBsmOxSzIzUQykzE9EscKK1a3w8,3115334
|
|
14
14
|
web3/__init__.py,sha256=P11QAEV_GYoZq9ij8gDzFx5tKzJY2aMXG-keg2Lg1xs,1277
|
|
15
15
|
web3/constants.py,sha256=eQLRQVMFPbgpOjjkPTMHkY-syncJuO-sPX5UrCSRjzQ,564
|
|
16
|
-
web3/datastructures.py,sha256=
|
|
16
|
+
web3/datastructures.py,sha256=LbUsfE0icgRRTXsC_LATR-LtmO7MAYwYB5D-6LCX1jE,11366
|
|
17
17
|
web3/exceptions.py,sha256=5Yc-tUdmcnwGv1dxg45iD3Tor3IKMfedA9U_xZ4AR3M,9081
|
|
18
18
|
web3/geth.py,sha256=IQYeqiVSqcskuXWgDR35UBuVsD-whhvTpDltO4vvCvE,5867
|
|
19
19
|
web3/logs.py,sha256=ROs-mDMH_ZOecE7hfbWA5yp27G38FbLjX4lO_WtlZxQ,198
|
|
@@ -97,13 +97,13 @@ web3/_utils/module_testing/web3_module.py,sha256=7c6penGbHn381fPTYY6DsXKv56xGQpY
|
|
|
97
97
|
web3/auto/__init__.py,sha256=ZbzAiCZMdt_tCTTPvH6t8NCVNroKKkt7TSVBBNR74Is,44
|
|
98
98
|
web3/auto/gethdev.py,sha256=MuWD2gxv0xDv_SzPsp9mSkS1oG4P54xFK83qw9NvswA,438
|
|
99
99
|
web3/beacon/__init__.py,sha256=Ac6YiNgU8D8Ynnh5RwSCx2NwPyjnpFjpXeHuSssFbaU,113
|
|
100
|
-
web3/beacon/api_endpoints.py,sha256=
|
|
101
|
-
web3/beacon/async_beacon.py,sha256=
|
|
102
|
-
web3/beacon/beacon.py,sha256=
|
|
100
|
+
web3/beacon/api_endpoints.py,sha256=0mHrYFYAWHfF9OGzrFdg012L_ocU2nGDXUTU1isOo7o,2272
|
|
101
|
+
web3/beacon/async_beacon.py,sha256=9-V-rfPwj-SbksHKSYs2Quk8frE2AJXjH908cbSM8v0,8098
|
|
102
|
+
web3/beacon/beacon.py,sha256=tPA9ABPm6MyzbzutiphkhFzOAxLresmftG5UjWkuNyY,7236
|
|
103
103
|
web3/contract/__init__.py,sha256=qeZRtTw9xriwoD82w6vePDuPBZ35-CMVdkzViBSH3Qs,293
|
|
104
|
-
web3/contract/async_contract.py,sha256=
|
|
104
|
+
web3/contract/async_contract.py,sha256=KYB-e1GCTZINTRu0Y1f2IIp4LWg2UvKIRFFSIrsjfUs,20593
|
|
105
105
|
web3/contract/base_contract.py,sha256=qfYzMC-PlefkAQVGplXwdYi5I37DwEe5Slbp5-oOc6U,38053
|
|
106
|
-
web3/contract/contract.py,sha256=
|
|
106
|
+
web3/contract/contract.py,sha256=wB5g6H7PoAyp4wN__3GGXMrDCvEYuj6crZL4Q2ipTRE,20174
|
|
107
107
|
web3/contract/utils.py,sha256=bonHXESnb9xhvMzJoi271qppwpy2D6yaHtUwt56wEJc,17853
|
|
108
108
|
web3/eth/__init__.py,sha256=qDLxOcHHIzzPD7xzwy6Wcs0lLPQieB7WN0Ax25ctit8,197
|
|
109
109
|
web3/eth/async_eth.py,sha256=elPH3Atkayk3afwepDRP3ibB7EK8MziK0fPikpKCLxI,23176
|
|
@@ -114,7 +114,7 @@ web3/gas_strategies/rpc.py,sha256=3Va-32jdmHkX7tzQCmh17ms2D6te5zZcqHP1326BdpY,35
|
|
|
114
114
|
web3/gas_strategies/time_based.py,sha256=oGk6nBUD4iMC8wl1vzf-nhURaqyPWYdPvNU0C3RIs8g,9071
|
|
115
115
|
web3/middleware/__init__.py,sha256=fSmPCYJOO8Qp5p-Vm_Z4XPJATu2qN7KJRypYNSO6_uM,2830
|
|
116
116
|
web3/middleware/attrdict.py,sha256=NY5yxlFOfLBBmcIjl8R-uP2dTz9ITIyTttG8-QcJWCI,2259
|
|
117
|
-
web3/middleware/base.py,sha256=
|
|
117
|
+
web3/middleware/base.py,sha256=aHBUWc5pSohLUZ7zcCgrVqp_H_1PTqh31x2n6vWqzuY,5376
|
|
118
118
|
web3/middleware/buffered_gas_estimate.py,sha256=EmxUd-uO959UVroPsPKkl7oDa8Tw6N8BQLB6Urng5Eo,1647
|
|
119
119
|
web3/middleware/filter.py,sha256=I09sSE_q_dhWX5_24KVWhVXZNevwViI7wucJBP4TZl4,22221
|
|
120
120
|
web3/middleware/formatting.py,sha256=hqe5XQE1n5Fmj6riJp7i3oIoZkd-4ChQc7UK8f3HB6I,7567
|
|
@@ -147,16 +147,23 @@ web3/providers/rpc/async_rpc.py,sha256=hibsCoyrAD199ExAEyHRsEnZ0_rDP_2EC2k5g-D2z
|
|
|
147
147
|
web3/providers/rpc/rpc.py,sha256=ePlGdlkvQTaf2Wi2khxiY-rRj-OFcPlpDMuTPLKaAyU,5655
|
|
148
148
|
web3/providers/rpc/utils.py,sha256=_mtoZMMIoZpPA8J8U5DfRxaNQmi8bw0ZVUiqn1Nz4co,2154
|
|
149
149
|
web3/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
150
|
+
web3/scripts/install_pre_releases.py,sha256=uVxsZk239640yxiqlPhfXxZKSsh3858pURKppi9kM5U,821
|
|
151
|
+
web3/scripts/parse_pygeth_version.py,sha256=BZjWOsJmYuFbAnFuB1jec9Rl6z0tJJNFFV38sJvDfGo,416
|
|
150
152
|
web3/scripts/release/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
151
153
|
web3/scripts/release/test_package.py,sha256=DH0AryllcF4zfpWSd0NLPSQGHNoC-Qng5WYYbS5_4c8,1534
|
|
154
|
+
web3/tools/benchmark/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
155
|
+
web3/tools/benchmark/main.py,sha256=9nBC8yvdiNPoRuNlcqKC6HKWly_iwOYSeG0cOQCjfpg,5810
|
|
156
|
+
web3/tools/benchmark/node.py,sha256=n73GckmBKLm4_urC7HfF_Z3ZURffNMjq6ymzb9HM9c8,3252
|
|
157
|
+
web3/tools/benchmark/reporting.py,sha256=G2bj_Eo2kBV06GARDYK9zr0VqesiR0_5JLKvhAo6zRM,912
|
|
158
|
+
web3/tools/benchmark/utils.py,sha256=7OOdUD71AVWi0cowAE9ekMgqlfcJwk3vrNnMCHtiGdU,1696
|
|
152
159
|
web3/utils/__init__.py,sha256=XwpyVR4EBkfqV5SHBH3maNyNBy624EwqujRgetLc7PU,1781
|
|
153
160
|
web3/utils/abi.py,sha256=iSBaCW41UxB1q1UHDPwJ1QJbdiuYmTWNu8m6E28DqlY,18672
|
|
154
161
|
web3/utils/address.py,sha256=KC_IpEbixSCuMhaW6V2QCyyJTYKYGS9c8QtI9_aH7zQ,967
|
|
155
162
|
web3/utils/async_exception_handling.py,sha256=GZWSBFC0-Wmwz1tpTie-1AKRbIQH7JkmBpf5bXrUTzY,3320
|
|
156
163
|
web3/utils/caching.py,sha256=IG_IxW-jyiRklrIyUgjOj3GQvcXrok0KLDX3ch_6wuA,2390
|
|
157
164
|
web3/utils/exception_handling.py,sha256=k31JROfUyKIm9PoEWOtYSkIq9wL8SOBwQfnSLNQyfnM,3097
|
|
158
|
-
web3-7.0.
|
|
159
|
-
web3-7.0.
|
|
160
|
-
web3-7.0.
|
|
161
|
-
web3-7.0.
|
|
162
|
-
web3-7.0.
|
|
165
|
+
web3-7.1.0.dist-info/LICENSE,sha256=ScEyLx1vWrB0ybKiZKKTXm5QhVksHCEUtTp4lwYV45I,1095
|
|
166
|
+
web3-7.1.0.dist-info/METADATA,sha256=p_1iA6mObqMRYbT9SN-0xI9fr_Wh-AN6-fZcOknn1BU,4986
|
|
167
|
+
web3-7.1.0.dist-info/WHEEL,sha256=UvcQYKBHoFqaQd6LKyqHw9fxEolWLQnlzP0h_LgJAfI,91
|
|
168
|
+
web3-7.1.0.dist-info/top_level.txt,sha256=iwupuJh7wgypXrpk_awszyri3TahRr5vxSphNyvt1bU,9
|
|
169
|
+
web3-7.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|