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/abi.py
CHANGED
|
@@ -25,7 +25,6 @@ from typing import (
|
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
from eth_abi import (
|
|
28
|
-
codec,
|
|
29
28
|
decoding,
|
|
30
29
|
encoding,
|
|
31
30
|
)
|
|
@@ -47,11 +46,24 @@ from eth_abi.registry import (
|
|
|
47
46
|
registry as default_registry,
|
|
48
47
|
)
|
|
49
48
|
from eth_typing import (
|
|
49
|
+
ABI,
|
|
50
|
+
ABIComponent,
|
|
51
|
+
ABIComponentIndexed,
|
|
52
|
+
ABIConstructor,
|
|
53
|
+
ABIElement,
|
|
54
|
+
ABIEvent,
|
|
55
|
+
ABIFallback,
|
|
56
|
+
ABIFunction,
|
|
57
|
+
ABIReceive,
|
|
50
58
|
HexStr,
|
|
51
59
|
TypeStr,
|
|
52
60
|
)
|
|
53
61
|
from eth_utils import (
|
|
62
|
+
collapse_if_tuple,
|
|
54
63
|
decode_hex,
|
|
64
|
+
filter_abi_by_type,
|
|
65
|
+
get_abi_input_names,
|
|
66
|
+
get_abi_input_types,
|
|
55
67
|
is_bytes,
|
|
56
68
|
is_list_like,
|
|
57
69
|
is_string,
|
|
@@ -59,15 +71,16 @@ from eth_utils import (
|
|
|
59
71
|
to_text,
|
|
60
72
|
to_tuple,
|
|
61
73
|
)
|
|
62
|
-
from eth_utils.abi import (
|
|
63
|
-
collapse_if_tuple,
|
|
64
|
-
)
|
|
65
74
|
from eth_utils.toolz import (
|
|
66
75
|
curry,
|
|
67
76
|
partial,
|
|
68
77
|
pipe,
|
|
69
78
|
)
|
|
70
79
|
|
|
80
|
+
from web3._utils.abi_element_identifiers import (
|
|
81
|
+
FallbackFn,
|
|
82
|
+
ReceiveFn,
|
|
83
|
+
)
|
|
71
84
|
from web3._utils.decorators import (
|
|
72
85
|
reject_recursive_repeats,
|
|
73
86
|
)
|
|
@@ -78,20 +91,15 @@ from web3._utils.formatters import (
|
|
|
78
91
|
recursive_map,
|
|
79
92
|
)
|
|
80
93
|
from web3.exceptions import (
|
|
81
|
-
FallbackNotFound,
|
|
82
94
|
MismatchedABI,
|
|
95
|
+
Web3AttributeError,
|
|
96
|
+
Web3TypeError,
|
|
97
|
+
Web3ValueError,
|
|
83
98
|
)
|
|
84
99
|
from web3.types import (
|
|
85
|
-
|
|
86
|
-
ABIEvent,
|
|
87
|
-
ABIEventParams,
|
|
88
|
-
ABIFunction,
|
|
89
|
-
ABIFunctionParams,
|
|
100
|
+
ABIElementIdentifier,
|
|
90
101
|
TReturn,
|
|
91
102
|
)
|
|
92
|
-
from web3.utils import ( # public utils module
|
|
93
|
-
get_abi_input_names,
|
|
94
|
-
)
|
|
95
103
|
|
|
96
104
|
if TYPE_CHECKING:
|
|
97
105
|
from web3 import ( # noqa: F401
|
|
@@ -99,92 +107,94 @@ if TYPE_CHECKING:
|
|
|
99
107
|
)
|
|
100
108
|
|
|
101
109
|
|
|
102
|
-
def
|
|
103
|
-
return
|
|
104
|
-
|
|
110
|
+
def fallback_func_abi_exists(contract_abi: ABI) -> Sequence[ABIFallback]:
|
|
111
|
+
return filter_abi_by_type("fallback", contract_abi)
|
|
105
112
|
|
|
106
|
-
def filter_by_name(name: str, contract_abi: ABI) -> List[Union[ABIFunction, ABIEvent]]:
|
|
107
|
-
return [
|
|
108
|
-
abi
|
|
109
|
-
for abi in contract_abi
|
|
110
|
-
if (
|
|
111
|
-
abi["type"] not in ("fallback", "constructor", "receive")
|
|
112
|
-
and abi["name"] == name
|
|
113
|
-
)
|
|
114
|
-
]
|
|
115
113
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if "inputs" not in abi and (abi["type"] == "fallback" or abi["type"] == "receive"):
|
|
119
|
-
return []
|
|
120
|
-
else:
|
|
121
|
-
return [collapse_if_tuple(cast(Dict[str, Any], arg)) for arg in abi["inputs"]]
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
def get_abi_output_types(abi: ABIFunction) -> List[str]:
|
|
125
|
-
if abi["type"] == "fallback":
|
|
126
|
-
return []
|
|
127
|
-
else:
|
|
128
|
-
return [collapse_if_tuple(cast(Dict[str, Any], arg)) for arg in abi["outputs"]]
|
|
114
|
+
def receive_func_abi_exists(contract_abi: ABI) -> Sequence[ABIReceive]:
|
|
115
|
+
return filter_abi_by_type("receive", contract_abi)
|
|
129
116
|
|
|
130
117
|
|
|
131
|
-
def
|
|
132
|
-
|
|
133
|
-
if receive_abis:
|
|
134
|
-
return cast(ABIFunction, receive_abis[0])
|
|
135
|
-
else:
|
|
136
|
-
raise FallbackNotFound("No receive function was found in the contract ABI.")
|
|
137
|
-
|
|
118
|
+
def get_indexed_event_inputs(event_abi: ABIEvent) -> Sequence[ABIComponentIndexed]:
|
|
119
|
+
return [arg for arg in event_abi["inputs"] if arg["indexed"] is True]
|
|
138
120
|
|
|
139
|
-
def get_fallback_func_abi(contract_abi: ABI) -> ABIFunction:
|
|
140
|
-
fallback_abis = filter_by_type("fallback", contract_abi)
|
|
141
|
-
if fallback_abis:
|
|
142
|
-
return cast(ABIFunction, fallback_abis[0])
|
|
143
|
-
else:
|
|
144
|
-
raise FallbackNotFound("No fallback function was found in the contract ABI.")
|
|
145
121
|
|
|
122
|
+
def exclude_indexed_event_inputs(event_abi: ABIEvent) -> Sequence[ABIComponentIndexed]:
|
|
123
|
+
return [arg for arg in event_abi["inputs"] if arg["indexed"] is False]
|
|
146
124
|
|
|
147
|
-
def fallback_func_abi_exists(contract_abi: ABI) -> List[Union[ABIFunction, ABIEvent]]:
|
|
148
|
-
return filter_by_type("fallback", contract_abi)
|
|
149
125
|
|
|
126
|
+
def filter_by_types(types: Collection[str], contract_abi: ABI) -> Sequence[ABIElement]:
|
|
127
|
+
return [abi_element for abi_element in contract_abi if abi_element["type"] in types]
|
|
150
128
|
|
|
151
|
-
def receive_func_abi_exists(contract_abi: ABI) -> List[Union[ABIFunction, ABIEvent]]:
|
|
152
|
-
return filter_by_type("receive", contract_abi)
|
|
153
129
|
|
|
130
|
+
def filter_by_argument_name(
|
|
131
|
+
argument_names: Collection[str], contract_abi: ABI
|
|
132
|
+
) -> Sequence[ABIElement]:
|
|
133
|
+
"""
|
|
134
|
+
Return a list of each ``ABIElement`` which contain arguments matching provided
|
|
135
|
+
names.
|
|
136
|
+
"""
|
|
137
|
+
abis_with_matching_args = []
|
|
138
|
+
for abi_element in contract_abi:
|
|
139
|
+
try:
|
|
140
|
+
abi_arg_names = get_abi_input_names(abi_element)
|
|
154
141
|
|
|
155
|
-
|
|
156
|
-
|
|
142
|
+
if set(argument_names).intersection(abi_arg_names) == set(argument_names):
|
|
143
|
+
abis_with_matching_args.append(abi_element)
|
|
144
|
+
except TypeError:
|
|
145
|
+
# fallback or receive functions do not have arguments
|
|
146
|
+
# proceed to next ABIElement
|
|
147
|
+
continue
|
|
157
148
|
|
|
149
|
+
return abis_with_matching_args
|
|
158
150
|
|
|
159
|
-
def exclude_indexed_event_inputs(event_abi: ABIEvent) -> List[ABIEventParams]:
|
|
160
|
-
return [arg for arg in event_abi["inputs"] if arg["indexed"] is False]
|
|
161
151
|
|
|
162
|
-
|
|
163
|
-
|
|
152
|
+
def filter_by_argument_type(
|
|
153
|
+
argument_types: Collection[str], contract_abi: ABI
|
|
154
|
+
) -> List[ABIElement]:
|
|
164
155
|
"""
|
|
165
|
-
Return
|
|
166
|
-
|
|
167
|
-
makes use of `collapse_if_tuple()` to collapse the appropriate component
|
|
168
|
-
types within a tuple type, if present.
|
|
156
|
+
Return a list of each ``ABIElement`` which contain arguments matching provided
|
|
157
|
+
types.
|
|
169
158
|
"""
|
|
170
|
-
|
|
159
|
+
abis_with_matching_args = []
|
|
160
|
+
for abi_element in contract_abi:
|
|
161
|
+
try:
|
|
162
|
+
abi_arg_types = get_abi_input_types(abi_element)
|
|
163
|
+
|
|
164
|
+
if set(argument_types).intersection(abi_arg_types) == set(argument_types):
|
|
165
|
+
abis_with_matching_args.append(abi_element)
|
|
166
|
+
except ValueError:
|
|
167
|
+
# fallback or receive functions do not have arguments
|
|
168
|
+
# proceed to next ABIElement
|
|
169
|
+
continue
|
|
170
|
+
|
|
171
|
+
return abis_with_matching_args
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def get_name_from_abi_element_identifier(
|
|
175
|
+
abi_element_identifier: ABIElementIdentifier,
|
|
176
|
+
) -> str:
|
|
177
|
+
if abi_element_identifier in ["fallback", FallbackFn]:
|
|
178
|
+
return "fallback"
|
|
179
|
+
elif abi_element_identifier in ["receive", ReceiveFn]:
|
|
180
|
+
return "receive"
|
|
181
|
+
elif is_text(abi_element_identifier):
|
|
182
|
+
return str(abi_element_identifier).split("(")[0]
|
|
183
|
+
else:
|
|
184
|
+
raise Web3TypeError("Unsupported function identifier")
|
|
171
185
|
|
|
172
186
|
|
|
173
|
-
def
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
187
|
+
def get_abi_element_signature(
|
|
188
|
+
abi_element_identifier: ABIElementIdentifier,
|
|
189
|
+
abi_element_argument_types: Optional[Sequence[str]] = None,
|
|
190
|
+
) -> str:
|
|
191
|
+
element_name = get_name_from_abi_element_identifier(abi_element_identifier)
|
|
192
|
+
argument_types = ",".join(abi_element_argument_types or [])
|
|
177
193
|
|
|
194
|
+
if element_name in ["fallback", "receive"]:
|
|
195
|
+
return element_name
|
|
178
196
|
|
|
179
|
-
|
|
180
|
-
argument_names: Collection[str], contract_abi: ABI
|
|
181
|
-
) -> List[Union[ABIFunction, ABIEvent]]:
|
|
182
|
-
return [
|
|
183
|
-
abi
|
|
184
|
-
for abi in contract_abi
|
|
185
|
-
if set(argument_names).intersection(get_abi_input_names(abi))
|
|
186
|
-
== set(argument_names)
|
|
187
|
-
]
|
|
197
|
+
return f"{element_name}({argument_types})"
|
|
188
198
|
|
|
189
199
|
|
|
190
200
|
class AddressEncoder(encoding.AddressEncoder):
|
|
@@ -193,7 +203,7 @@ class AddressEncoder(encoding.AddressEncoder):
|
|
|
193
203
|
if is_ens_name(value):
|
|
194
204
|
return
|
|
195
205
|
|
|
196
|
-
super().validate_value(value)
|
|
206
|
+
super().validate_value(value) # type: ignore[no-untyped-call]
|
|
197
207
|
|
|
198
208
|
|
|
199
209
|
class AcceptsHexStrEncoder(encoding.BaseEncoder):
|
|
@@ -208,7 +218,7 @@ class AcceptsHexStrEncoder(encoding.BaseEncoder):
|
|
|
208
218
|
subencoder: encoding.BaseEncoder,
|
|
209
219
|
**kwargs: Dict[str, Any],
|
|
210
220
|
) -> None:
|
|
211
|
-
super().__init__(**kwargs)
|
|
221
|
+
super().__init__(**kwargs) # type: ignore[no-untyped-call]
|
|
212
222
|
self.subencoder = subencoder
|
|
213
223
|
self.is_dynamic = subencoder.is_dynamic
|
|
214
224
|
|
|
@@ -220,14 +230,14 @@ class AcceptsHexStrEncoder(encoding.BaseEncoder):
|
|
|
220
230
|
# cast b/c expects BaseCoder but `from_type_string`
|
|
221
231
|
# restricted to BaseEncoder subclasses
|
|
222
232
|
subencoder = cast(
|
|
223
|
-
encoding.BaseEncoder, subencoder_cls.from_type_str(abi_type, registry)
|
|
233
|
+
encoding.BaseEncoder, subencoder_cls.from_type_str(abi_type, registry) # type: ignore[no-untyped-call] # noqa: E501
|
|
224
234
|
)
|
|
225
235
|
return cls(subencoder)
|
|
226
236
|
|
|
227
237
|
@classmethod
|
|
228
238
|
def get_subencoder_class(cls) -> Type[encoding.BaseEncoder]:
|
|
229
239
|
if cls.subencoder_cls is None:
|
|
230
|
-
raise
|
|
240
|
+
raise Web3AttributeError(f"No subencoder class is set. {cls.__name__}")
|
|
231
241
|
return cls.subencoder_cls
|
|
232
242
|
|
|
233
243
|
def validate_value(self, value: Any) -> None:
|
|
@@ -285,35 +295,39 @@ class ExactLengthBytesEncoder(BytesEncoder):
|
|
|
285
295
|
is_strict = True
|
|
286
296
|
|
|
287
297
|
def validate(self) -> None:
|
|
288
|
-
super().validate()
|
|
298
|
+
super().validate() # type: ignore[no-untyped-call]
|
|
289
299
|
if self.value_bit_size is None:
|
|
290
|
-
raise
|
|
300
|
+
raise Web3ValueError("`value_bit_size` may not be none")
|
|
291
301
|
if self.data_byte_size is None:
|
|
292
|
-
raise
|
|
302
|
+
raise Web3ValueError("`data_byte_size` may not be none")
|
|
293
303
|
if self.is_big_endian is None:
|
|
294
|
-
raise
|
|
304
|
+
raise Web3ValueError("`is_big_endian` may not be none")
|
|
295
305
|
|
|
296
306
|
if self.value_bit_size % 8 != 0:
|
|
297
|
-
raise
|
|
307
|
+
raise Web3ValueError(
|
|
298
308
|
f"Invalid value bit size: {self.value_bit_size}. "
|
|
299
309
|
"Must be a multiple of 8"
|
|
300
310
|
)
|
|
301
311
|
|
|
302
312
|
if self.value_bit_size > self.data_byte_size * 8:
|
|
303
|
-
raise
|
|
313
|
+
raise Web3ValueError("Value byte size exceeds data size")
|
|
304
314
|
|
|
305
|
-
@parse_type_str("bytes")
|
|
315
|
+
@parse_type_str("bytes") # type: ignore[no-untyped-call]
|
|
306
316
|
def from_type_str(
|
|
307
317
|
cls, abi_type: BasicType, registry: ABIRegistry
|
|
308
318
|
) -> "ExactLengthBytesEncoder":
|
|
309
319
|
subencoder_cls = cls.get_subencoder_class()
|
|
310
|
-
subencoder = subencoder_cls.from_type_str(abi_type.to_type_str(), registry)
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
320
|
+
subencoder = subencoder_cls.from_type_str(abi_type.to_type_str(), registry) # type: ignore[no-untyped-call] # noqa: E501
|
|
321
|
+
return cast(
|
|
322
|
+
ExactLengthBytesEncoder,
|
|
323
|
+
# type ignored b/c mypy thinks the __call__ is from BaseEncoder, but it's
|
|
324
|
+
# from ExactLengthBytesEncoder, which does have value_bit_size and
|
|
325
|
+
# data_byte_size attributes
|
|
326
|
+
cls( # type: ignore[call-arg]
|
|
327
|
+
subencoder,
|
|
328
|
+
value_bit_size=abi_type.sub * 8,
|
|
329
|
+
data_byte_size=abi_type.sub,
|
|
330
|
+
),
|
|
317
331
|
)
|
|
318
332
|
|
|
319
333
|
|
|
@@ -339,110 +353,7 @@ class TextStringEncoder(encoding.TextStringEncoder):
|
|
|
339
353
|
msg="not decodable as unicode string",
|
|
340
354
|
)
|
|
341
355
|
|
|
342
|
-
super().validate_value(value)
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
def filter_by_encodability(
|
|
346
|
-
abi_codec: codec.ABIEncoder,
|
|
347
|
-
args: Sequence[Any],
|
|
348
|
-
kwargs: Dict[str, Any],
|
|
349
|
-
contract_abi: ABI,
|
|
350
|
-
) -> List[ABIFunction]:
|
|
351
|
-
return [
|
|
352
|
-
cast(ABIFunction, function_abi)
|
|
353
|
-
for function_abi in contract_abi
|
|
354
|
-
if check_if_arguments_can_be_encoded(
|
|
355
|
-
cast(ABIFunction, function_abi), abi_codec, args, kwargs
|
|
356
|
-
)
|
|
357
|
-
]
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
def check_if_arguments_can_be_encoded(
|
|
361
|
-
function_abi: ABIFunction,
|
|
362
|
-
abi_codec: codec.ABIEncoder,
|
|
363
|
-
args: Sequence[Any],
|
|
364
|
-
kwargs: Dict[str, Any],
|
|
365
|
-
) -> bool:
|
|
366
|
-
try:
|
|
367
|
-
arguments = merge_args_and_kwargs(function_abi, args, kwargs)
|
|
368
|
-
except TypeError:
|
|
369
|
-
return False
|
|
370
|
-
|
|
371
|
-
if len(function_abi.get("inputs", [])) != len(arguments):
|
|
372
|
-
return False
|
|
373
|
-
|
|
374
|
-
try:
|
|
375
|
-
types, aligned_args = get_aligned_abi_inputs(function_abi, arguments)
|
|
376
|
-
except TypeError:
|
|
377
|
-
return False
|
|
378
|
-
|
|
379
|
-
return all(
|
|
380
|
-
abi_codec.is_encodable(_type, arg) for _type, arg in zip(types, aligned_args)
|
|
381
|
-
)
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
def merge_args_and_kwargs(
|
|
385
|
-
function_abi: ABIFunction, args: Sequence[Any], kwargs: Dict[str, Any]
|
|
386
|
-
) -> Tuple[Any, ...]:
|
|
387
|
-
"""
|
|
388
|
-
Takes a list of positional args (``args``) and a dict of keyword args
|
|
389
|
-
(``kwargs``) defining values to be passed to a call to the contract function
|
|
390
|
-
described by ``function_abi``. Checks to ensure that the correct number of
|
|
391
|
-
args were given, no duplicate args were given, and no unknown args were
|
|
392
|
-
given. Returns a list of argument values aligned to the order of inputs
|
|
393
|
-
defined in ``function_abi``.
|
|
394
|
-
"""
|
|
395
|
-
# Ensure the function is being applied to the correct number of args
|
|
396
|
-
if len(args) + len(kwargs) != len(function_abi.get("inputs", [])):
|
|
397
|
-
raise TypeError(
|
|
398
|
-
f"Incorrect argument count. Expected '{len(function_abi['inputs'])}'"
|
|
399
|
-
f". Got '{len(args) + len(kwargs)}'"
|
|
400
|
-
)
|
|
401
|
-
|
|
402
|
-
# If no keyword args were given, we don't need to align them
|
|
403
|
-
if not kwargs:
|
|
404
|
-
return cast(Tuple[Any, ...], args)
|
|
405
|
-
|
|
406
|
-
kwarg_names = set(kwargs.keys())
|
|
407
|
-
sorted_arg_names = tuple(arg_abi["name"] for arg_abi in function_abi["inputs"])
|
|
408
|
-
args_as_kwargs = dict(zip(sorted_arg_names, args))
|
|
409
|
-
|
|
410
|
-
# Check for duplicate args
|
|
411
|
-
duplicate_args = kwarg_names.intersection(args_as_kwargs.keys())
|
|
412
|
-
if duplicate_args:
|
|
413
|
-
raise TypeError(
|
|
414
|
-
f"{function_abi.get('name')}() got multiple values for argument(s) "
|
|
415
|
-
f"'{', '.join(duplicate_args)}'"
|
|
416
|
-
)
|
|
417
|
-
|
|
418
|
-
# Check for unknown args
|
|
419
|
-
unknown_args = kwarg_names.difference(sorted_arg_names)
|
|
420
|
-
if unknown_args:
|
|
421
|
-
if function_abi.get("name"):
|
|
422
|
-
raise TypeError(
|
|
423
|
-
f"{function_abi.get('name')}() got unexpected keyword argument(s)"
|
|
424
|
-
f" '{', '.join(unknown_args)}'"
|
|
425
|
-
)
|
|
426
|
-
raise TypeError(
|
|
427
|
-
f"Type: '{function_abi.get('type')}' got unexpected keyword argument(s)"
|
|
428
|
-
f" '{', '.join(unknown_args)}'"
|
|
429
|
-
)
|
|
430
|
-
|
|
431
|
-
# Sort args according to their position in the ABI and unzip them from their
|
|
432
|
-
# names
|
|
433
|
-
sorted_args = tuple(
|
|
434
|
-
zip(
|
|
435
|
-
*sorted(
|
|
436
|
-
itertools.chain(kwargs.items(), args_as_kwargs.items()),
|
|
437
|
-
key=lambda kv: sorted_arg_names.index(kv[0]),
|
|
438
|
-
)
|
|
439
|
-
)
|
|
440
|
-
)
|
|
441
|
-
|
|
442
|
-
if sorted_args:
|
|
443
|
-
return sorted_args[1]
|
|
444
|
-
else:
|
|
445
|
-
return tuple()
|
|
356
|
+
super().validate_value(value) # type: ignore[no-untyped-call]
|
|
446
357
|
|
|
447
358
|
|
|
448
359
|
TUPLE_TYPE_STR_RE = re.compile(r"^(tuple)((\[([1-9]\d*\b)?])*)??$")
|
|
@@ -464,7 +375,9 @@ def get_tuple_type_str_parts(s: str) -> Optional[Tuple[str, Optional[str]]]:
|
|
|
464
375
|
return None
|
|
465
376
|
|
|
466
377
|
|
|
467
|
-
def _align_abi_input(
|
|
378
|
+
def _align_abi_input(
|
|
379
|
+
arg_abi: Union[ABIComponent, ABIComponentIndexed], arg: Any
|
|
380
|
+
) -> Tuple[Any, ...]:
|
|
468
381
|
"""
|
|
469
382
|
Aligns the values of any mapping at any level of nesting in ``arg``
|
|
470
383
|
according to the layout of the corresponding abi spec.
|
|
@@ -488,7 +401,7 @@ def _align_abi_input(arg_abi: ABIFunctionParams, arg: Any) -> Tuple[Any, ...]:
|
|
|
488
401
|
new_abi = copy.copy(arg_abi)
|
|
489
402
|
new_abi["type"] = tuple_prefix + "[]" * (num_dims - 1)
|
|
490
403
|
|
|
491
|
-
sub_abis = itertools.repeat(new_abi)
|
|
404
|
+
sub_abis = [cast(ABIComponent, abi) for abi in itertools.repeat(new_abi)]
|
|
492
405
|
|
|
493
406
|
if isinstance(arg, abc.Mapping):
|
|
494
407
|
# Arg is mapping. Align values according to abi order.
|
|
@@ -497,7 +410,7 @@ def _align_abi_input(arg_abi: ABIFunctionParams, arg: Any) -> Tuple[Any, ...]:
|
|
|
497
410
|
aligned_arg = arg
|
|
498
411
|
|
|
499
412
|
if not is_list_like(aligned_arg):
|
|
500
|
-
raise
|
|
413
|
+
raise Web3TypeError(
|
|
501
414
|
f'Expected non-string sequence for "{arg_abi.get("type")}" '
|
|
502
415
|
f"component type: got {aligned_arg}"
|
|
503
416
|
)
|
|
@@ -511,38 +424,21 @@ def _align_abi_input(arg_abi: ABIFunctionParams, arg: Any) -> Tuple[Any, ...]:
|
|
|
511
424
|
)
|
|
512
425
|
|
|
513
426
|
|
|
514
|
-
def
|
|
515
|
-
abi: ABIFunction, args: Union[Tuple[Any, ...], Mapping[Any, Any]]
|
|
516
|
-
) -> Tuple[Tuple[Any, ...], Tuple[Any, ...]]:
|
|
427
|
+
def find_constructor_abi_element_by_type(contract_abi: ABI) -> ABIConstructor:
|
|
517
428
|
"""
|
|
518
|
-
|
|
519
|
-
Returns a list of type strings for the function's inputs and a list of
|
|
520
|
-
arguments which have been aligned to the layout of those types. The args
|
|
521
|
-
contained in ``args`` may contain nested mappings or sequences corresponding
|
|
522
|
-
to tuple-encoded values in ``abi``.
|
|
523
|
-
"""
|
|
524
|
-
input_abis = abi.get("inputs", [])
|
|
525
|
-
|
|
526
|
-
if isinstance(args, abc.Mapping):
|
|
527
|
-
# `args` is mapping. Align values according to abi order.
|
|
528
|
-
args = tuple(args[abi["name"]] for abi in input_abis)
|
|
529
|
-
|
|
530
|
-
return (
|
|
531
|
-
# typed dict cannot be used w/ a normal Dict
|
|
532
|
-
# https://github.com/python/mypy/issues/4976
|
|
533
|
-
tuple(collapse_if_tuple(abi) for abi in input_abis), # type: ignore
|
|
534
|
-
type(args)(_align_abi_input(abi, arg) for abi, arg in zip(input_abis, args)),
|
|
535
|
-
)
|
|
536
|
-
|
|
429
|
+
Find the constructor ABI element in the contract ABI.
|
|
537
430
|
|
|
538
|
-
|
|
431
|
+
This function is often used in place of `web3.utils.abi.get_abi_element` to find
|
|
432
|
+
a constructor without considering it's argument types. This is used prior to
|
|
433
|
+
encoding the abi, since the argument types are not known at that time.
|
|
434
|
+
"""
|
|
539
435
|
candidates = [abi for abi in contract_abi if abi["type"] == "constructor"]
|
|
540
436
|
if len(candidates) == 1:
|
|
541
437
|
return candidates[0]
|
|
542
438
|
elif len(candidates) == 0:
|
|
543
439
|
return None
|
|
544
440
|
elif len(candidates) > 1:
|
|
545
|
-
raise
|
|
441
|
+
raise Web3ValueError("Found multiple constructors.")
|
|
546
442
|
return None
|
|
547
443
|
|
|
548
444
|
|
|
@@ -564,7 +460,7 @@ STATIC_TYPES = list(
|
|
|
564
460
|
)
|
|
565
461
|
|
|
566
462
|
BASE_TYPE_REGEX = "|".join(
|
|
567
|
-
|
|
463
|
+
_type + "(?![a-z0-9])" for _type in itertools.chain(STATIC_TYPES, DYNAMIC_TYPES)
|
|
568
464
|
)
|
|
569
465
|
|
|
570
466
|
SUB_TYPE_REGEX = r"\[" "[0-9]*" r"\]"
|
|
@@ -630,14 +526,14 @@ END_BRACKETS_OF_ARRAY_TYPE_REGEX = r"\[[^]]*\]$"
|
|
|
630
526
|
|
|
631
527
|
def sub_type_of_array_type(abi_type: TypeStr) -> str:
|
|
632
528
|
if not is_array_type(abi_type):
|
|
633
|
-
raise
|
|
529
|
+
raise Web3ValueError(f"Cannot parse subtype of nonarray abi-type: {abi_type}")
|
|
634
530
|
|
|
635
|
-
return re.sub(END_BRACKETS_OF_ARRAY_TYPE_REGEX, "", abi_type, 1)
|
|
531
|
+
return re.sub(END_BRACKETS_OF_ARRAY_TYPE_REGEX, "", abi_type, count=1)
|
|
636
532
|
|
|
637
533
|
|
|
638
534
|
def length_of_array_type(abi_type: TypeStr) -> int:
|
|
639
535
|
if not is_array_type(abi_type):
|
|
640
|
-
raise
|
|
536
|
+
raise Web3ValueError(f"Cannot parse length of nonarray abi-type: {abi_type}")
|
|
641
537
|
|
|
642
538
|
inner_brackets = (
|
|
643
539
|
re.search(END_BRACKETS_OF_ARRAY_TYPE_REGEX, abi_type).group(0).strip("[]")
|
|
@@ -669,8 +565,8 @@ def is_probably_enum(abi_type: TypeStr) -> bool:
|
|
|
669
565
|
|
|
670
566
|
@to_tuple
|
|
671
567
|
def normalize_event_input_types(
|
|
672
|
-
abi_args: Collection[
|
|
673
|
-
) -> Iterable[Union[
|
|
568
|
+
abi_args: Collection[ABIEvent],
|
|
569
|
+
) -> Iterable[Union[ABIEvent, Dict[TypeStr, Any]]]:
|
|
674
570
|
for arg in abi_args:
|
|
675
571
|
if is_recognized_type(arg["type"]):
|
|
676
572
|
yield arg
|
|
@@ -680,17 +576,6 @@ def normalize_event_input_types(
|
|
|
680
576
|
yield arg
|
|
681
577
|
|
|
682
578
|
|
|
683
|
-
def abi_to_signature(abi: Union[ABIFunction, ABIEvent]) -> str:
|
|
684
|
-
function_signature = "{fn_name}({fn_input_types})".format(
|
|
685
|
-
fn_name=abi["name"],
|
|
686
|
-
fn_input_types=",".join(
|
|
687
|
-
collapse_if_tuple(dict(arg))
|
|
688
|
-
for arg in normalize_event_input_types(abi.get("inputs", []))
|
|
689
|
-
),
|
|
690
|
-
)
|
|
691
|
-
return function_signature
|
|
692
|
-
|
|
693
|
-
|
|
694
579
|
########################################################
|
|
695
580
|
#
|
|
696
581
|
# Conditionally modifying data, tagged with ABI Types
|
|
@@ -705,8 +590,8 @@ def map_abi_data(
|
|
|
705
590
|
data: Sequence[Any],
|
|
706
591
|
) -> Any:
|
|
707
592
|
"""
|
|
708
|
-
|
|
709
|
-
|
|
593
|
+
Applies normalizers to your data, in the context of the relevant types.
|
|
594
|
+
Each normalizer is in the format:
|
|
710
595
|
|
|
711
596
|
def normalizer(datatype, data):
|
|
712
597
|
# Conditionally modify data
|
|
@@ -772,7 +657,7 @@ def data_tree_map(
|
|
|
772
657
|
|
|
773
658
|
class ABITypedData(namedtuple("ABITypedData", "abi_type, data")):
|
|
774
659
|
"""
|
|
775
|
-
|
|
660
|
+
Marks data as having a certain ABI-type.
|
|
776
661
|
|
|
777
662
|
>>> a1 = ABITypedData(['address', addr1])
|
|
778
663
|
>>> a2 = ABITypedData(['address', addr2])
|
|
@@ -841,7 +726,7 @@ def strip_abi_type(elements: Any) -> Any:
|
|
|
841
726
|
def build_non_strict_registry() -> ABIRegistry:
|
|
842
727
|
# We make a copy here just to make sure that eth-abi's default registry is not
|
|
843
728
|
# affected by our custom encoder subclasses
|
|
844
|
-
registry = default_registry.copy()
|
|
729
|
+
registry = default_registry.copy() # type: ignore[no-untyped-call]
|
|
845
730
|
|
|
846
731
|
registry.unregister("address")
|
|
847
732
|
registry.unregister("bytes<M>")
|
|
@@ -849,25 +734,25 @@ def build_non_strict_registry() -> ABIRegistry:
|
|
|
849
734
|
registry.unregister("string")
|
|
850
735
|
|
|
851
736
|
registry.register(
|
|
852
|
-
BaseEquals("address"),
|
|
737
|
+
BaseEquals("address"), # type: ignore[no-untyped-call]
|
|
853
738
|
AddressEncoder,
|
|
854
739
|
decoding.AddressDecoder,
|
|
855
740
|
label="address",
|
|
856
741
|
)
|
|
857
742
|
registry.register(
|
|
858
|
-
BaseEquals("bytes", with_sub=True),
|
|
743
|
+
BaseEquals("bytes", with_sub=True), # type: ignore[no-untyped-call]
|
|
859
744
|
BytesEncoder,
|
|
860
745
|
decoding.BytesDecoder,
|
|
861
746
|
label="bytes<M>",
|
|
862
747
|
)
|
|
863
748
|
registry.register(
|
|
864
|
-
BaseEquals("bytes", with_sub=False),
|
|
749
|
+
BaseEquals("bytes", with_sub=False), # type: ignore[no-untyped-call]
|
|
865
750
|
ByteStringEncoder,
|
|
866
751
|
decoding.ByteStringDecoder,
|
|
867
752
|
label="bytes",
|
|
868
753
|
)
|
|
869
754
|
registry.register(
|
|
870
|
-
BaseEquals("string"),
|
|
755
|
+
BaseEquals("string"), # type: ignore[no-untyped-call]
|
|
871
756
|
TextStringEncoder,
|
|
872
757
|
decoding.StringDecoder,
|
|
873
758
|
label="string",
|
|
@@ -876,7 +761,7 @@ def build_non_strict_registry() -> ABIRegistry:
|
|
|
876
761
|
|
|
877
762
|
|
|
878
763
|
def build_strict_registry() -> ABIRegistry:
|
|
879
|
-
registry = default_registry.copy()
|
|
764
|
+
registry = default_registry.copy() # type: ignore[no-untyped-call]
|
|
880
765
|
|
|
881
766
|
registry.unregister("address")
|
|
882
767
|
registry.unregister("bytes<M>")
|
|
@@ -884,25 +769,25 @@ def build_strict_registry() -> ABIRegistry:
|
|
|
884
769
|
registry.unregister("string")
|
|
885
770
|
|
|
886
771
|
registry.register(
|
|
887
|
-
BaseEquals("address"),
|
|
772
|
+
BaseEquals("address"), # type: ignore[no-untyped-call]
|
|
888
773
|
AddressEncoder,
|
|
889
774
|
decoding.AddressDecoder,
|
|
890
775
|
label="address",
|
|
891
776
|
)
|
|
892
777
|
registry.register(
|
|
893
|
-
BaseEquals("bytes", with_sub=True),
|
|
778
|
+
BaseEquals("bytes", with_sub=True), # type: ignore[no-untyped-call]
|
|
894
779
|
ExactLengthBytesEncoder,
|
|
895
780
|
decoding.BytesDecoder,
|
|
896
781
|
label="bytes<M>",
|
|
897
782
|
)
|
|
898
783
|
registry.register(
|
|
899
|
-
BaseEquals("bytes", with_sub=False),
|
|
784
|
+
BaseEquals("bytes", with_sub=False), # type: ignore[no-untyped-call]
|
|
900
785
|
StrictByteStringEncoder,
|
|
901
786
|
decoding.ByteStringDecoder,
|
|
902
787
|
label="bytes",
|
|
903
788
|
)
|
|
904
789
|
registry.register(
|
|
905
|
-
BaseEquals("string"),
|
|
790
|
+
BaseEquals("string"), # type: ignore[no-untyped-call]
|
|
906
791
|
encoding.TextStringEncoder,
|
|
907
792
|
decoding.StringDecoder,
|
|
908
793
|
label="string",
|
|
@@ -911,7 +796,11 @@ def build_strict_registry() -> ABIRegistry:
|
|
|
911
796
|
|
|
912
797
|
|
|
913
798
|
def named_tree(
|
|
914
|
-
abi: Iterable[
|
|
799
|
+
abi: Iterable[
|
|
800
|
+
Union[
|
|
801
|
+
ABIComponent, ABIComponentIndexed, ABIFunction, ABIEvent, Dict[TypeStr, Any]
|
|
802
|
+
]
|
|
803
|
+
],
|
|
915
804
|
data: Iterable[Tuple[Any, ...]],
|
|
916
805
|
) -> Dict[str, Any]:
|
|
917
806
|
"""
|
|
@@ -924,10 +813,12 @@ def named_tree(
|
|
|
924
813
|
|
|
925
814
|
|
|
926
815
|
def _named_subtree(
|
|
927
|
-
abi: Union[
|
|
816
|
+
abi: Union[
|
|
817
|
+
ABIComponent, ABIComponentIndexed, ABIFunction, ABIEvent, Dict[TypeStr, Any]
|
|
818
|
+
],
|
|
928
819
|
data: Tuple[Any, ...],
|
|
929
820
|
) -> Union[Dict[str, Any], Tuple[Any, ...], List[Any]]:
|
|
930
|
-
abi_type = parse(collapse_if_tuple(
|
|
821
|
+
abi_type = parse(collapse_if_tuple(cast(Dict[str, Any], abi)))
|
|
931
822
|
|
|
932
823
|
if abi_type.is_array:
|
|
933
824
|
item_type = abi_type.item_type.to_type_str()
|
|
@@ -936,7 +827,11 @@ def _named_subtree(
|
|
|
936
827
|
return items
|
|
937
828
|
|
|
938
829
|
elif isinstance(abi_type, TupleType):
|
|
939
|
-
abi
|
|
830
|
+
if abi.get("indexed"):
|
|
831
|
+
abi = cast(ABIComponentIndexed, abi)
|
|
832
|
+
else:
|
|
833
|
+
abi = cast(ABIComponent, abi)
|
|
834
|
+
|
|
940
835
|
names = [item["name"] for item in abi["components"]]
|
|
941
836
|
items = [_named_subtree(*item) for item in zip(abi["components"], data)]
|
|
942
837
|
|
|
@@ -1029,7 +924,6 @@ async def async_map_if_collection(
|
|
|
1029
924
|
Apply an awaitable method to each element of a collection or value of a dictionary.
|
|
1030
925
|
If the value is not a collection, return it unmodified.
|
|
1031
926
|
"""
|
|
1032
|
-
|
|
1033
927
|
datatype = type(value)
|
|
1034
928
|
if isinstance(value, Mapping):
|
|
1035
929
|
return datatype({key: await func(val) for key, val in value.values()})
|