web3 7.0.0b2__py3-none-any.whl → 7.7.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.
- ens/__init__.py +13 -2
- ens/_normalization.py +4 -4
- ens/async_ens.py +27 -15
- ens/base_ens.py +3 -1
- ens/contract_data.py +2 -2
- ens/ens.py +10 -7
- ens/exceptions.py +16 -29
- ens/specs/nf.json +1 -1
- ens/specs/normalization_spec.json +1 -1
- ens/utils.py +24 -32
- web3/__init__.py +23 -12
- web3/_utils/abi.py +157 -263
- web3/_utils/async_transactions.py +34 -20
- web3/_utils/batching.py +217 -0
- web3/_utils/blocks.py +6 -2
- web3/_utils/caching/__init__.py +12 -0
- web3/_utils/caching/caching_utils.py +433 -0
- web3/_utils/caching/request_caching_validation.py +287 -0
- web3/_utils/compat/__init__.py +2 -3
- web3/_utils/contract_sources/compile_contracts.py +1 -1
- web3/_utils/contract_sources/contract_data/ambiguous_function_contract.py +42 -0
- web3/_utils/contract_sources/contract_data/arrays_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/bytes_contracts.py +5 -5
- web3/_utils/contract_sources/contract_data/constructor_contracts.py +7 -7
- web3/_utils/contract_sources/contract_data/contract_caller_tester.py +3 -3
- web3/_utils/contract_sources/contract_data/emitter_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/event_contracts.py +50 -5
- web3/_utils/contract_sources/contract_data/extended_resolver.py +3 -3
- web3/_utils/contract_sources/contract_data/fallback_function_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/function_name_tester_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/math_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/offchain_lookup.py +3 -3
- web3/_utils/contract_sources/contract_data/offchain_resolver.py +3 -3
- web3/_utils/contract_sources/contract_data/panic_errors_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/payable_tester.py +3 -3
- web3/_utils/contract_sources/contract_data/receive_function_contracts.py +5 -5
- web3/_utils/contract_sources/contract_data/reflector_contracts.py +3 -3
- web3/_utils/contract_sources/contract_data/revert_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/simple_resolver.py +3 -3
- web3/_utils/contract_sources/contract_data/storage_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/string_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/tuple_contracts.py +5 -5
- web3/_utils/contracts.py +172 -220
- web3/_utils/datatypes.py +5 -1
- web3/_utils/decorators.py +6 -1
- web3/_utils/empty.py +1 -1
- web3/_utils/encoding.py +16 -12
- web3/_utils/error_formatters_utils.py +5 -3
- web3/_utils/events.py +78 -72
- web3/_utils/fee_utils.py +1 -3
- web3/_utils/filters.py +24 -22
- web3/_utils/formatters.py +2 -2
- web3/_utils/http.py +8 -2
- web3/_utils/http_session_manager.py +314 -0
- web3/_utils/math.py +14 -15
- web3/_utils/method_formatters.py +161 -34
- web3/_utils/module.py +2 -1
- web3/_utils/module_testing/__init__.py +3 -2
- web3/_utils/module_testing/eth_module.py +736 -583
- web3/_utils/module_testing/go_ethereum_debug_module.py +128 -0
- web3/_utils/module_testing/module_testing_utils.py +81 -24
- web3/_utils/module_testing/persistent_connection_provider.py +702 -220
- web3/_utils/module_testing/utils.py +114 -33
- web3/_utils/module_testing/web3_module.py +438 -17
- web3/_utils/normalizers.py +13 -11
- web3/_utils/rpc_abi.py +10 -22
- web3/_utils/threads.py +8 -7
- web3/_utils/transactions.py +32 -25
- web3/_utils/type_conversion.py +5 -1
- web3/_utils/validation.py +20 -17
- web3/beacon/__init__.py +5 -0
- web3/beacon/api_endpoints.py +3 -0
- web3/beacon/async_beacon.py +29 -6
- web3/beacon/beacon.py +24 -6
- web3/contract/__init__.py +7 -0
- web3/contract/async_contract.py +285 -82
- web3/contract/base_contract.py +556 -258
- web3/contract/contract.py +295 -84
- web3/contract/utils.py +251 -55
- web3/datastructures.py +49 -34
- web3/eth/__init__.py +7 -0
- web3/eth/async_eth.py +89 -69
- web3/eth/base_eth.py +7 -3
- web3/eth/eth.py +43 -66
- web3/exceptions.py +158 -83
- web3/gas_strategies/time_based.py +8 -6
- web3/geth.py +53 -184
- web3/main.py +77 -17
- web3/manager.py +362 -95
- web3/method.py +43 -15
- web3/middleware/__init__.py +17 -0
- web3/middleware/attrdict.py +12 -22
- web3/middleware/base.py +55 -2
- web3/middleware/filter.py +45 -23
- web3/middleware/formatting.py +6 -3
- web3/middleware/names.py +4 -1
- web3/middleware/signing.py +15 -6
- web3/middleware/stalecheck.py +2 -1
- web3/module.py +61 -25
- web3/providers/__init__.py +21 -0
- web3/providers/async_base.py +87 -32
- web3/providers/base.py +77 -32
- web3/providers/eth_tester/__init__.py +5 -0
- web3/providers/eth_tester/defaults.py +2 -55
- web3/providers/eth_tester/main.py +41 -15
- web3/providers/eth_tester/middleware.py +16 -17
- web3/providers/ipc.py +41 -17
- web3/providers/legacy_websocket.py +26 -1
- web3/providers/persistent/__init__.py +7 -0
- web3/providers/persistent/async_ipc.py +61 -121
- web3/providers/persistent/persistent.py +323 -16
- web3/providers/persistent/persistent_connection.py +54 -5
- web3/providers/persistent/request_processor.py +136 -56
- web3/providers/persistent/subscription_container.py +56 -0
- web3/providers/persistent/subscription_manager.py +233 -0
- web3/providers/persistent/websocket.py +29 -92
- web3/providers/rpc/__init__.py +5 -0
- web3/providers/rpc/async_rpc.py +73 -18
- web3/providers/rpc/rpc.py +73 -30
- web3/providers/rpc/utils.py +1 -13
- web3/scripts/install_pre_releases.py +33 -0
- web3/scripts/parse_pygeth_version.py +16 -0
- web3/testing.py +4 -4
- web3/tracing.py +9 -5
- web3/types.py +141 -74
- web3/utils/__init__.py +64 -5
- web3/utils/abi.py +790 -10
- web3/utils/address.py +8 -0
- web3/utils/async_exception_handling.py +20 -11
- web3/utils/caching.py +34 -4
- web3/utils/exception_handling.py +9 -12
- web3/utils/subscriptions.py +285 -0
- {web3-7.0.0b2.dist-info → web3-7.7.0.dist-info}/LICENSE +1 -1
- web3-7.7.0.dist-info/METADATA +130 -0
- web3-7.7.0.dist-info/RECORD +171 -0
- {web3-7.0.0b2.dist-info → web3-7.7.0.dist-info}/WHEEL +1 -1
- web3/_utils/caching.py +0 -155
- web3/_utils/contract_sources/contract_data/address_reflector.py +0 -29
- web3/_utils/module_testing/go_ethereum_personal_module.py +0 -300
- web3/_utils/request.py +0 -265
- web3-7.0.0b2.dist-info/METADATA +0 -106
- web3-7.0.0b2.dist-info/RECORD +0 -163
- /web3/_utils/{function_identifiers.py → abi_element_identifiers.py} +0 -0
- {web3-7.0.0b2.dist-info → web3-7.7.0.dist-info}/top_level.txt +0 -0
web3/_utils/transactions.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import math
|
|
2
2
|
from typing import (
|
|
3
3
|
TYPE_CHECKING,
|
|
4
|
+
Dict,
|
|
4
5
|
List,
|
|
6
|
+
Literal,
|
|
5
7
|
Optional,
|
|
6
8
|
Union,
|
|
7
9
|
cast,
|
|
@@ -19,9 +21,6 @@ from hexbytes import (
|
|
|
19
21
|
HexBytes,
|
|
20
22
|
)
|
|
21
23
|
|
|
22
|
-
from web3._utils.compat import (
|
|
23
|
-
Literal,
|
|
24
|
-
)
|
|
25
24
|
from web3._utils.utility_methods import (
|
|
26
25
|
all_in_dict,
|
|
27
26
|
any_in_dict,
|
|
@@ -29,6 +28,10 @@ from web3._utils.utility_methods import (
|
|
|
29
28
|
from web3.constants import (
|
|
30
29
|
DYNAMIC_FEE_TXN_PARAMS,
|
|
31
30
|
)
|
|
31
|
+
from web3.exceptions import (
|
|
32
|
+
Web3AttributeError,
|
|
33
|
+
Web3ValueError,
|
|
34
|
+
)
|
|
32
35
|
from web3.types import (
|
|
33
36
|
BlockIdentifier,
|
|
34
37
|
TxData,
|
|
@@ -49,6 +52,8 @@ TX_PARAM_LITERALS = Literal[
|
|
|
49
52
|
"nonce",
|
|
50
53
|
"chainId",
|
|
51
54
|
"accessList",
|
|
55
|
+
"maxFeePerBlobGas",
|
|
56
|
+
"blobVersionedHashes",
|
|
52
57
|
]
|
|
53
58
|
|
|
54
59
|
VALID_TRANSACTION_PARAMS: List[TX_PARAM_LITERALS] = [
|
|
@@ -64,19 +69,23 @@ VALID_TRANSACTION_PARAMS: List[TX_PARAM_LITERALS] = [
|
|
|
64
69
|
"data",
|
|
65
70
|
"nonce",
|
|
66
71
|
"chainId",
|
|
72
|
+
"maxFeePerBlobGas",
|
|
73
|
+
"blobVersionedHashes",
|
|
67
74
|
]
|
|
68
75
|
|
|
69
76
|
TRANSACTION_DEFAULTS = {
|
|
70
77
|
"value": 0,
|
|
71
78
|
"data": b"",
|
|
72
|
-
"gas": lambda w3, tx: w3.eth.estimate_gas(tx),
|
|
73
|
-
"gasPrice": lambda w3, tx: w3.eth.generate_gas_price(tx),
|
|
79
|
+
"gas": lambda w3, tx, _defaults: w3.eth.estimate_gas(tx),
|
|
80
|
+
"gasPrice": lambda w3, tx, _defaults: w3.eth.generate_gas_price(tx),
|
|
81
|
+
"maxPriorityFeePerGas": lambda w3, _tx, _defaults: w3.eth.max_priority_fee,
|
|
74
82
|
"maxFeePerGas": (
|
|
75
|
-
lambda w3, tx:
|
|
76
|
-
|
|
83
|
+
lambda w3, tx, defaults: (
|
|
84
|
+
tx.get("maxPriorityFeePerGas", defaults.get("maxPriorityFeePerGas"))
|
|
85
|
+
+ (2 * w3.eth.get_block("latest")["baseFeePerGas"])
|
|
86
|
+
)
|
|
77
87
|
),
|
|
78
|
-
"
|
|
79
|
-
"chainId": lambda w3, tx: w3.eth.chain_id,
|
|
88
|
+
"chainId": lambda w3, _tx, _defaults: w3.eth.chain_id,
|
|
80
89
|
}
|
|
81
90
|
|
|
82
91
|
if TYPE_CHECKING:
|
|
@@ -103,7 +112,7 @@ def fill_nonce(w3: "Web3", transaction: TxParams) -> TxParams:
|
|
|
103
112
|
@curry
|
|
104
113
|
def fill_transaction_defaults(w3: "Web3", transaction: TxParams) -> TxParams:
|
|
105
114
|
"""
|
|
106
|
-
|
|
115
|
+
If w3 is None, fill as much as possible while offline
|
|
107
116
|
"""
|
|
108
117
|
strategy_based_gas_price = w3.eth.generate_gas_price(transaction)
|
|
109
118
|
is_dynamic_fee_transaction = strategy_based_gas_price is None and (
|
|
@@ -111,7 +120,7 @@ def fill_transaction_defaults(w3: "Web3", transaction: TxParams) -> TxParams:
|
|
|
111
120
|
or any_in_dict(DYNAMIC_FEE_TXN_PARAMS, transaction)
|
|
112
121
|
)
|
|
113
122
|
|
|
114
|
-
defaults = {}
|
|
123
|
+
defaults: Dict[str, Union[bytes, int]] = {}
|
|
115
124
|
for key, default_getter in TRANSACTION_DEFAULTS.items():
|
|
116
125
|
if key not in transaction:
|
|
117
126
|
if (
|
|
@@ -126,10 +135,10 @@ def fill_transaction_defaults(w3: "Web3", transaction: TxParams) -> TxParams:
|
|
|
126
135
|
|
|
127
136
|
if callable(default_getter):
|
|
128
137
|
if w3 is None:
|
|
129
|
-
raise
|
|
138
|
+
raise Web3ValueError(
|
|
130
139
|
f"You must specify a '{key}' value in the transaction"
|
|
131
140
|
)
|
|
132
|
-
default_val = default_getter(w3, transaction)
|
|
141
|
+
default_val = default_getter(w3, transaction, defaults)
|
|
133
142
|
else:
|
|
134
143
|
default_val = default_getter
|
|
135
144
|
|
|
@@ -140,9 +149,7 @@ def fill_transaction_defaults(w3: "Web3", transaction: TxParams) -> TxParams:
|
|
|
140
149
|
def get_block_gas_limit(
|
|
141
150
|
w3: "Web3", block_identifier: Optional[BlockIdentifier] = None
|
|
142
151
|
) -> int:
|
|
143
|
-
|
|
144
|
-
block_identifier = w3.eth.block_number
|
|
145
|
-
block = w3.eth.get_block(block_identifier)
|
|
152
|
+
block = w3.eth.get_block(block_identifier or "latest")
|
|
146
153
|
return block["gasLimit"]
|
|
147
154
|
|
|
148
155
|
|
|
@@ -156,9 +163,9 @@ def get_buffered_gas_estimate(
|
|
|
156
163
|
gas_limit = get_block_gas_limit(w3)
|
|
157
164
|
|
|
158
165
|
if gas_estimate > gas_limit:
|
|
159
|
-
raise
|
|
160
|
-
"
|
|
161
|
-
f"
|
|
166
|
+
raise Web3ValueError(
|
|
167
|
+
"Gas estimate for transaction is higher than current network gas limits. "
|
|
168
|
+
f"Transaction could not be sent. Estimated: {gas_estimate}. "
|
|
162
169
|
f"Current gas limit: {gas_limit}"
|
|
163
170
|
)
|
|
164
171
|
|
|
@@ -168,7 +175,7 @@ def get_buffered_gas_estimate(
|
|
|
168
175
|
def get_required_transaction(w3: "Web3", transaction_hash: _Hash32) -> TxData:
|
|
169
176
|
current_transaction = w3.eth.get_transaction(transaction_hash)
|
|
170
177
|
if not current_transaction:
|
|
171
|
-
raise
|
|
178
|
+
raise Web3ValueError(
|
|
172
179
|
f"Supplied transaction with hash {transaction_hash!r} does not exist"
|
|
173
180
|
)
|
|
174
181
|
return current_transaction
|
|
@@ -200,7 +207,7 @@ def extract_valid_transaction_params(transaction_params: TxData) -> TxParams:
|
|
|
200
207
|
msg = 'failure to handle this transaction due to both "input: {}" and'
|
|
201
208
|
msg += ' "data: {}" are populated. You need to resolve this conflict.'
|
|
202
209
|
err_vals = (transaction_params["input"], extracted_params["data"])
|
|
203
|
-
raise
|
|
210
|
+
raise Web3AttributeError(msg.format(*err_vals))
|
|
204
211
|
else:
|
|
205
212
|
return extracted_params
|
|
206
213
|
else:
|
|
@@ -219,7 +226,7 @@ def extract_valid_transaction_params(transaction_params: TxData) -> TxParams:
|
|
|
219
226
|
def assert_valid_transaction_params(transaction_params: TxParams) -> None:
|
|
220
227
|
for param in transaction_params:
|
|
221
228
|
if param not in VALID_TRANSACTION_PARAMS:
|
|
222
|
-
raise
|
|
229
|
+
raise Web3ValueError(f"{param} is not a valid transaction parameter")
|
|
223
230
|
|
|
224
231
|
|
|
225
232
|
def prepare_replacement_transaction(
|
|
@@ -229,14 +236,14 @@ def prepare_replacement_transaction(
|
|
|
229
236
|
gas_multiplier: float = 1.125,
|
|
230
237
|
) -> TxParams:
|
|
231
238
|
if original_transaction["blockHash"] is not None:
|
|
232
|
-
raise
|
|
239
|
+
raise Web3ValueError(
|
|
233
240
|
f'Supplied transaction with hash {original_transaction["hash"]!r} '
|
|
234
241
|
"has already been mined"
|
|
235
242
|
)
|
|
236
243
|
if "nonce" in replacement_transaction and (
|
|
237
244
|
replacement_transaction["nonce"] != original_transaction["nonce"]
|
|
238
245
|
):
|
|
239
|
-
raise
|
|
246
|
+
raise Web3ValueError(
|
|
240
247
|
"Supplied nonce in new_transaction must match the pending transaction"
|
|
241
248
|
)
|
|
242
249
|
|
|
@@ -255,7 +262,7 @@ def prepare_replacement_transaction(
|
|
|
255
262
|
and original_transaction["gasPrice"] is not None
|
|
256
263
|
):
|
|
257
264
|
if replacement_transaction["gasPrice"] <= original_transaction["gasPrice"]:
|
|
258
|
-
raise
|
|
265
|
+
raise Web3ValueError(
|
|
259
266
|
"Supplied gas price must exceed existing transaction gas price"
|
|
260
267
|
)
|
|
261
268
|
|
web3/_utils/type_conversion.py
CHANGED
|
@@ -10,6 +10,10 @@ from eth_utils import (
|
|
|
10
10
|
to_hex,
|
|
11
11
|
)
|
|
12
12
|
|
|
13
|
+
from web3.exceptions import (
|
|
14
|
+
Web3ValueError,
|
|
15
|
+
)
|
|
16
|
+
|
|
13
17
|
|
|
14
18
|
def to_hex_if_bytes(val: Union[HexStr, str, bytes, bytearray]) -> HexStr:
|
|
15
19
|
"""
|
|
@@ -17,7 +21,7 @@ def to_hex_if_bytes(val: Union[HexStr, str, bytes, bytearray]) -> HexStr:
|
|
|
17
21
|
meant to work with bytes and hex strings.
|
|
18
22
|
"""
|
|
19
23
|
if isinstance(val, str) and not val.startswith("0x"):
|
|
20
|
-
raise
|
|
24
|
+
raise Web3ValueError(f"Expected a hex string. Got: {val!r}")
|
|
21
25
|
|
|
22
26
|
return to_hex(val) if isinstance(val, (bytes, bytearray)) else to_hex(hexstr=val)
|
|
23
27
|
|
web3/_utils/validation.py
CHANGED
|
@@ -5,10 +5,14 @@ from typing import (
|
|
|
5
5
|
)
|
|
6
6
|
|
|
7
7
|
from eth_typing import (
|
|
8
|
+
ABI,
|
|
9
|
+
ABIFunction,
|
|
8
10
|
HexStr,
|
|
9
11
|
TypeStr,
|
|
10
12
|
)
|
|
11
13
|
from eth_utils import (
|
|
14
|
+
abi_to_signature,
|
|
15
|
+
filter_abi_by_type,
|
|
12
16
|
function_abi_to_4byte_selector,
|
|
13
17
|
is_0x_prefixed,
|
|
14
18
|
is_binary_address,
|
|
@@ -38,8 +42,6 @@ from ens.utils import (
|
|
|
38
42
|
is_valid_ens_name,
|
|
39
43
|
)
|
|
40
44
|
from web3._utils.abi import (
|
|
41
|
-
abi_to_signature,
|
|
42
|
-
filter_by_type,
|
|
43
45
|
is_address_type,
|
|
44
46
|
is_array_type,
|
|
45
47
|
is_bool_type,
|
|
@@ -53,10 +55,8 @@ from web3._utils.abi import (
|
|
|
53
55
|
)
|
|
54
56
|
from web3.exceptions import (
|
|
55
57
|
InvalidAddress,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
ABI,
|
|
59
|
-
ABIFunction,
|
|
58
|
+
Web3TypeError,
|
|
59
|
+
Web3ValueError,
|
|
60
60
|
)
|
|
61
61
|
|
|
62
62
|
|
|
@@ -74,16 +74,19 @@ def validate_abi(abi: ABI) -> None:
|
|
|
74
74
|
Helper function for validating an ABI
|
|
75
75
|
"""
|
|
76
76
|
if not is_list_like(abi):
|
|
77
|
-
raise
|
|
77
|
+
raise Web3ValueError("'abi' is not a list")
|
|
78
78
|
|
|
79
79
|
if not all(is_dict(e) for e in abi):
|
|
80
|
-
raise
|
|
80
|
+
raise Web3ValueError("'abi' is not a list of dictionaries")
|
|
81
|
+
|
|
82
|
+
if not all("type" in e for e in abi):
|
|
83
|
+
raise Web3ValueError("'abi' must contain a list of elements each with a type")
|
|
81
84
|
|
|
82
|
-
functions =
|
|
85
|
+
functions = filter_abi_by_type("function", abi)
|
|
83
86
|
selectors = groupby(compose(encode_hex, function_abi_to_4byte_selector), functions)
|
|
84
87
|
duplicates = valfilter(lambda funcs: len(funcs) > 1, selectors)
|
|
85
88
|
if duplicates:
|
|
86
|
-
raise
|
|
89
|
+
raise Web3ValueError(
|
|
87
90
|
"Abi contains functions with colliding selectors. "
|
|
88
91
|
f"Functions {_prepare_selector_collision_msg(duplicates)}"
|
|
89
92
|
)
|
|
@@ -94,7 +97,7 @@ def validate_abi_type(abi_type: TypeStr) -> None:
|
|
|
94
97
|
Helper function for validating an abi_type
|
|
95
98
|
"""
|
|
96
99
|
if not is_recognized_type(abi_type):
|
|
97
|
-
raise
|
|
100
|
+
raise Web3ValueError(f"Unrecognized abi_type: {abi_type}")
|
|
98
101
|
|
|
99
102
|
|
|
100
103
|
def validate_abi_value(abi_type: TypeStr, value: Any) -> None:
|
|
@@ -107,12 +110,12 @@ def validate_abi_value(abi_type: TypeStr, value: Any) -> None:
|
|
|
107
110
|
specified_length = length_of_array_type(abi_type)
|
|
108
111
|
if specified_length is not None:
|
|
109
112
|
if specified_length < 1:
|
|
110
|
-
raise
|
|
113
|
+
raise Web3TypeError(
|
|
111
114
|
f"Invalid abi-type: {abi_type}. Length of fixed sized "
|
|
112
115
|
"arrays must be greater than 0."
|
|
113
116
|
)
|
|
114
117
|
if specified_length != len(value):
|
|
115
|
-
raise
|
|
118
|
+
raise Web3TypeError(
|
|
116
119
|
"The following array length does not the length specified"
|
|
117
120
|
f"by the abi-type, {abi_type}: {value}"
|
|
118
121
|
)
|
|
@@ -138,14 +141,14 @@ def validate_abi_value(abi_type: TypeStr, value: Any) -> None:
|
|
|
138
141
|
if is_0x_prefixed(value):
|
|
139
142
|
return
|
|
140
143
|
else:
|
|
141
|
-
raise
|
|
144
|
+
raise Web3TypeError(
|
|
142
145
|
"ABI values of abi-type 'bytes' must be either"
|
|
143
146
|
"a python3 'bytes' object or an '0x' prefixed string."
|
|
144
147
|
)
|
|
145
148
|
elif is_string_type(abi_type) and is_string(value):
|
|
146
149
|
return
|
|
147
150
|
|
|
148
|
-
raise
|
|
151
|
+
raise Web3TypeError(f"The following abi value is not a '{abi_type}': {value}")
|
|
149
152
|
|
|
150
153
|
|
|
151
154
|
def is_not_address_string(value: Any) -> bool:
|
|
@@ -173,7 +176,7 @@ def validate_address(value: Any) -> None:
|
|
|
173
176
|
return
|
|
174
177
|
|
|
175
178
|
if not isinstance(value, str):
|
|
176
|
-
raise
|
|
179
|
+
raise Web3TypeError(f"Address {value} must be provided as a string")
|
|
177
180
|
if not is_hex_address(value):
|
|
178
181
|
raise InvalidAddress(
|
|
179
182
|
"Address must be 20 bytes, as a hex string with a 0x prefix", value
|
|
@@ -204,7 +207,7 @@ def has_one_val(*args: Any, **kwargs: Any) -> bool:
|
|
|
204
207
|
|
|
205
208
|
def assert_one_val(*args: Any, **kwargs: Any) -> None:
|
|
206
209
|
if not has_one_val(*args, **kwargs):
|
|
207
|
-
raise
|
|
210
|
+
raise Web3TypeError(
|
|
208
211
|
"Exactly one of the passed values can be specified. "
|
|
209
212
|
f"Instead, values were: {args!r}, {kwargs!r}"
|
|
210
213
|
)
|
web3/beacon/__init__.py
CHANGED
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,16 +1,20 @@
|
|
|
1
1
|
from typing import (
|
|
2
2
|
Any,
|
|
3
3
|
Dict,
|
|
4
|
+
List,
|
|
5
|
+
Optional,
|
|
4
6
|
)
|
|
5
7
|
|
|
8
|
+
from aiohttp import (
|
|
9
|
+
ClientTimeout,
|
|
10
|
+
)
|
|
6
11
|
from eth_typing import (
|
|
7
12
|
URI,
|
|
8
13
|
HexStr,
|
|
9
14
|
)
|
|
10
15
|
|
|
11
|
-
from web3._utils.
|
|
12
|
-
|
|
13
|
-
async_json_make_get_request,
|
|
16
|
+
from web3._utils.http_session_manager import (
|
|
17
|
+
HTTPSessionManager,
|
|
14
18
|
)
|
|
15
19
|
from web3.beacon.api_endpoints import (
|
|
16
20
|
GET_ATTESTATIONS,
|
|
@@ -18,6 +22,7 @@ from web3.beacon.api_endpoints import (
|
|
|
18
22
|
GET_BEACON_HEADS,
|
|
19
23
|
GET_BEACON_STATE,
|
|
20
24
|
GET_BLINDED_BLOCKS,
|
|
25
|
+
GET_BLOB_SIDECARS,
|
|
21
26
|
GET_BLOCK,
|
|
22
27
|
GET_BLOCK_ATTESTATIONS,
|
|
23
28
|
GET_BLOCK_HEADER,
|
|
@@ -63,10 +68,15 @@ class AsyncBeacon:
|
|
|
63
68
|
) -> None:
|
|
64
69
|
self.base_url = base_url
|
|
65
70
|
self.request_timeout = request_timeout
|
|
71
|
+
self._request_session_manager = HTTPSessionManager()
|
|
66
72
|
|
|
67
|
-
async def _async_make_get_request(
|
|
73
|
+
async def _async_make_get_request(
|
|
74
|
+
self, endpoint_uri: str, params: Optional[Dict[str, str]] = None
|
|
75
|
+
) -> Dict[str, Any]:
|
|
68
76
|
uri = URI(self.base_url + endpoint_uri)
|
|
69
|
-
return await async_json_make_get_request(
|
|
77
|
+
return await self._request_session_manager.async_json_make_get_request(
|
|
78
|
+
uri, params=params, timeout=ClientTimeout(self.request_timeout)
|
|
79
|
+
)
|
|
70
80
|
|
|
71
81
|
# [ BEACON endpoints ]
|
|
72
82
|
|
|
@@ -208,7 +218,9 @@ class AsyncBeacon:
|
|
|
208
218
|
|
|
209
219
|
async def get_health(self) -> int:
|
|
210
220
|
url = URI(self.base_url + GET_HEALTH)
|
|
211
|
-
response =
|
|
221
|
+
response = (
|
|
222
|
+
await self._request_session_manager.async_get_response_from_get_request(url)
|
|
223
|
+
)
|
|
212
224
|
return response.status
|
|
213
225
|
|
|
214
226
|
async def get_version(self) -> Dict[str, Any]:
|
|
@@ -216,3 +228,14 @@ class AsyncBeacon:
|
|
|
216
228
|
|
|
217
229
|
async def get_syncing(self) -> Dict[str, Any]:
|
|
218
230
|
return await self._async_make_get_request(GET_SYNCING)
|
|
231
|
+
|
|
232
|
+
# [ BLOB endpoints ]
|
|
233
|
+
|
|
234
|
+
async def get_blob_sidecars(
|
|
235
|
+
self, block_id: str, indices: Optional[List[int]] = None
|
|
236
|
+
) -> Dict[str, Any]:
|
|
237
|
+
indices_param = {"indices": ",".join(map(str, indices))} if indices else None
|
|
238
|
+
return await self._async_make_get_request(
|
|
239
|
+
GET_BLOB_SIDECARS.format(block_id),
|
|
240
|
+
params=indices_param,
|
|
241
|
+
)
|
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 (
|
|
@@ -8,9 +10,8 @@ from eth_typing import (
|
|
|
8
10
|
HexStr,
|
|
9
11
|
)
|
|
10
12
|
|
|
11
|
-
from web3._utils.
|
|
12
|
-
|
|
13
|
-
json_make_get_request,
|
|
13
|
+
from web3._utils.http_session_manager import (
|
|
14
|
+
HTTPSessionManager,
|
|
14
15
|
)
|
|
15
16
|
from web3.beacon.api_endpoints import (
|
|
16
17
|
GET_ATTESTATIONS,
|
|
@@ -18,6 +19,7 @@ from web3.beacon.api_endpoints import (
|
|
|
18
19
|
GET_BEACON_HEADS,
|
|
19
20
|
GET_BEACON_STATE,
|
|
20
21
|
GET_BLINDED_BLOCKS,
|
|
22
|
+
GET_BLOB_SIDECARS,
|
|
21
23
|
GET_BLOCK,
|
|
22
24
|
GET_BLOCK_ATTESTATIONS,
|
|
23
25
|
GET_BLOCK_HEADER,
|
|
@@ -61,10 +63,15 @@ class Beacon:
|
|
|
61
63
|
) -> None:
|
|
62
64
|
self.base_url = base_url
|
|
63
65
|
self.request_timeout = request_timeout
|
|
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
|
-
return json_make_get_request(
|
|
72
|
+
return self._request_session_manager.json_make_get_request(
|
|
73
|
+
uri, params=params, timeout=self.request_timeout
|
|
74
|
+
)
|
|
68
75
|
|
|
69
76
|
# [ BEACON endpoints ]
|
|
70
77
|
|
|
@@ -196,7 +203,7 @@ class Beacon:
|
|
|
196
203
|
|
|
197
204
|
def get_health(self) -> int:
|
|
198
205
|
url = URI(self.base_url + GET_HEALTH)
|
|
199
|
-
response = get_response_from_get_request(url)
|
|
206
|
+
response = self._request_session_manager.get_response_from_get_request(url)
|
|
200
207
|
return response.status_code
|
|
201
208
|
|
|
202
209
|
def get_version(self) -> Dict[str, Any]:
|
|
@@ -204,3 +211,14 @@ class Beacon:
|
|
|
204
211
|
|
|
205
212
|
def get_syncing(self) -> Dict[str, Any]:
|
|
206
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
|
+
)
|