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/contracts.py
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import copy
|
|
1
2
|
import functools
|
|
2
3
|
from typing import (
|
|
3
4
|
TYPE_CHECKING,
|
|
4
5
|
Any,
|
|
5
6
|
Callable,
|
|
6
7
|
Dict,
|
|
8
|
+
List,
|
|
7
9
|
Optional,
|
|
8
10
|
Sequence,
|
|
9
11
|
Tuple,
|
|
10
|
-
Type,
|
|
11
12
|
Union,
|
|
12
13
|
cast,
|
|
13
14
|
)
|
|
@@ -19,6 +20,14 @@ from eth_abi.registry import (
|
|
|
19
20
|
registry as default_registry,
|
|
20
21
|
)
|
|
21
22
|
from eth_typing import (
|
|
23
|
+
ABI,
|
|
24
|
+
ABICallable,
|
|
25
|
+
ABIConstructor,
|
|
26
|
+
ABIElement,
|
|
27
|
+
ABIEvent,
|
|
28
|
+
ABIFallback,
|
|
29
|
+
ABIFunction,
|
|
30
|
+
ABIReceive,
|
|
22
31
|
ChecksumAddress,
|
|
23
32
|
HexStr,
|
|
24
33
|
TypeStr,
|
|
@@ -26,11 +35,9 @@ from eth_typing import (
|
|
|
26
35
|
from eth_utils import (
|
|
27
36
|
add_0x_prefix,
|
|
28
37
|
encode_hex,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
is_list_like,
|
|
33
|
-
is_text,
|
|
38
|
+
filter_abi_by_name,
|
|
39
|
+
filter_abi_by_type,
|
|
40
|
+
get_abi_input_types,
|
|
34
41
|
)
|
|
35
42
|
from eth_utils.toolz import (
|
|
36
43
|
pipe,
|
|
@@ -40,19 +47,10 @@ from hexbytes import (
|
|
|
40
47
|
)
|
|
41
48
|
|
|
42
49
|
from web3._utils.abi import (
|
|
43
|
-
abi_to_signature,
|
|
44
|
-
check_if_arguments_can_be_encoded,
|
|
45
|
-
filter_by_argument_count,
|
|
46
50
|
filter_by_argument_name,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
filter_by_type,
|
|
50
|
-
get_abi_input_types,
|
|
51
|
-
get_aligned_abi_inputs,
|
|
52
|
-
get_fallback_func_abi,
|
|
53
|
-
get_receive_func_abi,
|
|
51
|
+
get_abi_element_signature,
|
|
52
|
+
get_name_from_abi_element_identifier,
|
|
54
53
|
map_abi_data,
|
|
55
|
-
merge_args_and_kwargs,
|
|
56
54
|
named_tree,
|
|
57
55
|
)
|
|
58
56
|
from web3._utils.blocks import (
|
|
@@ -61,10 +59,6 @@ from web3._utils.blocks import (
|
|
|
61
59
|
from web3._utils.encoding import (
|
|
62
60
|
to_hex,
|
|
63
61
|
)
|
|
64
|
-
from web3._utils.function_identifiers import (
|
|
65
|
-
FallbackFn,
|
|
66
|
-
ReceiveFn,
|
|
67
|
-
)
|
|
68
62
|
from web3._utils.method_formatters import (
|
|
69
63
|
to_integer_if_hex,
|
|
70
64
|
)
|
|
@@ -75,17 +69,24 @@ from web3._utils.normalizers import (
|
|
|
75
69
|
abi_string_to_text,
|
|
76
70
|
)
|
|
77
71
|
from web3.exceptions import (
|
|
78
|
-
|
|
72
|
+
BlockNumberOutOfRange,
|
|
73
|
+
Web3TypeError,
|
|
79
74
|
Web3ValidationError,
|
|
75
|
+
Web3ValueError,
|
|
80
76
|
)
|
|
81
77
|
from web3.types import (
|
|
82
|
-
|
|
83
|
-
ABIEvent,
|
|
84
|
-
ABIFunction,
|
|
78
|
+
ABIElementIdentifier,
|
|
85
79
|
BlockIdentifier,
|
|
86
80
|
BlockNumber,
|
|
81
|
+
TContractEvent,
|
|
82
|
+
TContractFn,
|
|
87
83
|
TxParams,
|
|
88
84
|
)
|
|
85
|
+
from web3.utils.abi import (
|
|
86
|
+
check_if_arguments_can_be_encoded,
|
|
87
|
+
get_abi_element,
|
|
88
|
+
get_abi_element_info,
|
|
89
|
+
)
|
|
89
90
|
|
|
90
91
|
if TYPE_CHECKING:
|
|
91
92
|
from web3 import ( # noqa: F401
|
|
@@ -94,130 +95,50 @@ if TYPE_CHECKING:
|
|
|
94
95
|
)
|
|
95
96
|
|
|
96
97
|
|
|
97
|
-
def extract_argument_types(*args: Sequence[Any]) -> str:
|
|
98
|
-
"""
|
|
99
|
-
Takes a list of arguments and returns a string representation of the argument types,
|
|
100
|
-
appropriately collapsing `tuple` types into the respective nested types.
|
|
101
|
-
"""
|
|
102
|
-
collapsed_args = []
|
|
103
|
-
|
|
104
|
-
for arg in args:
|
|
105
|
-
if is_list_like(arg):
|
|
106
|
-
collapsed_nested = []
|
|
107
|
-
for nested in arg:
|
|
108
|
-
if is_list_like(nested):
|
|
109
|
-
collapsed_nested.append(f"({extract_argument_types(nested)})")
|
|
110
|
-
else:
|
|
111
|
-
collapsed_nested.append(_get_argument_readable_type(nested))
|
|
112
|
-
collapsed_args.append(",".join(collapsed_nested))
|
|
113
|
-
else:
|
|
114
|
-
collapsed_args.append(_get_argument_readable_type(arg))
|
|
115
|
-
|
|
116
|
-
return ",".join(collapsed_args)
|
|
117
|
-
|
|
118
|
-
|
|
119
98
|
def find_matching_event_abi(
|
|
120
99
|
abi: ABI,
|
|
121
100
|
event_name: Optional[str] = None,
|
|
122
101
|
argument_names: Optional[Sequence[str]] = None,
|
|
123
102
|
) -> ABIEvent:
|
|
124
|
-
filters = [
|
|
125
|
-
functools.partial(
|
|
103
|
+
filters: List[functools.partial[Sequence[ABIElement]]] = [
|
|
104
|
+
functools.partial(filter_abi_by_type, "event"),
|
|
126
105
|
]
|
|
127
106
|
|
|
128
107
|
if event_name is not None:
|
|
129
|
-
filters.append(functools.partial(
|
|
108
|
+
filters.append(functools.partial(filter_abi_by_name, event_name))
|
|
130
109
|
|
|
131
110
|
if argument_names is not None:
|
|
132
111
|
filters.append(functools.partial(filter_by_argument_name, argument_names))
|
|
133
112
|
|
|
134
|
-
event_abi_candidates = pipe(abi, *filters)
|
|
113
|
+
event_abi_candidates: Sequence[ABIEvent] = pipe(abi, *filters)
|
|
135
114
|
|
|
136
115
|
if len(event_abi_candidates) == 1:
|
|
137
116
|
return event_abi_candidates[0]
|
|
138
117
|
elif not event_abi_candidates:
|
|
139
|
-
raise
|
|
118
|
+
raise Web3ValueError("No matching events found")
|
|
140
119
|
else:
|
|
141
|
-
raise
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
def find_matching_fn_abi(
|
|
145
|
-
abi: ABI,
|
|
146
|
-
abi_codec: ABICodec,
|
|
147
|
-
fn_identifier: Optional[Union[str, Type[FallbackFn], Type[ReceiveFn]]] = None,
|
|
148
|
-
args: Optional[Sequence[Any]] = None,
|
|
149
|
-
kwargs: Optional[Any] = None,
|
|
150
|
-
) -> ABIFunction:
|
|
151
|
-
args = args or tuple()
|
|
152
|
-
kwargs = kwargs or dict()
|
|
153
|
-
num_arguments = len(args) + len(kwargs)
|
|
154
|
-
|
|
155
|
-
if fn_identifier is FallbackFn:
|
|
156
|
-
return get_fallback_func_abi(abi)
|
|
157
|
-
|
|
158
|
-
if fn_identifier is ReceiveFn:
|
|
159
|
-
return get_receive_func_abi(abi)
|
|
160
|
-
|
|
161
|
-
if not is_text(fn_identifier):
|
|
162
|
-
raise TypeError("Unsupported function identifier")
|
|
163
|
-
|
|
164
|
-
name_filter = functools.partial(filter_by_name, fn_identifier)
|
|
165
|
-
arg_count_filter = functools.partial(filter_by_argument_count, num_arguments)
|
|
166
|
-
encoding_filter = functools.partial(filter_by_encodability, abi_codec, args, kwargs)
|
|
167
|
-
|
|
168
|
-
function_candidates = pipe(abi, name_filter, arg_count_filter, encoding_filter)
|
|
169
|
-
|
|
170
|
-
if len(function_candidates) == 1:
|
|
171
|
-
return function_candidates[0]
|
|
172
|
-
else:
|
|
173
|
-
matching_identifiers = name_filter(abi)
|
|
174
|
-
matching_function_signatures = [
|
|
175
|
-
abi_to_signature(func) for func in matching_identifiers
|
|
176
|
-
]
|
|
177
|
-
|
|
178
|
-
arg_count_matches = len(arg_count_filter(matching_identifiers))
|
|
179
|
-
encoding_matches = len(encoding_filter(matching_identifiers))
|
|
180
|
-
|
|
181
|
-
if arg_count_matches == 0:
|
|
182
|
-
diagnosis = (
|
|
183
|
-
"\nFunction invocation failed due to improper number of arguments."
|
|
184
|
-
)
|
|
185
|
-
elif encoding_matches == 0:
|
|
186
|
-
diagnosis = (
|
|
187
|
-
"\nFunction invocation failed due to no matching argument types."
|
|
188
|
-
)
|
|
189
|
-
elif encoding_matches > 1:
|
|
190
|
-
diagnosis = (
|
|
191
|
-
"\nAmbiguous argument encoding. "
|
|
192
|
-
"Provided arguments can be encoded to multiple functions "
|
|
193
|
-
"matching this call."
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
collapsed_args = extract_argument_types(args)
|
|
197
|
-
collapsed_kwargs = dict(
|
|
198
|
-
{(k, extract_argument_types([v])) for k, v in kwargs.items()}
|
|
199
|
-
)
|
|
200
|
-
message = (
|
|
201
|
-
f"\nCould not identify the intended function with name `{fn_identifier}`, "
|
|
202
|
-
f"positional arguments with type(s) `{collapsed_args}` and "
|
|
203
|
-
f"keyword arguments with type(s) `{collapsed_kwargs}`."
|
|
204
|
-
f"\nFound {len(matching_identifiers)} function(s) with "
|
|
205
|
-
f"the name `{fn_identifier}`: {matching_function_signatures}{diagnosis}"
|
|
206
|
-
)
|
|
207
|
-
|
|
208
|
-
raise Web3ValidationError(message)
|
|
120
|
+
raise Web3ValueError("Multiple events found")
|
|
209
121
|
|
|
210
122
|
|
|
211
123
|
def encode_abi(
|
|
212
124
|
w3: Union["AsyncWeb3", "Web3"],
|
|
213
|
-
abi:
|
|
125
|
+
abi: ABIElement,
|
|
214
126
|
arguments: Sequence[Any],
|
|
215
127
|
data: Optional[HexStr] = None,
|
|
216
128
|
) -> HexStr:
|
|
217
|
-
argument_types =
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
129
|
+
argument_types = []
|
|
130
|
+
try:
|
|
131
|
+
argument_types = get_abi_input_types(abi)
|
|
132
|
+
except ValueError:
|
|
133
|
+
# Use the default argument_types if the abi doesn't have inputs
|
|
134
|
+
pass
|
|
135
|
+
|
|
136
|
+
if not check_if_arguments_can_be_encoded(
|
|
137
|
+
abi,
|
|
138
|
+
*arguments,
|
|
139
|
+
abi_codec=w3.codec,
|
|
140
|
+
):
|
|
141
|
+
raise Web3TypeError(
|
|
221
142
|
"One or more arguments could not be encoded to the necessary "
|
|
222
143
|
f"ABI type. Expected types are: {', '.join(argument_types)}"
|
|
223
144
|
)
|
|
@@ -248,25 +169,45 @@ def encode_abi(
|
|
|
248
169
|
def prepare_transaction(
|
|
249
170
|
address: ChecksumAddress,
|
|
250
171
|
w3: Union["AsyncWeb3", "Web3"],
|
|
251
|
-
|
|
172
|
+
abi_element_identifier: ABIElementIdentifier,
|
|
252
173
|
contract_abi: Optional[ABI] = None,
|
|
253
|
-
|
|
174
|
+
abi_callable: Optional[ABICallable] = None,
|
|
254
175
|
transaction: Optional[TxParams] = None,
|
|
255
176
|
fn_args: Optional[Sequence[Any]] = None,
|
|
256
177
|
fn_kwargs: Optional[Any] = None,
|
|
257
178
|
) -> TxParams:
|
|
258
179
|
"""
|
|
259
|
-
:parameter `is_function_abi` is used to distinguish function abi from contract abi
|
|
260
180
|
Returns a dictionary of the transaction that could be used to call this
|
|
261
181
|
TODO: make this a public API
|
|
262
182
|
TODO: add new prepare_deploy_transaction API
|
|
263
183
|
"""
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
184
|
+
fn_args = fn_args or []
|
|
185
|
+
fn_kwargs = fn_kwargs or {}
|
|
186
|
+
|
|
187
|
+
if not fn_args and not fn_kwargs and "(" not in str(abi_element_identifier):
|
|
188
|
+
abi_element_identifier = get_abi_element_signature(abi_element_identifier)
|
|
189
|
+
|
|
190
|
+
if abi_element_identifier in [
|
|
191
|
+
"fallback()",
|
|
192
|
+
"receive()",
|
|
193
|
+
]:
|
|
194
|
+
abi_element_identifier = get_name_from_abi_element_identifier(
|
|
195
|
+
abi_element_identifier
|
|
267
196
|
)
|
|
268
197
|
|
|
269
|
-
|
|
198
|
+
if abi_callable is None:
|
|
199
|
+
abi_callable = cast(
|
|
200
|
+
ABICallable,
|
|
201
|
+
get_abi_element(
|
|
202
|
+
contract_abi,
|
|
203
|
+
abi_element_identifier,
|
|
204
|
+
*fn_args,
|
|
205
|
+
abi_codec=w3.codec,
|
|
206
|
+
**fn_kwargs,
|
|
207
|
+
),
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
validate_payable(transaction, abi_callable)
|
|
270
211
|
|
|
271
212
|
if transaction is None:
|
|
272
213
|
prepared_transaction: TxParams = {}
|
|
@@ -274,16 +215,16 @@ def prepare_transaction(
|
|
|
274
215
|
prepared_transaction = cast(TxParams, dict(**transaction))
|
|
275
216
|
|
|
276
217
|
if "data" in prepared_transaction:
|
|
277
|
-
raise
|
|
218
|
+
raise Web3ValueError("Transaction parameter may not contain a 'data' key")
|
|
278
219
|
|
|
279
220
|
if address:
|
|
280
221
|
prepared_transaction.setdefault("to", address)
|
|
281
222
|
|
|
282
223
|
prepared_transaction["data"] = encode_transaction_data(
|
|
283
224
|
w3,
|
|
284
|
-
|
|
225
|
+
abi_element_identifier,
|
|
285
226
|
contract_abi,
|
|
286
|
-
|
|
227
|
+
abi_callable,
|
|
287
228
|
fn_args,
|
|
288
229
|
fn_kwargs,
|
|
289
230
|
)
|
|
@@ -292,34 +233,37 @@ def prepare_transaction(
|
|
|
292
233
|
|
|
293
234
|
def encode_transaction_data(
|
|
294
235
|
w3: Union["AsyncWeb3", "Web3"],
|
|
295
|
-
|
|
236
|
+
abi_element_identifier: ABIElementIdentifier,
|
|
296
237
|
contract_abi: Optional[ABI] = None,
|
|
297
|
-
|
|
238
|
+
abi_callable: Optional[ABICallable] = None,
|
|
298
239
|
args: Optional[Sequence[Any]] = None,
|
|
299
240
|
kwargs: Optional[Any] = None,
|
|
300
241
|
) -> HexStr:
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
242
|
+
info_abi: ABIElement
|
|
243
|
+
abi_element_name = get_name_from_abi_element_identifier(abi_element_identifier)
|
|
244
|
+
if abi_element_name == "fallback":
|
|
245
|
+
info_abi, info_selector, info_arguments = get_fallback_function_info(
|
|
246
|
+
contract_abi, cast(ABIFallback, abi_callable)
|
|
304
247
|
)
|
|
305
|
-
elif
|
|
306
|
-
|
|
307
|
-
contract_abi,
|
|
248
|
+
elif abi_element_name == "receive":
|
|
249
|
+
info_abi, info_selector, info_arguments = get_receive_function_info(
|
|
250
|
+
contract_abi, cast(ABIReceive, abi_callable)
|
|
308
251
|
)
|
|
309
|
-
elif
|
|
310
|
-
|
|
311
|
-
# type ignored b/c fn_id here is always str b/c FallbackFn is handled above
|
|
312
|
-
fn_identifier, # type: ignore
|
|
313
|
-
w3.codec,
|
|
252
|
+
elif isinstance(abi_element_identifier, str):
|
|
253
|
+
fn_info = get_abi_element_info(
|
|
314
254
|
contract_abi,
|
|
315
|
-
|
|
316
|
-
args,
|
|
317
|
-
|
|
255
|
+
abi_element_identifier,
|
|
256
|
+
*args,
|
|
257
|
+
abi_codec=w3.codec,
|
|
258
|
+
**kwargs,
|
|
318
259
|
)
|
|
260
|
+
info_abi = fn_info["abi"]
|
|
261
|
+
info_selector = fn_info["selector"]
|
|
262
|
+
info_arguments = fn_info["arguments"]
|
|
319
263
|
else:
|
|
320
|
-
raise
|
|
264
|
+
raise Web3TypeError("Unsupported function identifier")
|
|
321
265
|
|
|
322
|
-
return add_0x_prefix(encode_abi(w3,
|
|
266
|
+
return add_0x_prefix(encode_abi(w3, info_abi, info_arguments, info_selector))
|
|
323
267
|
|
|
324
268
|
|
|
325
269
|
def decode_transaction_data(
|
|
@@ -327,91 +271,71 @@ def decode_transaction_data(
|
|
|
327
271
|
data: HexStr,
|
|
328
272
|
normalizers: Sequence[Callable[[TypeStr, Any], Tuple[TypeStr, Any]]] = None,
|
|
329
273
|
) -> Dict[str, Any]:
|
|
330
|
-
|
|
331
|
-
data = HexBytes(data) # type: ignore
|
|
274
|
+
data_bytes = HexBytes(data)
|
|
332
275
|
types = get_abi_input_types(fn_abi)
|
|
333
276
|
abi_codec = ABICodec(default_registry)
|
|
334
|
-
decoded = abi_codec.decode(types,
|
|
277
|
+
decoded = abi_codec.decode(types, data_bytes[4:])
|
|
335
278
|
if normalizers:
|
|
336
279
|
decoded = map_abi_data(normalizers, types, decoded)
|
|
337
280
|
return named_tree(fn_abi["inputs"], decoded)
|
|
338
281
|
|
|
339
282
|
|
|
340
|
-
def
|
|
341
|
-
contract_abi: Optional[ABI] = None,
|
|
342
|
-
) -> Tuple[
|
|
343
|
-
if
|
|
344
|
-
|
|
283
|
+
def get_constructor_function_info(
|
|
284
|
+
contract_abi: Optional[ABI] = None, constructor_abi: Optional[ABIConstructor] = None
|
|
285
|
+
) -> Tuple[ABIConstructor, HexStr, Tuple[Any, ...]]:
|
|
286
|
+
if constructor_abi is None:
|
|
287
|
+
constructor_abi = cast(
|
|
288
|
+
ABIConstructor, get_abi_element(contract_abi, "constructor")
|
|
289
|
+
)
|
|
345
290
|
fn_selector = encode_hex(b"")
|
|
346
291
|
fn_arguments: Tuple[Any, ...] = tuple()
|
|
347
|
-
return
|
|
292
|
+
return constructor_abi, fn_selector, fn_arguments
|
|
348
293
|
|
|
349
294
|
|
|
350
|
-
def
|
|
351
|
-
contract_abi: Optional[ABI] = None,
|
|
352
|
-
) -> Tuple[
|
|
353
|
-
if
|
|
354
|
-
|
|
295
|
+
def get_fallback_function_info(
|
|
296
|
+
contract_abi: Optional[ABI] = None, fallback_abi: Optional[ABIFallback] = None
|
|
297
|
+
) -> Tuple[ABIFallback, HexStr, Tuple[Any, ...]]:
|
|
298
|
+
if fallback_abi is None:
|
|
299
|
+
fallback_abi = cast(ABIFallback, get_abi_element(contract_abi, "fallback"))
|
|
355
300
|
fn_selector = encode_hex(b"")
|
|
356
301
|
fn_arguments: Tuple[Any, ...] = tuple()
|
|
357
|
-
return
|
|
302
|
+
return fallback_abi, fn_selector, fn_arguments
|
|
358
303
|
|
|
359
304
|
|
|
360
|
-
def
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
if args is None:
|
|
369
|
-
args = tuple()
|
|
370
|
-
if kwargs is None:
|
|
371
|
-
kwargs = {}
|
|
372
|
-
|
|
373
|
-
if fn_abi is None:
|
|
374
|
-
fn_abi = find_matching_fn_abi(contract_abi, abi_codec, fn_name, args, kwargs)
|
|
375
|
-
|
|
376
|
-
# typed dict cannot be used w/ a normal Dict
|
|
377
|
-
# https://github.com/python/mypy/issues/4976
|
|
378
|
-
fn_selector = encode_hex(function_abi_to_4byte_selector(fn_abi)) # type: ignore
|
|
379
|
-
|
|
380
|
-
fn_arguments = merge_args_and_kwargs(fn_abi, args, kwargs)
|
|
381
|
-
|
|
382
|
-
_, aligned_fn_arguments = get_aligned_abi_inputs(fn_abi, fn_arguments)
|
|
383
|
-
|
|
384
|
-
return fn_abi, fn_selector, aligned_fn_arguments
|
|
305
|
+
def get_receive_function_info(
|
|
306
|
+
contract_abi: Optional[ABI] = None, receive_abi: Optional[ABIReceive] = None
|
|
307
|
+
) -> Tuple[ABIReceive, HexStr, Tuple[Any, ...]]:
|
|
308
|
+
if receive_abi is None:
|
|
309
|
+
receive_abi = cast(ABIReceive, get_abi_element(contract_abi, "receive"))
|
|
310
|
+
fn_selector = encode_hex(b"")
|
|
311
|
+
fn_arguments: Tuple[Any, ...] = tuple()
|
|
312
|
+
return receive_abi, fn_selector, fn_arguments
|
|
385
313
|
|
|
386
314
|
|
|
387
|
-
def validate_payable(transaction: TxParams,
|
|
388
|
-
"""
|
|
315
|
+
def validate_payable(transaction: TxParams, abi_callable: ABICallable) -> None:
|
|
316
|
+
"""
|
|
317
|
+
Raise Web3ValidationError if non-zero ether
|
|
389
318
|
is sent to a non-payable function.
|
|
390
319
|
"""
|
|
391
|
-
if
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
def _get_argument_readable_type(arg: Any) -> str:
|
|
407
|
-
if is_checksum_address(arg) or is_binary_address(arg):
|
|
408
|
-
return "address"
|
|
409
|
-
|
|
410
|
-
return arg.__class__.__name__
|
|
320
|
+
if (
|
|
321
|
+
"value" in transaction
|
|
322
|
+
and to_integer_if_hex(transaction["value"]) != 0
|
|
323
|
+
and (
|
|
324
|
+
"payable" in abi_callable
|
|
325
|
+
and not abi_callable["payable"]
|
|
326
|
+
or "stateMutability" in abi_callable
|
|
327
|
+
and abi_callable["stateMutability"] == "nonpayable"
|
|
328
|
+
)
|
|
329
|
+
):
|
|
330
|
+
raise Web3ValidationError(
|
|
331
|
+
"Sending non-zero ether to a contract function "
|
|
332
|
+
"with payable=False. Please ensure that "
|
|
333
|
+
"transaction's value is 0."
|
|
334
|
+
)
|
|
411
335
|
|
|
412
336
|
|
|
413
337
|
def parse_block_identifier(
|
|
414
|
-
w3: "Web3", block_identifier: BlockIdentifier
|
|
338
|
+
w3: "Web3", block_identifier: Optional[BlockIdentifier]
|
|
415
339
|
) -> BlockIdentifier:
|
|
416
340
|
if block_identifier is None:
|
|
417
341
|
return w3.eth.default_block
|
|
@@ -424,7 +348,7 @@ def parse_block_identifier(
|
|
|
424
348
|
):
|
|
425
349
|
return w3.eth.get_block(block_identifier)["number"]
|
|
426
350
|
else:
|
|
427
|
-
raise
|
|
351
|
+
raise BlockNumberOutOfRange
|
|
428
352
|
|
|
429
353
|
|
|
430
354
|
def parse_block_identifier_int(w3: "Web3", block_identifier_int: int) -> BlockNumber:
|
|
@@ -434,7 +358,7 @@ def parse_block_identifier_int(w3: "Web3", block_identifier_int: int) -> BlockNu
|
|
|
434
358
|
last_block = w3.eth.get_block("latest")["number"]
|
|
435
359
|
block_num = last_block + block_identifier_int + 1
|
|
436
360
|
if block_num < 0:
|
|
437
|
-
raise
|
|
361
|
+
raise BlockNumberOutOfRange
|
|
438
362
|
return BlockNumber(block_num)
|
|
439
363
|
|
|
440
364
|
|
|
@@ -453,7 +377,7 @@ async def async_parse_block_identifier(
|
|
|
453
377
|
requested_block = await async_w3.eth.get_block(block_identifier)
|
|
454
378
|
return requested_block["number"]
|
|
455
379
|
else:
|
|
456
|
-
raise
|
|
380
|
+
raise BlockNumberOutOfRange
|
|
457
381
|
|
|
458
382
|
|
|
459
383
|
async def async_parse_block_identifier_int(
|
|
@@ -466,5 +390,33 @@ async def async_parse_block_identifier_int(
|
|
|
466
390
|
last_block_num = last_block["number"]
|
|
467
391
|
block_num = last_block_num + block_identifier_int + 1
|
|
468
392
|
if block_num < 0:
|
|
469
|
-
raise
|
|
393
|
+
raise BlockNumberOutOfRange
|
|
470
394
|
return BlockNumber(block_num)
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def copy_contract_function(
|
|
398
|
+
contract_function: TContractFn, *args: Any, **kwargs: Any
|
|
399
|
+
) -> TContractFn:
|
|
400
|
+
"""
|
|
401
|
+
Copy a contract function instance.
|
|
402
|
+
"""
|
|
403
|
+
clone = copy.copy(contract_function)
|
|
404
|
+
clone.args = args or tuple()
|
|
405
|
+
clone.kwargs = kwargs or dict()
|
|
406
|
+
|
|
407
|
+
clone._set_function_info()
|
|
408
|
+
return clone
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
def copy_contract_event(
|
|
412
|
+
contract_event: TContractEvent, *args: Any, **kwargs: Any
|
|
413
|
+
) -> TContractEvent:
|
|
414
|
+
"""
|
|
415
|
+
Copy a contract function instance.
|
|
416
|
+
"""
|
|
417
|
+
clone = copy.copy(contract_event)
|
|
418
|
+
clone.args = args or tuple()
|
|
419
|
+
clone.kwargs = kwargs or dict()
|
|
420
|
+
|
|
421
|
+
clone._set_event_info()
|
|
422
|
+
return clone
|
web3/_utils/datatypes.py
CHANGED
|
@@ -14,10 +14,14 @@ from eth_utils.toolz import (
|
|
|
14
14
|
concat,
|
|
15
15
|
)
|
|
16
16
|
|
|
17
|
+
from web3.exceptions import (
|
|
18
|
+
Web3AttributeError,
|
|
19
|
+
)
|
|
20
|
+
|
|
17
21
|
|
|
18
22
|
def verify_attr(class_name: str, key: str, namespace: Collection[str]) -> None:
|
|
19
23
|
if key not in namespace:
|
|
20
|
-
raise
|
|
24
|
+
raise Web3AttributeError(
|
|
21
25
|
f"Property {key} not found on {class_name} class. "
|
|
22
26
|
f"`{class_name}.factory` only accepts keyword arguments which are "
|
|
23
27
|
f"present on the {class_name} class"
|
web3/_utils/decorators.py
CHANGED
|
@@ -8,6 +8,10 @@ from typing import (
|
|
|
8
8
|
)
|
|
9
9
|
import warnings
|
|
10
10
|
|
|
11
|
+
from web3.exceptions import (
|
|
12
|
+
Web3ValueError,
|
|
13
|
+
)
|
|
14
|
+
|
|
11
15
|
TFunc = TypeVar("TFunc", bound=Callable[..., Any])
|
|
12
16
|
|
|
13
17
|
|
|
@@ -24,7 +28,7 @@ def reject_recursive_repeats(to_wrap: Callable[..., Any]) -> Callable[..., Any]:
|
|
|
24
28
|
thread_id = threading.get_ident()
|
|
25
29
|
thread_local_args = (thread_id,) + arg_instances
|
|
26
30
|
if thread_local_args in to_wrap.__already_called: # type: ignore
|
|
27
|
-
raise
|
|
31
|
+
raise Web3ValueError(f"Recursively called {to_wrap} with {args!r}")
|
|
28
32
|
to_wrap.__already_called[thread_local_args] = True # type: ignore
|
|
29
33
|
try:
|
|
30
34
|
wrapped_val = to_wrap(*args)
|
|
@@ -50,6 +54,7 @@ def deprecated_for(replace_message: str) -> Callable[..., Any]:
|
|
|
50
54
|
warnings.warn(
|
|
51
55
|
f"{to_wrap.__name__} is deprecated in favor of {replace_message}",
|
|
52
56
|
category=DeprecationWarning,
|
|
57
|
+
stacklevel=2,
|
|
53
58
|
)
|
|
54
59
|
return to_wrap(*args, **kwargs)
|
|
55
60
|
|
web3/_utils/empty.py
CHANGED