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
web3/exceptions.py
CHANGED
|
@@ -30,6 +30,44 @@ class Web3Exception(Exception):
|
|
|
30
30
|
# deal with other exceptions
|
|
31
31
|
"""
|
|
32
32
|
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
*args: Any,
|
|
36
|
+
user_message: Optional[str] = None,
|
|
37
|
+
):
|
|
38
|
+
super().__init__(*args)
|
|
39
|
+
|
|
40
|
+
# Assign properties of Web3Exception
|
|
41
|
+
self.user_message = user_message
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class Web3AssertionError(Web3Exception, AssertionError):
|
|
45
|
+
"""
|
|
46
|
+
A web3.py exception wrapper for `AssertionError`, for better control over
|
|
47
|
+
exception handling.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class Web3ValueError(Web3Exception, ValueError):
|
|
52
|
+
"""
|
|
53
|
+
A web3.py exception wrapper for `ValueError`, for better control over
|
|
54
|
+
exception handling.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class Web3AttributeError(Web3Exception, AttributeError):
|
|
59
|
+
"""
|
|
60
|
+
A web3.py exception wrapper for `AttributeError`, for better control over
|
|
61
|
+
exception handling.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class Web3TypeError(Web3Exception, TypeError):
|
|
66
|
+
"""
|
|
67
|
+
A web3.py exception wrapper for `TypeError`, for better control over
|
|
68
|
+
exception handling.
|
|
69
|
+
"""
|
|
70
|
+
|
|
33
71
|
|
|
34
72
|
class BadFunctionCallOutput(Web3Exception):
|
|
35
73
|
"""
|
|
@@ -38,24 +76,18 @@ class BadFunctionCallOutput(Web3Exception):
|
|
|
38
76
|
Most likely ABI mismatch.
|
|
39
77
|
"""
|
|
40
78
|
|
|
41
|
-
pass
|
|
42
|
-
|
|
43
79
|
|
|
44
80
|
class BlockNumberOutofRange(Web3Exception):
|
|
45
81
|
"""
|
|
46
82
|
block_identifier passed does not match known block.
|
|
47
83
|
"""
|
|
48
84
|
|
|
49
|
-
pass
|
|
50
|
-
|
|
51
85
|
|
|
52
86
|
class ProviderConnectionError(Web3Exception):
|
|
53
87
|
"""
|
|
54
88
|
Raised when unable to connect to a provider
|
|
55
89
|
"""
|
|
56
90
|
|
|
57
|
-
pass
|
|
58
|
-
|
|
59
91
|
|
|
60
92
|
class CannotHandleRequest(Web3Exception):
|
|
61
93
|
"""
|
|
@@ -63,16 +95,12 @@ class CannotHandleRequest(Web3Exception):
|
|
|
63
95
|
that the manager should proceed to the next provider.
|
|
64
96
|
"""
|
|
65
97
|
|
|
66
|
-
pass
|
|
67
|
-
|
|
68
98
|
|
|
69
99
|
class TooManyRequests(Web3Exception):
|
|
70
100
|
"""
|
|
71
101
|
Raised by a provider to signal that too many requests have been made consecutively.
|
|
72
102
|
"""
|
|
73
103
|
|
|
74
|
-
pass
|
|
75
|
-
|
|
76
104
|
|
|
77
105
|
class MultipleFailedRequests(Web3Exception):
|
|
78
106
|
"""
|
|
@@ -80,16 +108,12 @@ class MultipleFailedRequests(Web3Exception):
|
|
|
80
108
|
(or similar) data have failed.
|
|
81
109
|
"""
|
|
82
110
|
|
|
83
|
-
pass
|
|
84
|
-
|
|
85
111
|
|
|
86
112
|
class InvalidAddress(Web3Exception):
|
|
87
113
|
"""
|
|
88
114
|
The supplied address does not have a valid checksum, as defined in EIP-55
|
|
89
115
|
"""
|
|
90
116
|
|
|
91
|
-
pass
|
|
92
|
-
|
|
93
117
|
|
|
94
118
|
class NameNotFound(Web3Exception):
|
|
95
119
|
"""
|
|
@@ -97,8 +121,6 @@ class NameNotFound(Web3Exception):
|
|
|
97
121
|
does not resolve to an address.
|
|
98
122
|
"""
|
|
99
123
|
|
|
100
|
-
pass
|
|
101
|
-
|
|
102
124
|
|
|
103
125
|
class StaleBlockchain(Web3Exception):
|
|
104
126
|
"""
|
|
@@ -128,8 +150,6 @@ class MismatchedABI(Web3Exception):
|
|
|
128
150
|
attempt is made to access a function/event that does not exist in the ABI.
|
|
129
151
|
"""
|
|
130
152
|
|
|
131
|
-
pass
|
|
132
|
-
|
|
133
153
|
|
|
134
154
|
class ABIEventFunctionNotFound(AttributeError, MismatchedABI):
|
|
135
155
|
"""
|
|
@@ -137,8 +157,6 @@ class ABIEventFunctionNotFound(AttributeError, MismatchedABI):
|
|
|
137
157
|
that does not exist in the ABI.
|
|
138
158
|
"""
|
|
139
159
|
|
|
140
|
-
pass
|
|
141
|
-
|
|
142
160
|
|
|
143
161
|
class ABIFunctionNotFound(AttributeError, MismatchedABI):
|
|
144
162
|
"""
|
|
@@ -146,56 +164,43 @@ class ABIFunctionNotFound(AttributeError, MismatchedABI):
|
|
|
146
164
|
that does not exist in the ABI.
|
|
147
165
|
"""
|
|
148
166
|
|
|
149
|
-
pass
|
|
150
|
-
|
|
151
167
|
|
|
152
168
|
class FallbackNotFound(Web3Exception):
|
|
153
169
|
"""
|
|
154
170
|
Raised when fallback function doesn't exist in contract.
|
|
155
171
|
"""
|
|
156
172
|
|
|
157
|
-
pass
|
|
158
173
|
|
|
159
|
-
|
|
160
|
-
class Web3ValidationError(Web3Exception, ValidationError):
|
|
174
|
+
# type ignored because subclassing ValidationError which has type Any
|
|
175
|
+
class Web3ValidationError(Web3Exception, ValidationError): # type: ignore[misc]
|
|
161
176
|
"""
|
|
162
177
|
Raised when a supplied value is invalid.
|
|
163
178
|
"""
|
|
164
179
|
|
|
165
|
-
pass
|
|
166
|
-
|
|
167
180
|
|
|
168
181
|
class ExtraDataLengthError(Web3ValidationError):
|
|
169
182
|
"""
|
|
170
183
|
Raised when an RPC call returns >32 bytes of extraData.
|
|
171
184
|
"""
|
|
172
185
|
|
|
173
|
-
pass
|
|
174
|
-
|
|
175
186
|
|
|
176
187
|
class NoABIFunctionsFound(Web3Exception):
|
|
177
188
|
"""
|
|
178
189
|
Raised when an ABI is present, but doesn't contain any functions.
|
|
179
190
|
"""
|
|
180
191
|
|
|
181
|
-
pass
|
|
182
|
-
|
|
183
192
|
|
|
184
193
|
class NoABIFound(Web3Exception):
|
|
185
194
|
"""
|
|
186
195
|
Raised when no ABI is present.
|
|
187
196
|
"""
|
|
188
197
|
|
|
189
|
-
pass
|
|
190
|
-
|
|
191
198
|
|
|
192
199
|
class NoABIEventsFound(Web3Exception):
|
|
193
200
|
"""
|
|
194
201
|
Raised when an ABI doesn't contain any events.
|
|
195
202
|
"""
|
|
196
203
|
|
|
197
|
-
pass
|
|
198
|
-
|
|
199
204
|
|
|
200
205
|
class InsufficientData(Web3Exception):
|
|
201
206
|
"""
|
|
@@ -203,8 +208,6 @@ class InsufficientData(Web3Exception):
|
|
|
203
208
|
complete a calculation
|
|
204
209
|
"""
|
|
205
210
|
|
|
206
|
-
pass
|
|
207
|
-
|
|
208
211
|
|
|
209
212
|
class TimeExhausted(Web3Exception):
|
|
210
213
|
"""
|
|
@@ -212,16 +215,12 @@ class TimeExhausted(Web3Exception):
|
|
|
212
215
|
result within a specified timeout.
|
|
213
216
|
"""
|
|
214
217
|
|
|
215
|
-
pass
|
|
216
|
-
|
|
217
218
|
|
|
218
219
|
class TransactionNotFound(Web3Exception):
|
|
219
220
|
"""
|
|
220
221
|
Raised when a tx hash used to lookup a tx in a jsonrpc call cannot be found.
|
|
221
222
|
"""
|
|
222
223
|
|
|
223
|
-
pass
|
|
224
|
-
|
|
225
224
|
|
|
226
225
|
class TransactionIndexingInProgress(Web3Exception):
|
|
227
226
|
"""
|
|
@@ -229,40 +228,30 @@ class TransactionIndexingInProgress(Web3Exception):
|
|
|
229
228
|
still being in progress.
|
|
230
229
|
"""
|
|
231
230
|
|
|
232
|
-
pass
|
|
233
|
-
|
|
234
231
|
|
|
235
232
|
class BlockNotFound(Web3Exception):
|
|
236
233
|
"""
|
|
237
234
|
Raised when the block id used to lookup a block in a jsonrpc call cannot be found.
|
|
238
235
|
"""
|
|
239
236
|
|
|
240
|
-
pass
|
|
241
|
-
|
|
242
237
|
|
|
243
238
|
class InfuraProjectIdNotFound(Web3Exception):
|
|
244
239
|
"""
|
|
245
240
|
Raised when there is no Infura Project Id set.
|
|
246
241
|
"""
|
|
247
242
|
|
|
248
|
-
pass
|
|
249
|
-
|
|
250
243
|
|
|
251
244
|
class LogTopicError(Web3Exception):
|
|
252
245
|
"""
|
|
253
246
|
Raised when the number of log topics is mismatched.
|
|
254
247
|
"""
|
|
255
248
|
|
|
256
|
-
pass
|
|
257
|
-
|
|
258
249
|
|
|
259
250
|
class InvalidEventABI(Web3Exception):
|
|
260
251
|
"""
|
|
261
252
|
Raised when the event ABI is invalid.
|
|
262
253
|
"""
|
|
263
254
|
|
|
264
|
-
pass
|
|
265
|
-
|
|
266
255
|
|
|
267
256
|
class ContractLogicError(Web3Exception):
|
|
268
257
|
"""
|
|
@@ -274,6 +263,7 @@ class ContractLogicError(Web3Exception):
|
|
|
274
263
|
message: Optional[str] = None,
|
|
275
264
|
data: Optional[Union[str, Dict[str, str]]] = None,
|
|
276
265
|
):
|
|
266
|
+
super().__init__(message, data)
|
|
277
267
|
self.message = message
|
|
278
268
|
self.data = data
|
|
279
269
|
|
|
@@ -283,16 +273,12 @@ class ContractCustomError(ContractLogicError):
|
|
|
283
273
|
Raised on a contract revert custom error
|
|
284
274
|
"""
|
|
285
275
|
|
|
286
|
-
pass
|
|
287
|
-
|
|
288
276
|
|
|
289
277
|
class ContractPanicError(ContractLogicError):
|
|
290
278
|
"""
|
|
291
279
|
Raised when a contract reverts with Panic, as of Solidity 0.8.0
|
|
292
280
|
"""
|
|
293
281
|
|
|
294
|
-
pass
|
|
295
|
-
|
|
296
282
|
|
|
297
283
|
class OffchainLookup(ContractLogicError):
|
|
298
284
|
"""
|
|
@@ -330,12 +316,8 @@ class BadResponseFormat(Web3Exception):
|
|
|
330
316
|
Raised when a JSON-RPC response comes back in an unexpected format
|
|
331
317
|
"""
|
|
332
318
|
|
|
333
|
-
pass
|
|
334
|
-
|
|
335
319
|
|
|
336
320
|
class MethodUnavailable(Web3Exception):
|
|
337
321
|
"""
|
|
338
322
|
Raised when the method is not available on the node
|
|
339
323
|
"""
|
|
340
|
-
|
|
341
|
-
pass
|
|
@@ -84,8 +84,7 @@ def _get_raw_miner_data(
|
|
|
84
84
|
latest = w3.eth.get_block("latest", full_transactions=True)
|
|
85
85
|
|
|
86
86
|
for transaction in latest["transactions"]:
|
|
87
|
-
|
|
88
|
-
yield (latest["miner"], latest["hash"], transaction["gasPrice"]) # type: ignore
|
|
87
|
+
yield (latest["miner"], latest["hash"], transaction["gasPrice"])
|
|
89
88
|
|
|
90
89
|
block = latest
|
|
91
90
|
|
|
@@ -97,8 +96,7 @@ def _get_raw_miner_data(
|
|
|
97
96
|
# block numbers to make caching the data easier to implement.
|
|
98
97
|
block = w3.eth.get_block(block["parentHash"], full_transactions=True)
|
|
99
98
|
for transaction in block["transactions"]:
|
|
100
|
-
|
|
101
|
-
yield (block["miner"], block["hash"], transaction["gasPrice"]) # type: ignore # noqa: E501
|
|
99
|
+
yield (block["miner"], block["hash"], transaction["gasPrice"])
|
|
102
100
|
|
|
103
101
|
|
|
104
102
|
def _aggregate_miner_data(
|
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
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import asyncio
|
|
2
1
|
import logging
|
|
3
2
|
from typing import (
|
|
4
3
|
TYPE_CHECKING,
|
|
@@ -36,6 +35,8 @@ from web3.exceptions import (
|
|
|
36
35
|
BadResponseFormat,
|
|
37
36
|
MethodUnavailable,
|
|
38
37
|
ProviderConnectionError,
|
|
38
|
+
Web3TypeError,
|
|
39
|
+
Web3ValueError,
|
|
39
40
|
)
|
|
40
41
|
from web3.middleware import (
|
|
41
42
|
AttributeDictMiddleware,
|
|
@@ -239,14 +240,18 @@ class RequestManager:
|
|
|
239
240
|
error = response.get("error")
|
|
240
241
|
# Raise the error when the value is a string
|
|
241
242
|
if error is None or isinstance(error, str):
|
|
242
|
-
raise
|
|
243
|
+
raise Web3ValueError(error)
|
|
243
244
|
|
|
244
245
|
# Errors must include an integer code
|
|
245
246
|
code = error.get("code")
|
|
246
247
|
if not isinstance(code, int):
|
|
247
248
|
_raise_bad_response_format(response, "error['code'] must be an integer")
|
|
248
249
|
elif code == METHOD_NOT_FOUND:
|
|
249
|
-
raise MethodUnavailable(
|
|
250
|
+
raise MethodUnavailable(
|
|
251
|
+
error,
|
|
252
|
+
user_message="Check your node provider's API docs to see what "
|
|
253
|
+
"methods are supported",
|
|
254
|
+
)
|
|
250
255
|
|
|
251
256
|
# Errors must include a message
|
|
252
257
|
if not isinstance(error.get("message"), str):
|
|
@@ -256,7 +261,7 @@ class RequestManager:
|
|
|
256
261
|
|
|
257
262
|
apply_error_formatters(error_formatters, response)
|
|
258
263
|
|
|
259
|
-
raise
|
|
264
|
+
raise Web3ValueError(error)
|
|
260
265
|
|
|
261
266
|
# Format and validate results
|
|
262
267
|
elif "result" in response:
|
|
@@ -320,8 +325,8 @@ class RequestManager:
|
|
|
320
325
|
cast("AsyncWeb3", self.w3), cast("MiddlewareOnion", self.middleware_onion)
|
|
321
326
|
)
|
|
322
327
|
self.logger.debug(
|
|
323
|
-
"Making request to open socket connection
|
|
324
|
-
f"
|
|
328
|
+
"Making request to open socket connection: "
|
|
329
|
+
f"{provider.get_endpoint_uri_or_ipc_path()}, method: {method}"
|
|
325
330
|
)
|
|
326
331
|
response = await request_func(method, params)
|
|
327
332
|
return await self._process_response(response)
|
|
@@ -334,7 +339,7 @@ class RequestManager:
|
|
|
334
339
|
|
|
335
340
|
async def _message_stream(self) -> AsyncGenerator[RPCResponse, None]:
|
|
336
341
|
if not isinstance(self._provider, PersistentConnectionProvider):
|
|
337
|
-
raise
|
|
342
|
+
raise Web3TypeError(
|
|
338
343
|
"Only providers that maintain an open, persistent connection "
|
|
339
344
|
"can listen to streams."
|
|
340
345
|
)
|
|
@@ -345,11 +350,7 @@ class RequestManager:
|
|
|
345
350
|
)
|
|
346
351
|
|
|
347
352
|
while True:
|
|
348
|
-
|
|
349
|
-
# back to the event loop while waiting for the response in the queue.
|
|
350
|
-
await asyncio.sleep(0)
|
|
351
|
-
|
|
352
|
-
response = self._request_processor.pop_raw_response(subscription=True)
|
|
353
|
+
response = await self._request_processor.pop_raw_response(subscription=True)
|
|
353
354
|
if (
|
|
354
355
|
response is not None
|
|
355
356
|
and response.get("params", {}).get("subscription")
|
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``.
|