web3 7.0.0b2__py3-none-any.whl → 7.0.0b4__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/_normalization.py +1 -3
- ens/async_ens.py +14 -11
- ens/contract_data.py +2 -2
- ens/ens.py +10 -7
- ens/exceptions.py +19 -27
- ens/specs/nf.json +1 -1
- ens/specs/normalization_spec.json +1 -1
- ens/utils.py +24 -15
- web3/__init__.py +2 -7
- web3/_utils/abi.py +30 -29
- web3/_utils/async_transactions.py +7 -4
- web3/_utils/blocks.py +6 -2
- web3/_utils/caching.py +7 -3
- web3/_utils/compat/__init__.py +0 -3
- web3/_utils/contract_sources/compile_contracts.py +1 -1
- web3/_utils/contracts.py +12 -12
- web3/_utils/datatypes.py +5 -1
- web3/_utils/decorators.py +6 -1
- web3/_utils/empty.py +1 -1
- web3/_utils/encoding.py +15 -10
- web3/_utils/error_formatters_utils.py +5 -3
- web3/_utils/events.py +35 -24
- web3/_utils/fee_utils.py +2 -4
- web3/_utils/filters.py +17 -12
- web3/_utils/formatters.py +2 -2
- web3/_utils/math.py +14 -15
- web3/_utils/method_formatters.py +31 -5
- web3/_utils/module.py +2 -1
- web3/_utils/module_testing/eth_module.py +129 -75
- web3/_utils/module_testing/go_ethereum_personal_module.py +1 -1
- web3/_utils/module_testing/module_testing_utils.py +1 -3
- web3/_utils/module_testing/utils.py +14 -7
- web3/_utils/normalizers.py +3 -3
- web3/_utils/request.py +4 -4
- web3/_utils/rpc_abi.py +6 -1
- web3/_utils/threads.py +8 -7
- web3/_utils/transactions.py +18 -12
- web3/_utils/type_conversion.py +5 -1
- web3/_utils/validation.py +12 -10
- web3/contract/async_contract.py +12 -7
- web3/contract/base_contract.py +51 -57
- web3/contract/contract.py +12 -6
- web3/contract/utils.py +11 -6
- web3/datastructures.py +22 -12
- web3/eth/async_eth.py +53 -30
- web3/eth/base_eth.py +7 -3
- web3/eth/eth.py +31 -14
- web3/exceptions.py +41 -59
- web3/gas_strategies/time_based.py +2 -4
- web3/geth.py +1 -3
- web3/main.py +6 -2
- web3/manager.py +13 -12
- web3/method.py +13 -5
- web3/middleware/base.py +4 -2
- web3/middleware/filter.py +27 -17
- web3/middleware/formatting.py +6 -3
- web3/middleware/names.py +4 -1
- web3/middleware/signing.py +6 -2
- web3/middleware/stalecheck.py +2 -1
- web3/providers/eth_tester/defaults.py +1 -1
- web3/providers/eth_tester/main.py +5 -4
- web3/providers/eth_tester/middleware.py +10 -1
- web3/providers/ipc.py +7 -3
- web3/providers/persistent/async_ipc.py +6 -7
- web3/providers/persistent/persistent.py +12 -2
- web3/providers/persistent/request_processor.py +10 -12
- web3/providers/persistent/websocket.py +3 -3
- web3/providers/rpc/async_rpc.py +23 -6
- web3/providers/rpc/rpc.py +27 -16
- web3/testing.py +4 -4
- web3/tools/benchmark/__init__.py +0 -0
- web3/tools/benchmark/main.py +189 -0
- web3/tools/benchmark/node.py +126 -0
- web3/tools/benchmark/reporting.py +39 -0
- web3/tools/benchmark/utils.py +69 -0
- web3/tracing.py +9 -5
- web3/types.py +23 -22
- web3/utils/caching.py +2 -4
- {web3-7.0.0b2.dist-info → web3-7.0.0b4.dist-info}/METADATA +13 -26
- {web3-7.0.0b2.dist-info → web3-7.0.0b4.dist-info}/RECORD +83 -78
- {web3-7.0.0b2.dist-info → web3-7.0.0b4.dist-info}/LICENSE +0 -0
- {web3-7.0.0b2.dist-info → web3-7.0.0b4.dist-info}/WHEEL +0 -0
- {web3-7.0.0b2.dist-info → web3-7.0.0b4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,189 @@
|
|
|
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=w3_http: w3_http.eth.gas_price,
|
|
124
|
+
"async_exec": lambda async_w3_http=async_w3_http: async_w3_http.eth.gas_price, # noqa: E501
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"name": "eth_sendTransaction",
|
|
128
|
+
"params": {},
|
|
129
|
+
"exec": lambda w3_http=w3_http, coinbase=coinbase: w3_http.eth.send_transaction( # noqa: E501
|
|
130
|
+
{
|
|
131
|
+
"to": "0xd3CdA913deB6f67967B99D67aCDFa1712C293601",
|
|
132
|
+
"from": coinbase,
|
|
133
|
+
"value": Wei(1),
|
|
134
|
+
}
|
|
135
|
+
),
|
|
136
|
+
"async_exec": lambda async_w3_http=async_w3_http, async_coinbase=async_coinbase: async_w3_http.eth.send_transaction( # noqa: E501
|
|
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=w3_http: w3_http.eth.block_number,
|
|
148
|
+
"async_exec": lambda async_w3_http=async_w3_http: async_w3_http.eth.block_number, # noqa: E501
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"name": "eth_getBlock",
|
|
152
|
+
"params": {},
|
|
153
|
+
"exec": lambda w3_http=w3_http: w3_http.eth.get_block(1),
|
|
154
|
+
"async_exec": lambda async_w3_http=async_w3_http: async_w3_http.eth.get_block( # noqa: E501
|
|
155
|
+
1
|
|
156
|
+
),
|
|
157
|
+
},
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
def benchmark(
|
|
161
|
+
method: Dict[str, Any], loop: asyncio.AbstractEventLoop = loop
|
|
162
|
+
) -> None:
|
|
163
|
+
outcomes: Dict[str, Union[str, float]] = defaultdict(lambda: "N/A")
|
|
164
|
+
outcomes["name"] = method["name"]
|
|
165
|
+
outcomes["HTTPProvider"] = sync_benchmark(
|
|
166
|
+
method["exec"],
|
|
167
|
+
num_calls,
|
|
168
|
+
)
|
|
169
|
+
outcomes["AsyncHTTPProvider"] = loop.run_until_complete(
|
|
170
|
+
async_benchmark(method["async_exec"], num_calls)
|
|
171
|
+
)
|
|
172
|
+
print_entry(logger, outcomes)
|
|
173
|
+
|
|
174
|
+
print_header(logger, num_calls)
|
|
175
|
+
|
|
176
|
+
for method in methods:
|
|
177
|
+
benchmark(method)
|
|
178
|
+
|
|
179
|
+
print_footer(logger)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
if __name__ == "__main__":
|
|
183
|
+
args = parser.parse_args()
|
|
184
|
+
|
|
185
|
+
logger = logging.getLogger()
|
|
186
|
+
logger.setLevel(logging.INFO)
|
|
187
|
+
logger.addHandler(logging.StreamHandler(sys.stdout))
|
|
188
|
+
|
|
189
|
+
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 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)
|
web3/tracing.py
CHANGED
|
@@ -53,10 +53,10 @@ class Tracing(Module):
|
|
|
53
53
|
self._default_block = value
|
|
54
54
|
|
|
55
55
|
def trace_replay_transaction_munger(
|
|
56
|
-
self,
|
|
57
|
-
block_identifier: Union[_Hash32, BlockIdentifier],
|
|
58
|
-
mode: TraceMode = ["trace"],
|
|
56
|
+
self, block_identifier: Union[_Hash32, BlockIdentifier], mode: TraceMode = None
|
|
59
57
|
) -> Tuple[Union[BlockIdentifier, _Hash32], TraceMode]:
|
|
58
|
+
if mode is None:
|
|
59
|
+
mode = ["trace"]
|
|
60
60
|
return (block_identifier, mode)
|
|
61
61
|
|
|
62
62
|
trace_replay_transaction: Method[Callable[..., BlockTrace]] = Method(
|
|
@@ -86,9 +86,11 @@ class Tracing(Module):
|
|
|
86
86
|
def trace_call_munger(
|
|
87
87
|
self,
|
|
88
88
|
transaction: TxParams,
|
|
89
|
-
mode: TraceMode =
|
|
89
|
+
mode: TraceMode = None,
|
|
90
90
|
block_identifier: Optional[BlockIdentifier] = None,
|
|
91
91
|
) -> Tuple[TxParams, TraceMode, BlockIdentifier]:
|
|
92
|
+
if mode is None:
|
|
93
|
+
mode = ["trace"]
|
|
92
94
|
if "from" not in transaction and is_checksum_address(
|
|
93
95
|
self.w3.eth.default_account
|
|
94
96
|
):
|
|
@@ -105,8 +107,10 @@ class Tracing(Module):
|
|
|
105
107
|
)
|
|
106
108
|
|
|
107
109
|
def trace_transactions_munger(
|
|
108
|
-
self, raw_transaction: HexStr, mode: TraceMode =
|
|
110
|
+
self, raw_transaction: HexStr, mode: TraceMode = None
|
|
109
111
|
) -> Tuple[HexStr, TraceMode]:
|
|
112
|
+
if mode is None:
|
|
113
|
+
mode = ["trace"]
|
|
110
114
|
return raw_transaction, mode
|
|
111
115
|
|
|
112
116
|
trace_raw_transaction: Method[Callable[..., BlockTrace]] = Method(
|
web3/types.py
CHANGED
|
@@ -5,10 +5,12 @@ from typing import (
|
|
|
5
5
|
Coroutine,
|
|
6
6
|
Dict,
|
|
7
7
|
List,
|
|
8
|
+
Literal,
|
|
8
9
|
NewType,
|
|
9
10
|
Optional,
|
|
10
11
|
Sequence,
|
|
11
12
|
Type,
|
|
13
|
+
TypedDict,
|
|
12
14
|
TypeVar,
|
|
13
15
|
Union,
|
|
14
16
|
)
|
|
@@ -25,9 +27,7 @@ from hexbytes import (
|
|
|
25
27
|
)
|
|
26
28
|
|
|
27
29
|
from web3._utils.compat import (
|
|
28
|
-
Literal,
|
|
29
30
|
NotRequired,
|
|
30
|
-
TypedDict,
|
|
31
31
|
)
|
|
32
32
|
from web3._utils.function_identifiers import (
|
|
33
33
|
FallbackFn,
|
|
@@ -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,
|
|
@@ -163,6 +165,8 @@ TxData = TypedDict(
|
|
|
163
165
|
TxParams = TypedDict(
|
|
164
166
|
"TxParams",
|
|
165
167
|
{
|
|
168
|
+
"accessList": AccessList,
|
|
169
|
+
"blobVersionedHashes": Sequence[Union[str, HexStr, bytes, HexBytes]],
|
|
166
170
|
"chainId": int,
|
|
167
171
|
"data": Union[bytes, HexStr],
|
|
168
172
|
# addr or ens
|
|
@@ -170,6 +174,7 @@ TxParams = TypedDict(
|
|
|
170
174
|
"gas": int,
|
|
171
175
|
# legacy pricing
|
|
172
176
|
"gasPrice": Wei,
|
|
177
|
+
"maxFeePerBlobGas": Union[str, Wei],
|
|
173
178
|
# dynamic fee pricing
|
|
174
179
|
"maxFeePerGas": Union[str, Wei],
|
|
175
180
|
"maxPriorityFeePerGas": Union[str, Wei],
|
|
@@ -183,15 +188,11 @@ TxParams = TypedDict(
|
|
|
183
188
|
)
|
|
184
189
|
|
|
185
190
|
|
|
186
|
-
WithdrawalData
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
"address": ChecksumAddress,
|
|
192
|
-
"amount": Gwei,
|
|
193
|
-
},
|
|
194
|
-
)
|
|
191
|
+
class WithdrawalData(TypedDict):
|
|
192
|
+
index: int
|
|
193
|
+
validator_index: int
|
|
194
|
+
address: ChecksumAddress
|
|
195
|
+
amount: Gwei
|
|
195
196
|
|
|
196
197
|
|
|
197
198
|
class BlockData(TypedDict, total=False):
|
|
@@ -218,6 +219,9 @@ class BlockData(TypedDict, total=False):
|
|
|
218
219
|
uncles: Sequence[HexBytes]
|
|
219
220
|
withdrawals: Sequence[WithdrawalData]
|
|
220
221
|
withdrawalsRoot: HexBytes
|
|
222
|
+
parentBeaconBlockRoot: HexBytes
|
|
223
|
+
blobGasUsed: int
|
|
224
|
+
excessBlobGas: int
|
|
221
225
|
|
|
222
226
|
# ExtraDataToPOAMiddleware replaces extraData w/ proofOfAuthorityData
|
|
223
227
|
proofOfAuthorityData: HexBytes
|
|
@@ -338,17 +342,12 @@ class FeeHistory(TypedDict):
|
|
|
338
342
|
reward: List[List[Wei]]
|
|
339
343
|
|
|
340
344
|
|
|
341
|
-
StateOverrideParams =
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
"state": Optional[Dict[HexStr, HexStr]],
|
|
348
|
-
"stateDiff": Optional[Dict[HexStr, HexStr]],
|
|
349
|
-
},
|
|
350
|
-
total=False,
|
|
351
|
-
)
|
|
345
|
+
class StateOverrideParams(TypedDict, total=False):
|
|
346
|
+
balance: Optional[Wei]
|
|
347
|
+
nonce: Optional[int]
|
|
348
|
+
code: Optional[Union[bytes, HexStr]]
|
|
349
|
+
state: Optional[Dict[HexStr, HexStr]]
|
|
350
|
+
stateDiff: Optional[Dict[HexStr, HexStr]]
|
|
352
351
|
|
|
353
352
|
|
|
354
353
|
StateOverride = Dict[ChecksumAddress, StateOverrideParams]
|
|
@@ -381,6 +380,8 @@ TxReceipt = TypedDict(
|
|
|
381
380
|
},
|
|
382
381
|
)
|
|
383
382
|
|
|
383
|
+
BlockReceipts = List[TxReceipt]
|
|
384
|
+
|
|
384
385
|
|
|
385
386
|
class SignedTx(TypedDict, total=False):
|
|
386
387
|
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 =
|
|
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.
|
|
3
|
+
Version: 7.0.0b4
|
|
4
4
|
Summary: web3.py
|
|
5
5
|
Home-page: https://github.com/ethereum/web3.py
|
|
6
6
|
Author: The Ethereum Foundation
|
|
@@ -20,12 +20,12 @@ Requires-Python: >=3.8
|
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE
|
|
22
22
|
Requires-Dist: aiohttp >=3.7.4.post0
|
|
23
|
-
Requires-Dist: eth-abi >=
|
|
24
|
-
Requires-Dist: eth-account >=0.
|
|
23
|
+
Requires-Dist: eth-abi >=5.0.1
|
|
24
|
+
Requires-Dist: eth-account >=0.12.0
|
|
25
25
|
Requires-Dist: eth-hash[pycryptodome] >=0.5.1
|
|
26
|
-
Requires-Dist: eth-typing >=
|
|
26
|
+
Requires-Dist: eth-typing >=4.0.0
|
|
27
27
|
Requires-Dist: eth-utils >=4.0.0
|
|
28
|
-
Requires-Dist: hexbytes
|
|
28
|
+
Requires-Dist: hexbytes >=1.2.0
|
|
29
29
|
Requires-Dist: pydantic >=2.4.0
|
|
30
30
|
Requires-Dist: requests >=2.16.0
|
|
31
31
|
Requires-Dist: typing-extensions >=4.0.1
|
|
@@ -33,44 +33,31 @@ Requires-Dist: websockets >=10.0.0
|
|
|
33
33
|
Requires-Dist: pyunormalize >=15.0.0
|
|
34
34
|
Requires-Dist: pywin32 >=223 ; platform_system == "Windows"
|
|
35
35
|
Provides-Extra: dev
|
|
36
|
-
Requires-Dist: eth-tester[py-evm]
|
|
36
|
+
Requires-Dist: eth-tester[py-evm] <0.12.0b1,>=0.11.0b1 ; extra == 'dev'
|
|
37
37
|
Requires-Dist: py-geth >=4.1.0 ; extra == 'dev'
|
|
38
|
-
Requires-Dist: black >=22.1.0 ; extra == 'dev'
|
|
39
|
-
Requires-Dist: flake8 ==3.8.3 ; extra == 'dev'
|
|
40
|
-
Requires-Dist: isort >=5.11.0 ; extra == 'dev'
|
|
41
|
-
Requires-Dist: mypy ==1.4.1 ; extra == 'dev'
|
|
42
|
-
Requires-Dist: types-setuptools >=57.4.4 ; extra == 'dev'
|
|
43
|
-
Requires-Dist: types-requests >=2.26.1 ; extra == 'dev'
|
|
44
38
|
Requires-Dist: sphinx >=5.3.0 ; extra == 'dev'
|
|
45
39
|
Requires-Dist: sphinx-rtd-theme >=1.0.0 ; extra == 'dev'
|
|
46
40
|
Requires-Dist: towncrier <22,>=21 ; extra == 'dev'
|
|
41
|
+
Requires-Dist: build >=0.9.0 ; extra == 'dev'
|
|
47
42
|
Requires-Dist: bumpversion ; extra == 'dev'
|
|
48
43
|
Requires-Dist: flaky >=3.7.0 ; extra == 'dev'
|
|
49
44
|
Requires-Dist: hypothesis >=3.31.2 ; extra == 'dev'
|
|
50
|
-
Requires-Dist:
|
|
45
|
+
Requires-Dist: pre-commit >=3.4.0 ; extra == 'dev'
|
|
51
46
|
Requires-Dist: pytest-asyncio <0.23,>=0.18.1 ; extra == 'dev'
|
|
52
47
|
Requires-Dist: pytest-mock >=1.10 ; extra == 'dev'
|
|
53
48
|
Requires-Dist: pytest-watch >=4.2 ; extra == 'dev'
|
|
54
49
|
Requires-Dist: pytest-xdist >=1.29 ; extra == 'dev'
|
|
50
|
+
Requires-Dist: pytest >=7.0.0 ; extra == 'dev'
|
|
55
51
|
Requires-Dist: setuptools >=38.6.0 ; extra == 'dev'
|
|
56
52
|
Requires-Dist: tox >=3.18.0 ; extra == 'dev'
|
|
57
53
|
Requires-Dist: tqdm >4.32 ; extra == 'dev'
|
|
58
54
|
Requires-Dist: twine >=1.13 ; extra == 'dev'
|
|
59
|
-
Requires-Dist: build >=0.9.0 ; extra == 'dev'
|
|
60
|
-
Requires-Dist: importlib-metadata <5.0 ; (python_version < "3.8") and extra == 'dev'
|
|
61
55
|
Provides-Extra: docs
|
|
62
56
|
Requires-Dist: sphinx >=5.3.0 ; extra == 'docs'
|
|
63
57
|
Requires-Dist: sphinx-rtd-theme >=1.0.0 ; extra == 'docs'
|
|
64
58
|
Requires-Dist: towncrier <22,>=21 ; extra == 'docs'
|
|
65
|
-
Provides-Extra: linter
|
|
66
|
-
Requires-Dist: black >=22.1.0 ; extra == 'linter'
|
|
67
|
-
Requires-Dist: flake8 ==3.8.3 ; extra == 'linter'
|
|
68
|
-
Requires-Dist: isort >=5.11.0 ; extra == 'linter'
|
|
69
|
-
Requires-Dist: mypy ==1.4.1 ; extra == 'linter'
|
|
70
|
-
Requires-Dist: types-setuptools >=57.4.4 ; extra == 'linter'
|
|
71
|
-
Requires-Dist: types-requests >=2.26.1 ; extra == 'linter'
|
|
72
59
|
Provides-Extra: tester
|
|
73
|
-
Requires-Dist: eth-tester[py-evm]
|
|
60
|
+
Requires-Dist: eth-tester[py-evm] <0.12.0b1,>=0.11.0b1 ; extra == 'tester'
|
|
74
61
|
Requires-Dist: py-geth >=4.1.0 ; extra == 'tester'
|
|
75
62
|
|
|
76
63
|
# web3.py
|
|
@@ -81,9 +68,9 @@ Requires-Dist: py-geth >=4.1.0 ; extra == 'tester'
|
|
|
81
68
|
|
|
82
69
|
A Python library for interacting with Ethereum.
|
|
83
70
|
|
|
84
|
-
-
|
|
71
|
+
- Python 3.8+ support
|
|
85
72
|
|
|
86
|
-
|
|
73
|
+
______________________________________________________________________
|
|
87
74
|
|
|
88
75
|
## Quickstart
|
|
89
76
|
|
|
@@ -101,6 +88,6 @@ guidelines for [contributing](https://web3py.readthedocs.io/en/latest/contributi
|
|
|
101
88
|
then check out issues that are labeled
|
|
102
89
|
[Good First Issue](https://github.com/ethereum/web3.py/issues?q=is%3Aissue+is%3Aopen+label%3A%22Good+First+Issue%22).
|
|
103
90
|
|
|
104
|
-
|
|
91
|
+
______________________________________________________________________
|
|
105
92
|
|
|
106
93
|
#### Questions on implementation or usage? Join the conversation on [discord](https://discord.gg/GHryRvPB84).
|