web3 7.0.0b3__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 +12 -9
- ens/contract_data.py +2 -2
- ens/ens.py +8 -5
- ens/exceptions.py +19 -27
- ens/specs/nf.json +1 -1
- ens/specs/normalization_spec.json +1 -1
- ens/utils.py +17 -10
- 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 +20 -18
- web3/_utils/fee_utils.py +2 -4
- web3/_utils/filters.py +17 -12
- web3/_utils/formatters.py +2 -2
- web3/_utils/math.py +3 -2
- web3/_utils/method_formatters.py +24 -5
- web3/_utils/module.py +2 -1
- web3/_utils/module_testing/eth_module.py +62 -69
- 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 +5 -1
- web3/_utils/threads.py +8 -7
- web3/_utils/transactions.py +14 -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 +50 -56
- web3/contract/contract.py +12 -6
- web3/contract/utils.py +11 -6
- web3/datastructures.py +22 -12
- web3/eth/async_eth.py +33 -28
- web3/eth/base_eth.py +7 -3
- web3/eth/eth.py +18 -13
- web3/exceptions.py +30 -59
- web3/gas_strategies/time_based.py +2 -4
- web3/geth.py +1 -3
- web3/main.py +6 -2
- web3/manager.py +7 -5
- 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 +11 -1
- web3/providers/persistent/request_processor.py +7 -7
- 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/main.py +13 -9
- web3/tools/benchmark/utils.py +1 -1
- web3/tracing.py +9 -5
- web3/types.py +19 -22
- {web3-7.0.0b3.dist-info → web3-7.0.0b4.dist-info}/METADATA +13 -28
- {web3-7.0.0b3.dist-info → web3-7.0.0b4.dist-info}/RECORD +79 -79
- {web3-7.0.0b3.dist-info → web3-7.0.0b4.dist-info}/LICENSE +0 -0
- {web3-7.0.0b3.dist-info → web3-7.0.0b4.dist-info}/WHEEL +0 -0
- {web3-7.0.0b3.dist-info → web3-7.0.0b4.dist-info}/top_level.txt +0 -0
web3/geth.py
CHANGED
|
@@ -5,6 +5,7 @@ from typing import (
|
|
|
5
5
|
Dict,
|
|
6
6
|
List,
|
|
7
7
|
Optional,
|
|
8
|
+
Protocol,
|
|
8
9
|
Tuple,
|
|
9
10
|
)
|
|
10
11
|
|
|
@@ -18,9 +19,6 @@ from hexbytes.main import (
|
|
|
18
19
|
HexBytes,
|
|
19
20
|
)
|
|
20
21
|
|
|
21
|
-
from web3._utils.compat import (
|
|
22
|
-
Protocol,
|
|
23
|
-
)
|
|
24
22
|
from web3._utils.rpc_abi import (
|
|
25
23
|
RPC,
|
|
26
24
|
)
|
web3/main.py
CHANGED
|
@@ -84,6 +84,10 @@ from web3.eth import (
|
|
|
84
84
|
AsyncEth,
|
|
85
85
|
Eth,
|
|
86
86
|
)
|
|
87
|
+
from web3.exceptions import (
|
|
88
|
+
Web3TypeError,
|
|
89
|
+
Web3ValueError,
|
|
90
|
+
)
|
|
87
91
|
from web3.geth import (
|
|
88
92
|
AsyncGeth,
|
|
89
93
|
AsyncGethAdmin,
|
|
@@ -283,7 +287,7 @@ class BaseWeb3:
|
|
|
283
287
|
input_bytes = to_bytes(primitive, hexstr=hexstr, text=text)
|
|
284
288
|
return eth_utils_keccak(input_bytes)
|
|
285
289
|
|
|
286
|
-
raise
|
|
290
|
+
raise Web3TypeError(
|
|
287
291
|
f"You called keccak with first arg {primitive!r} and keywords "
|
|
288
292
|
f"{{'text': {text!r}, 'hexstr': {hexstr!r}}}. You must call it with "
|
|
289
293
|
"one of these approaches: keccak(text='txt'), keccak(hexstr='0x747874'), "
|
|
@@ -304,7 +308,7 @@ class BaseWeb3:
|
|
|
304
308
|
and list of corresponding values -- `[20, [-1, 5, 0], True]`
|
|
305
309
|
"""
|
|
306
310
|
if len(abi_types) != len(values):
|
|
307
|
-
raise
|
|
311
|
+
raise Web3ValueError(
|
|
308
312
|
"Length mismatch between provided abi types and values. Got "
|
|
309
313
|
f"{len(abi_types)} types and {len(values)} values."
|
|
310
314
|
)
|
web3/manager.py
CHANGED
|
@@ -35,6 +35,8 @@ from web3.exceptions import (
|
|
|
35
35
|
BadResponseFormat,
|
|
36
36
|
MethodUnavailable,
|
|
37
37
|
ProviderConnectionError,
|
|
38
|
+
Web3TypeError,
|
|
39
|
+
Web3ValueError,
|
|
38
40
|
)
|
|
39
41
|
from web3.middleware import (
|
|
40
42
|
AttributeDictMiddleware,
|
|
@@ -238,7 +240,7 @@ class RequestManager:
|
|
|
238
240
|
error = response.get("error")
|
|
239
241
|
# Raise the error when the value is a string
|
|
240
242
|
if error is None or isinstance(error, str):
|
|
241
|
-
raise
|
|
243
|
+
raise Web3ValueError(error)
|
|
242
244
|
|
|
243
245
|
# Errors must include an integer code
|
|
244
246
|
code = error.get("code")
|
|
@@ -259,7 +261,7 @@ class RequestManager:
|
|
|
259
261
|
|
|
260
262
|
apply_error_formatters(error_formatters, response)
|
|
261
263
|
|
|
262
|
-
raise
|
|
264
|
+
raise Web3ValueError(error)
|
|
263
265
|
|
|
264
266
|
# Format and validate results
|
|
265
267
|
elif "result" in response:
|
|
@@ -323,8 +325,8 @@ class RequestManager:
|
|
|
323
325
|
cast("AsyncWeb3", self.w3), cast("MiddlewareOnion", self.middleware_onion)
|
|
324
326
|
)
|
|
325
327
|
self.logger.debug(
|
|
326
|
-
"Making request to open socket connection
|
|
327
|
-
f"
|
|
328
|
+
"Making request to open socket connection: "
|
|
329
|
+
f"{provider.get_endpoint_uri_or_ipc_path()}, method: {method}"
|
|
328
330
|
)
|
|
329
331
|
response = await request_func(method, params)
|
|
330
332
|
return await self._process_response(response)
|
|
@@ -337,7 +339,7 @@ class RequestManager:
|
|
|
337
339
|
|
|
338
340
|
async def _message_stream(self) -> AsyncGenerator[RPCResponse, None]:
|
|
339
341
|
if not isinstance(self._provider, PersistentConnectionProvider):
|
|
340
|
-
raise
|
|
342
|
+
raise Web3TypeError(
|
|
341
343
|
"Only providers that maintain an open, persistent connection "
|
|
342
344
|
"can listen to streams."
|
|
343
345
|
)
|
web3/method.py
CHANGED
|
@@ -32,7 +32,9 @@ from web3._utils.rpc_abi import (
|
|
|
32
32
|
RPC,
|
|
33
33
|
)
|
|
34
34
|
from web3.exceptions import (
|
|
35
|
+
Web3TypeError,
|
|
35
36
|
Web3ValidationError,
|
|
37
|
+
Web3ValueError,
|
|
36
38
|
)
|
|
37
39
|
from web3.types import (
|
|
38
40
|
RPCEndpoint,
|
|
@@ -66,7 +68,9 @@ def _set_mungers(
|
|
|
66
68
|
return (
|
|
67
69
|
mungers
|
|
68
70
|
if mungers
|
|
69
|
-
else [default_munger]
|
|
71
|
+
else [default_munger]
|
|
72
|
+
if is_property
|
|
73
|
+
else [default_root_munger]
|
|
70
74
|
)
|
|
71
75
|
|
|
72
76
|
|
|
@@ -84,7 +88,8 @@ TFunc = TypeVar("TFunc", bound=Callable[..., Any])
|
|
|
84
88
|
|
|
85
89
|
|
|
86
90
|
class Method(Generic[TFunc]):
|
|
87
|
-
"""
|
|
91
|
+
"""
|
|
92
|
+
Method object for web3 module methods
|
|
88
93
|
|
|
89
94
|
Calls to the Method go through these steps:
|
|
90
95
|
|
|
@@ -147,7 +152,7 @@ class Method(Generic[TFunc]):
|
|
|
147
152
|
self, obj: Optional["Module"] = None, obj_type: Optional[Type["Module"]] = None
|
|
148
153
|
) -> TFunc:
|
|
149
154
|
if obj is None:
|
|
150
|
-
raise
|
|
155
|
+
raise Web3TypeError(
|
|
151
156
|
"Direct calls to methods are not supported. "
|
|
152
157
|
"Methods must be called from an module instance, "
|
|
153
158
|
"usually attached to a web3 instance."
|
|
@@ -163,7 +168,7 @@ class Method(Generic[TFunc]):
|
|
|
163
168
|
return self.json_rpc_method
|
|
164
169
|
elif isinstance(self.json_rpc_method, (str,)):
|
|
165
170
|
return lambda *_: self.json_rpc_method
|
|
166
|
-
raise
|
|
171
|
+
raise Web3ValueError(
|
|
167
172
|
"``json_rpc_method`` config invalid. May be a string or function"
|
|
168
173
|
)
|
|
169
174
|
|
|
@@ -175,7 +180,9 @@ class Method(Generic[TFunc]):
|
|
|
175
180
|
lambda args, munger: munger(module, *args, **kwargs), self.mungers, args
|
|
176
181
|
)
|
|
177
182
|
|
|
178
|
-
def process_params(
|
|
183
|
+
def process_params(
|
|
184
|
+
self, module: "Module", *args: Any, **kwargs: Any
|
|
185
|
+
) -> Tuple[
|
|
179
186
|
Tuple[Union[RPCEndpoint, Callable[..., RPCEndpoint]], Tuple[Any, ...]],
|
|
180
187
|
Tuple[
|
|
181
188
|
Union[TReturn, Dict[str, Callable[..., Any]]],
|
|
@@ -226,5 +233,6 @@ class DeprecatedMethod:
|
|
|
226
233
|
warnings.warn(
|
|
227
234
|
f"{self.old_name} is deprecated in favor of {self.new_name}",
|
|
228
235
|
category=DeprecationWarning,
|
|
236
|
+
stacklevel=2,
|
|
229
237
|
)
|
|
230
238
|
return self.method.__get__(obj, obj_type)
|
web3/middleware/base.py
CHANGED
|
@@ -48,7 +48,9 @@ class Web3Middleware:
|
|
|
48
48
|
def request_processor(self, method: "RPCEndpoint", params: Any) -> Any:
|
|
49
49
|
return method, params
|
|
50
50
|
|
|
51
|
-
def response_processor(
|
|
51
|
+
def response_processor(
|
|
52
|
+
self, method: "RPCEndpoint", response: "RPCResponse"
|
|
53
|
+
) -> "RPCResponse":
|
|
52
54
|
return response
|
|
53
55
|
|
|
54
56
|
# -- async -- #
|
|
@@ -76,7 +78,7 @@ class Web3Middleware:
|
|
|
76
78
|
self,
|
|
77
79
|
method: "RPCEndpoint",
|
|
78
80
|
response: "RPCResponse",
|
|
79
|
-
) ->
|
|
81
|
+
) -> "RPCResponse":
|
|
80
82
|
return response
|
|
81
83
|
|
|
82
84
|
|
web3/middleware/filter.py
CHANGED
|
@@ -42,6 +42,9 @@ from web3._utils.formatters import (
|
|
|
42
42
|
from web3._utils.rpc_abi import (
|
|
43
43
|
RPC,
|
|
44
44
|
)
|
|
45
|
+
from web3.exceptions import (
|
|
46
|
+
Web3TypeError,
|
|
47
|
+
)
|
|
45
48
|
from web3.middleware.base import (
|
|
46
49
|
Web3Middleware,
|
|
47
50
|
)
|
|
@@ -71,7 +74,8 @@ else:
|
|
|
71
74
|
|
|
72
75
|
|
|
73
76
|
def segment_count(start: int, stop: int, step: int = 5) -> Iterable[Tuple[int, int]]:
|
|
74
|
-
"""
|
|
77
|
+
"""
|
|
78
|
+
Creates a segment counting generator
|
|
75
79
|
|
|
76
80
|
The generator returns tuple pairs of integers
|
|
77
81
|
that correspond to segments in the provided range.
|
|
@@ -84,6 +88,7 @@ def segment_count(start: int, stop: int, step: int = 5) -> Iterable[Tuple[int, i
|
|
|
84
88
|
|
|
85
89
|
|
|
86
90
|
Example:
|
|
91
|
+
-------
|
|
87
92
|
|
|
88
93
|
>>> segment_counter = segment_count(start=0, stop=10, step=3)
|
|
89
94
|
>>> next(segment_counter)
|
|
@@ -94,6 +99,7 @@ def segment_count(start: int, stop: int, step: int = 5) -> Iterable[Tuple[int, i
|
|
|
94
99
|
(6, 9)
|
|
95
100
|
>>> next(segment_counter) # Remainder is also returned
|
|
96
101
|
(9, 10)
|
|
102
|
+
|
|
97
103
|
"""
|
|
98
104
|
return gen_bounded_segments(start, stop, step)
|
|
99
105
|
|
|
@@ -104,10 +110,9 @@ def gen_bounded_segments(start: int, stop: int, step: int) -> Iterable[Tuple[int
|
|
|
104
110
|
if start + step >= stop:
|
|
105
111
|
yield (start, stop)
|
|
106
112
|
return
|
|
107
|
-
|
|
113
|
+
yield from zip(
|
|
108
114
|
range(start, stop - step + 1, step), range(start + step, stop + 1, step)
|
|
109
|
-
)
|
|
110
|
-
yield segment
|
|
115
|
+
)
|
|
111
116
|
|
|
112
117
|
remainder = (stop - start) % step
|
|
113
118
|
# Handle the remainder
|
|
@@ -118,13 +123,14 @@ def gen_bounded_segments(start: int, stop: int, step: int) -> Iterable[Tuple[int
|
|
|
118
123
|
def block_ranges(
|
|
119
124
|
start_block: BlockNumber, last_block: Optional[BlockNumber], step: int = 5
|
|
120
125
|
) -> Iterable[Tuple[BlockNumber, BlockNumber]]:
|
|
121
|
-
"""
|
|
126
|
+
"""
|
|
127
|
+
Returns 2-tuple ranges describing ranges of block from start_block to last_block
|
|
122
128
|
|
|
123
129
|
Ranges do not overlap to facilitate use as ``toBlock``, ``fromBlock``
|
|
124
130
|
json-rpc arguments, which are both inclusive.
|
|
125
131
|
"""
|
|
126
132
|
if last_block is not None and start_block > last_block:
|
|
127
|
-
raise
|
|
133
|
+
raise Web3TypeError(
|
|
128
134
|
"Incompatible start and stop arguments.",
|
|
129
135
|
"Start must be less than or equal to stop.",
|
|
130
136
|
)
|
|
@@ -138,7 +144,8 @@ def block_ranges(
|
|
|
138
144
|
def iter_latest_block(
|
|
139
145
|
w3: "Web3", to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None
|
|
140
146
|
) -> Iterable[BlockNumber]:
|
|
141
|
-
"""
|
|
147
|
+
"""
|
|
148
|
+
Returns a generator that dispenses the latest block, if
|
|
142
149
|
any new blocks have been mined since last iteration.
|
|
143
150
|
|
|
144
151
|
If there are no new blocks or the latest block is greater than
|
|
@@ -160,8 +167,7 @@ def iter_latest_block(
|
|
|
160
167
|
|
|
161
168
|
while True:
|
|
162
169
|
latest_block = w3.eth.block_number
|
|
163
|
-
|
|
164
|
-
if is_bounded_range and latest_block > to_block: # type: ignore
|
|
170
|
+
if is_bounded_range and latest_block > to_block:
|
|
165
171
|
yield None
|
|
166
172
|
# No new blocks since last iteration.
|
|
167
173
|
if _last is not None and _last == latest_block:
|
|
@@ -176,7 +182,8 @@ def iter_latest_block_ranges(
|
|
|
176
182
|
from_block: BlockNumber,
|
|
177
183
|
to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None,
|
|
178
184
|
) -> Iterable[Tuple[Optional[BlockNumber], Optional[BlockNumber]]]:
|
|
179
|
-
"""
|
|
185
|
+
"""
|
|
186
|
+
Returns an iterator unloading ranges of available blocks
|
|
180
187
|
|
|
181
188
|
starting from `fromBlock` to the latest mined block,
|
|
182
189
|
until reaching toBlock. e.g.:
|
|
@@ -212,7 +219,8 @@ def get_logs_multipart(
|
|
|
212
219
|
topics: List[Optional[Union[_Hash32, List[_Hash32]]]],
|
|
213
220
|
max_blocks: int,
|
|
214
221
|
) -> Iterable[List[LogReceipt]]:
|
|
215
|
-
"""
|
|
222
|
+
"""
|
|
223
|
+
Used to break up requests to ``eth_getLogs``
|
|
216
224
|
|
|
217
225
|
The getLog request is partitioned into multiple calls of the max number of blocks
|
|
218
226
|
``max_blocks``.
|
|
@@ -247,9 +255,8 @@ class RequestLogs:
|
|
|
247
255
|
if from_block is None or from_block == "latest":
|
|
248
256
|
self._from_block = BlockNumber(w3.eth.block_number + 1)
|
|
249
257
|
elif is_string(from_block) and is_hex(from_block):
|
|
250
|
-
self._from_block = BlockNumber(hex_to_integer(from_block))
|
|
258
|
+
self._from_block = BlockNumber(hex_to_integer(from_block))
|
|
251
259
|
else:
|
|
252
|
-
# cast b/c LatestBlockParam is handled above
|
|
253
260
|
self._from_block = from_block
|
|
254
261
|
self._to_block = to_block
|
|
255
262
|
self.filter_changes = self._get_filter_changes()
|
|
@@ -265,7 +272,7 @@ class RequestLogs:
|
|
|
265
272
|
elif self._to_block == "latest":
|
|
266
273
|
to_block = self.w3.eth.block_number
|
|
267
274
|
elif is_string(self._to_block) and is_hex(self._to_block):
|
|
268
|
-
to_block = BlockNumber(hex_to_integer(self._to_block))
|
|
275
|
+
to_block = BlockNumber(hex_to_integer(self._to_block))
|
|
269
276
|
else:
|
|
270
277
|
to_block = self._to_block
|
|
271
278
|
|
|
@@ -352,7 +359,8 @@ def block_hashes_in_range(
|
|
|
352
359
|
async def async_iter_latest_block(
|
|
353
360
|
w3: "AsyncWeb3", to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None
|
|
354
361
|
) -> AsyncIterable[BlockNumber]:
|
|
355
|
-
"""
|
|
362
|
+
"""
|
|
363
|
+
Returns a generator that dispenses the latest block, if
|
|
356
364
|
any new blocks have been mined since last iteration.
|
|
357
365
|
|
|
358
366
|
If there are no new blocks or the latest block is greater than
|
|
@@ -390,7 +398,8 @@ async def async_iter_latest_block_ranges(
|
|
|
390
398
|
from_block: BlockNumber,
|
|
391
399
|
to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None,
|
|
392
400
|
) -> AsyncIterable[Tuple[Optional[BlockNumber], Optional[BlockNumber]]]:
|
|
393
|
-
"""
|
|
401
|
+
"""
|
|
402
|
+
Returns an iterator unloading ranges of available blocks
|
|
394
403
|
|
|
395
404
|
starting from `from_block` to the latest mined block,
|
|
396
405
|
until reaching to_block. e.g.:
|
|
@@ -423,7 +432,8 @@ async def async_get_logs_multipart(
|
|
|
423
432
|
topics: List[Optional[Union[_Hash32, List[_Hash32]]]],
|
|
424
433
|
max_blocks: int,
|
|
425
434
|
) -> AsyncIterable[List[LogReceipt]]:
|
|
426
|
-
"""
|
|
435
|
+
"""
|
|
436
|
+
Used to break up requests to ``eth_getLogs``
|
|
427
437
|
|
|
428
438
|
The getLog request is partitioned into multiple calls of the max number of blocks
|
|
429
439
|
``max_blocks``.
|
web3/middleware/formatting.py
CHANGED
|
@@ -3,6 +3,7 @@ from typing import (
|
|
|
3
3
|
Any,
|
|
4
4
|
Callable,
|
|
5
5
|
Coroutine,
|
|
6
|
+
Literal,
|
|
6
7
|
Optional,
|
|
7
8
|
Union,
|
|
8
9
|
cast,
|
|
@@ -14,6 +15,9 @@ from eth_utils.toolz import (
|
|
|
14
15
|
merge,
|
|
15
16
|
)
|
|
16
17
|
|
|
18
|
+
from web3.exceptions import (
|
|
19
|
+
Web3ValueError,
|
|
20
|
+
)
|
|
17
21
|
from web3.middleware.base import (
|
|
18
22
|
Web3MiddlewareBuilder,
|
|
19
23
|
)
|
|
@@ -21,7 +25,6 @@ from web3.types import (
|
|
|
21
25
|
EthSubscriptionParams,
|
|
22
26
|
Formatters,
|
|
23
27
|
FormattersDict,
|
|
24
|
-
Literal,
|
|
25
28
|
RPCEndpoint,
|
|
26
29
|
RPCResponse,
|
|
27
30
|
)
|
|
@@ -118,7 +121,7 @@ class FormattingMiddlewareBuilder(Web3MiddlewareBuilder):
|
|
|
118
121
|
if (
|
|
119
122
|
sync_formatters_builder is None and async_formatters_builder is not None
|
|
120
123
|
) or (sync_formatters_builder is not None and async_formatters_builder is None):
|
|
121
|
-
raise
|
|
124
|
+
raise Web3ValueError(
|
|
122
125
|
"Must specify both sync_formatters_builder and async_formatters_builder"
|
|
123
126
|
)
|
|
124
127
|
|
|
@@ -128,7 +131,7 @@ class FormattingMiddlewareBuilder(Web3MiddlewareBuilder):
|
|
|
128
131
|
or result_formatters is not None
|
|
129
132
|
or error_formatters is not None
|
|
130
133
|
):
|
|
131
|
-
raise
|
|
134
|
+
raise Web3ValueError(
|
|
132
135
|
"Cannot specify formatters_builder and formatters at the same time"
|
|
133
136
|
)
|
|
134
137
|
|
web3/middleware/names.py
CHANGED
|
@@ -31,6 +31,9 @@ from .._utils.abi import (
|
|
|
31
31
|
from .._utils.formatters import (
|
|
32
32
|
recursive_map,
|
|
33
33
|
)
|
|
34
|
+
from ..exceptions import (
|
|
35
|
+
Web3TypeError,
|
|
36
|
+
)
|
|
34
37
|
from .base import (
|
|
35
38
|
Web3Middleware,
|
|
36
39
|
)
|
|
@@ -92,7 +95,7 @@ async def async_apply_ens_to_address_conversion(
|
|
|
92
95
|
return (formatted_params_dict, *params[1:])
|
|
93
96
|
|
|
94
97
|
else:
|
|
95
|
-
raise
|
|
98
|
+
raise Web3TypeError(
|
|
96
99
|
f"ABI definitions must be a list or dictionary, "
|
|
97
100
|
f"got {abi_types_for_method!r}"
|
|
98
101
|
)
|
web3/middleware/signing.py
CHANGED
|
@@ -55,6 +55,9 @@ from web3._utils.transactions import (
|
|
|
55
55
|
fill_nonce,
|
|
56
56
|
fill_transaction_defaults,
|
|
57
57
|
)
|
|
58
|
+
from web3.exceptions import (
|
|
59
|
+
Web3TypeError,
|
|
60
|
+
)
|
|
58
61
|
from web3.middleware.base import (
|
|
59
62
|
Web3MiddlewareBuilder,
|
|
60
63
|
)
|
|
@@ -108,7 +111,7 @@ def gen_normalized_accounts(
|
|
|
108
111
|
|
|
109
112
|
@singledispatch
|
|
110
113
|
def to_account(val: Any) -> LocalAccount:
|
|
111
|
-
raise
|
|
114
|
+
raise Web3TypeError(
|
|
112
115
|
"key must be one of the types: "
|
|
113
116
|
"eth_keys.datatype.PrivateKey, eth_account.signers.local.LocalAccount, "
|
|
114
117
|
"or raw private key as a hex string or byte string. "
|
|
@@ -132,7 +135,8 @@ to_account.register(bytes, private_key_to_account)
|
|
|
132
135
|
|
|
133
136
|
|
|
134
137
|
def format_transaction(transaction: TxParams) -> TxParams:
|
|
135
|
-
"""
|
|
138
|
+
"""
|
|
139
|
+
Format transaction so that it can be used correctly in the signing middleware.
|
|
136
140
|
|
|
137
141
|
Converts bytes to hex strings and other types that can be passed to
|
|
138
142
|
the underlying layers. Also has the effect of normalizing 'from' for
|
web3/middleware/stalecheck.py
CHANGED
|
@@ -16,6 +16,7 @@ from toolz import (
|
|
|
16
16
|
|
|
17
17
|
from web3.exceptions import (
|
|
18
18
|
StaleBlockchain,
|
|
19
|
+
Web3ValueError,
|
|
19
20
|
)
|
|
20
21
|
from web3.middleware.base import (
|
|
21
22
|
Web3Middleware,
|
|
@@ -54,7 +55,7 @@ class StalecheckMiddlewareBuilder(Web3MiddlewareBuilder):
|
|
|
54
55
|
skip_stalecheck_for_methods: Collection[str] = SKIP_STALECHECK_FOR_METHODS,
|
|
55
56
|
) -> Web3Middleware:
|
|
56
57
|
if allowable_delay <= 0:
|
|
57
|
-
raise
|
|
58
|
+
raise Web3ValueError(
|
|
58
59
|
"You must set a positive allowable_delay in seconds for this middleware"
|
|
59
60
|
)
|
|
60
61
|
middleware = StalecheckMiddlewareBuilder(w3)
|
|
@@ -218,7 +218,7 @@ def _generate_random_private_key() -> HexStr:
|
|
|
218
218
|
WARNING: This is not a secure way to generate private keys and should only
|
|
219
219
|
be used for testing purposes.
|
|
220
220
|
"""
|
|
221
|
-
return encode_hex(bytes(bytearray(
|
|
221
|
+
return encode_hex(bytes(bytearray(random.randint(0, 255) for _ in range(32))))
|
|
222
222
|
|
|
223
223
|
|
|
224
224
|
@without_params
|
|
@@ -4,6 +4,7 @@ from typing import (
|
|
|
4
4
|
Callable,
|
|
5
5
|
Coroutine,
|
|
6
6
|
Dict,
|
|
7
|
+
Literal,
|
|
7
8
|
Optional,
|
|
8
9
|
Union,
|
|
9
10
|
)
|
|
@@ -18,9 +19,6 @@ from eth_utils import (
|
|
|
18
19
|
is_bytes,
|
|
19
20
|
)
|
|
20
21
|
|
|
21
|
-
from web3._utils.compat import (
|
|
22
|
-
Literal,
|
|
23
|
-
)
|
|
24
22
|
from web3.providers import (
|
|
25
23
|
BaseProvider,
|
|
26
24
|
)
|
|
@@ -33,6 +31,9 @@ from web3.types import (
|
|
|
33
31
|
RPCResponse,
|
|
34
32
|
)
|
|
35
33
|
|
|
34
|
+
from ...exceptions import (
|
|
35
|
+
Web3TypeError,
|
|
36
|
+
)
|
|
36
37
|
from ...middleware import (
|
|
37
38
|
async_combine_middleware,
|
|
38
39
|
combine_middleware,
|
|
@@ -133,7 +134,7 @@ class EthereumTesterProvider(BaseProvider):
|
|
|
133
134
|
elif isinstance(ethereum_tester, BaseChainBackend):
|
|
134
135
|
self.ethereum_tester = EthereumTester(ethereum_tester)
|
|
135
136
|
else:
|
|
136
|
-
raise
|
|
137
|
+
raise Web3TypeError(
|
|
137
138
|
"Expected ethereum_tester to be of type `eth_tester.EthereumTester` or "
|
|
138
139
|
"a subclass of `eth_tester.backends.base.BaseChainBackend`, "
|
|
139
140
|
f"instead received {type(ethereum_tester)}. "
|
|
@@ -72,7 +72,9 @@ is_not_named_block = complement(is_named_block)
|
|
|
72
72
|
# --- Request Mapping --- #
|
|
73
73
|
|
|
74
74
|
TRANSACTION_REQUEST_KEY_MAPPING = {
|
|
75
|
+
"blobVersionedHashes": "blob_versioned_hashes",
|
|
75
76
|
"gasPrice": "gas_price",
|
|
77
|
+
"maxFeePerBlobGas": "max_fee_per_blob_gas",
|
|
76
78
|
"maxFeePerGas": "max_fee_per_gas",
|
|
77
79
|
"maxPriorityFeePerGas": "max_priority_fee_per_gas",
|
|
78
80
|
"accessList": "access_list",
|
|
@@ -90,7 +92,7 @@ TRANSACTION_REQUEST_FORMATTERS = {
|
|
|
90
92
|
"maxFeePerGas": to_integer_if_hex,
|
|
91
93
|
"maxPriorityFeePerGas": to_integer_if_hex,
|
|
92
94
|
"accessList": apply_list_to_array_formatter(
|
|
93
|
-
|
|
95
|
+
apply_key_map({"storageKeys": "storage_keys"})
|
|
94
96
|
),
|
|
95
97
|
}
|
|
96
98
|
transaction_request_formatter = apply_formatters_to_dict(TRANSACTION_REQUEST_FORMATTERS)
|
|
@@ -123,10 +125,12 @@ filter_request_transformer = compose(
|
|
|
123
125
|
|
|
124
126
|
TRANSACTION_RESULT_KEY_MAPPING = {
|
|
125
127
|
"access_list": "accessList",
|
|
128
|
+
"blob_versioned_hashes": "blobVersionedHashes",
|
|
126
129
|
"block_hash": "blockHash",
|
|
127
130
|
"block_number": "blockNumber",
|
|
128
131
|
"chain_id": "chainId",
|
|
129
132
|
"gas_price": "gasPrice",
|
|
133
|
+
"max_fee_per_blob_gas": "maxFeePerBlobGas",
|
|
130
134
|
"max_fee_per_gas": "maxFeePerGas",
|
|
131
135
|
"max_priority_fee_per_gas": "maxPriorityFeePerGas",
|
|
132
136
|
"transaction_hash": "transactionHash",
|
|
@@ -164,6 +168,8 @@ RECEIPT_RESULT_KEY_MAPPING = {
|
|
|
164
168
|
"effective_gas_price": "effectiveGasPrice",
|
|
165
169
|
"transaction_hash": "transactionHash",
|
|
166
170
|
"transaction_index": "transactionIndex",
|
|
171
|
+
"blob_gas_used": "blobGasUsed",
|
|
172
|
+
"blob_gas_price": "blobGasPrice",
|
|
167
173
|
}
|
|
168
174
|
receipt_result_remapper = apply_key_map(RECEIPT_RESULT_KEY_MAPPING)
|
|
169
175
|
|
|
@@ -186,6 +192,9 @@ BLOCK_RESULT_KEY_MAPPING = {
|
|
|
186
192
|
# JSON-RPC spec still says miner
|
|
187
193
|
"coinbase": "miner",
|
|
188
194
|
"withdrawals_root": "withdrawalsRoot",
|
|
195
|
+
"parent_beacon_block_root": "parentBeaconBlockRoot",
|
|
196
|
+
"blob_gas_used": "blobGasUsed",
|
|
197
|
+
"excess_blob_gas": "excessBlobGas",
|
|
189
198
|
}
|
|
190
199
|
block_result_remapper = apply_key_map(BLOCK_RESULT_KEY_MAPPING)
|
|
191
200
|
|
web3/providers/ipc.py
CHANGED
|
@@ -26,6 +26,10 @@ from web3.types import (
|
|
|
26
26
|
RPCResponse,
|
|
27
27
|
)
|
|
28
28
|
|
|
29
|
+
from ..exceptions import (
|
|
30
|
+
Web3TypeError,
|
|
31
|
+
Web3ValueError,
|
|
32
|
+
)
|
|
29
33
|
from .base import (
|
|
30
34
|
JSONBaseProvider,
|
|
31
35
|
)
|
|
@@ -96,7 +100,7 @@ def get_default_ipc_path() -> str:
|
|
|
96
100
|
return r"\\.\pipe\geth.ipc"
|
|
97
101
|
|
|
98
102
|
else:
|
|
99
|
-
raise
|
|
103
|
+
raise Web3ValueError(
|
|
100
104
|
f"Unsupported platform '{sys.platform}'. Only darwin/linux/win32/"
|
|
101
105
|
"freebsd are supported. You must specify the ipc_path"
|
|
102
106
|
)
|
|
@@ -117,7 +121,7 @@ def get_dev_ipc_path() -> str:
|
|
|
117
121
|
return r"\\.\pipe\geth.ipc"
|
|
118
122
|
|
|
119
123
|
else:
|
|
120
|
-
raise
|
|
124
|
+
raise Web3ValueError(
|
|
121
125
|
f"Unsupported platform '{sys.platform}'. Only darwin/linux/win32/"
|
|
122
126
|
"freebsd are supported. You must specify the ipc_path"
|
|
123
127
|
)
|
|
@@ -139,7 +143,7 @@ class IPCProvider(JSONBaseProvider):
|
|
|
139
143
|
elif isinstance(ipc_path, str) or isinstance(ipc_path, Path):
|
|
140
144
|
self.ipc_path = str(Path(ipc_path).expanduser().resolve())
|
|
141
145
|
else:
|
|
142
|
-
raise
|
|
146
|
+
raise Web3TypeError("ipc_path must be of type string or pathlib.Path")
|
|
143
147
|
|
|
144
148
|
self.timeout = timeout
|
|
145
149
|
self._lock = threading.Lock()
|
|
@@ -33,6 +33,7 @@ from ..._utils.caching import (
|
|
|
33
33
|
)
|
|
34
34
|
from ...exceptions import (
|
|
35
35
|
ProviderConnectionError,
|
|
36
|
+
Web3TypeError,
|
|
36
37
|
)
|
|
37
38
|
from ..ipc import (
|
|
38
39
|
get_default_ipc_path,
|
|
@@ -71,7 +72,7 @@ class AsyncIPCProvider(PersistentConnectionProvider):
|
|
|
71
72
|
elif isinstance(ipc_path, str) or isinstance(ipc_path, Path):
|
|
72
73
|
self.ipc_path = str(Path(ipc_path).expanduser().resolve())
|
|
73
74
|
else:
|
|
74
|
-
raise
|
|
75
|
+
raise Web3TypeError("ipc_path must be of type string or pathlib.Path")
|
|
75
76
|
|
|
76
77
|
self._max_connection_retries = max_connection_retries
|
|
77
78
|
super().__init__(**kwargs)
|
|
@@ -91,7 +92,7 @@ class AsyncIPCProvider(PersistentConnectionProvider):
|
|
|
91
92
|
current_request_id = json.loads(request_data)["id"]
|
|
92
93
|
await self._get_response_for_request_id(current_request_id, timeout=2)
|
|
93
94
|
return True
|
|
94
|
-
except (OSError,
|
|
95
|
+
except (OSError, ProviderConnectionError) as e:
|
|
95
96
|
if show_traceback:
|
|
96
97
|
raise ProviderConnectionError(
|
|
97
98
|
f"Problem connecting to provider with error: {type(e)}: {e}"
|
|
@@ -114,11 +115,11 @@ class AsyncIPCProvider(PersistentConnectionProvider):
|
|
|
114
115
|
except OSError as e:
|
|
115
116
|
if _connection_attempts == self._max_connection_retries:
|
|
116
117
|
raise ProviderConnectionError(
|
|
117
|
-
f"Could not connect to
|
|
118
|
+
f"Could not connect to: {self.ipc_path}. "
|
|
118
119
|
f"Retries exceeded max of {self._max_connection_retries}."
|
|
119
120
|
) from e
|
|
120
121
|
self.logger.info(
|
|
121
|
-
f"Could not connect to
|
|
122
|
+
f"Could not connect to: {self.ipc_path}. Retrying in "
|
|
122
123
|
f"{round(_backoff_time, 1)} seconds.",
|
|
123
124
|
exc_info=True,
|
|
124
125
|
)
|
|
@@ -130,9 +131,7 @@ class AsyncIPCProvider(PersistentConnectionProvider):
|
|
|
130
131
|
self._writer.close()
|
|
131
132
|
await self._writer.wait_closed()
|
|
132
133
|
self._writer = None
|
|
133
|
-
self.logger.debug(
|
|
134
|
-
f'Successfully disconnected from endpoint: "{self.endpoint_uri}'
|
|
135
|
-
)
|
|
134
|
+
self.logger.debug(f'Successfully disconnected from : "{self.ipc_path}')
|
|
136
135
|
|
|
137
136
|
try:
|
|
138
137
|
self._message_listener_task.cancel()
|
|
@@ -30,7 +30,6 @@ DEFAULT_PERSISTENT_CONNECTION_TIMEOUT = 30.0
|
|
|
30
30
|
class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
|
|
31
31
|
logger = logging.getLogger("web3.providers.PersistentConnectionProvider")
|
|
32
32
|
has_persistent_connection = True
|
|
33
|
-
endpoint_uri: Optional[str] = None
|
|
34
33
|
|
|
35
34
|
_request_processor: RequestProcessor
|
|
36
35
|
_message_listener_task: Optional["asyncio.Task[None]"] = None
|
|
@@ -50,6 +49,17 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
|
|
|
50
49
|
self.request_timeout = request_timeout
|
|
51
50
|
self.silence_listener_task_exceptions = silence_listener_task_exceptions
|
|
52
51
|
|
|
52
|
+
def get_endpoint_uri_or_ipc_path(self) -> str:
|
|
53
|
+
if hasattr(self, "endpoint_uri"):
|
|
54
|
+
return str(self.endpoint_uri)
|
|
55
|
+
elif hasattr(self, "ipc_path"):
|
|
56
|
+
return str(self.ipc_path)
|
|
57
|
+
else:
|
|
58
|
+
raise AttributeError(
|
|
59
|
+
"`PersistentConnectionProvider` must have either `endpoint_uri` or "
|
|
60
|
+
"`ipc_path` attribute."
|
|
61
|
+
)
|
|
62
|
+
|
|
53
63
|
async def connect(self) -> None:
|
|
54
64
|
raise NotImplementedError("Must be implemented by subclasses")
|
|
55
65
|
|