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/contract/utils.py
CHANGED
|
@@ -9,21 +9,33 @@ from typing import (
|
|
|
9
9
|
Tuple,
|
|
10
10
|
Type,
|
|
11
11
|
Union,
|
|
12
|
+
cast,
|
|
12
13
|
)
|
|
13
14
|
|
|
14
15
|
from eth_abi.exceptions import (
|
|
15
16
|
DecodingError,
|
|
16
17
|
)
|
|
17
18
|
from eth_typing import (
|
|
19
|
+
ABI,
|
|
20
|
+
ABICallable,
|
|
21
|
+
ABIFunction,
|
|
18
22
|
ChecksumAddress,
|
|
23
|
+
TypeStr,
|
|
24
|
+
)
|
|
25
|
+
from eth_utils.abi import (
|
|
26
|
+
abi_to_signature,
|
|
27
|
+
filter_abi_by_type,
|
|
28
|
+
get_abi_output_types,
|
|
29
|
+
)
|
|
30
|
+
from eth_utils.toolz import (
|
|
31
|
+
compose,
|
|
32
|
+
curry,
|
|
19
33
|
)
|
|
20
34
|
from hexbytes import (
|
|
21
35
|
HexBytes,
|
|
22
36
|
)
|
|
23
37
|
|
|
24
38
|
from web3._utils.abi import (
|
|
25
|
-
filter_by_type,
|
|
26
|
-
get_abi_output_types,
|
|
27
39
|
map_abi_data,
|
|
28
40
|
named_tree,
|
|
29
41
|
recursive_dict_to_namedtuple,
|
|
@@ -31,8 +43,10 @@ from web3._utils.abi import (
|
|
|
31
43
|
from web3._utils.async_transactions import (
|
|
32
44
|
async_fill_transaction_defaults,
|
|
33
45
|
)
|
|
46
|
+
from web3._utils.compat import (
|
|
47
|
+
TypeAlias,
|
|
48
|
+
)
|
|
34
49
|
from web3._utils.contracts import (
|
|
35
|
-
find_matching_fn_abi,
|
|
36
50
|
prepare_transaction,
|
|
37
51
|
)
|
|
38
52
|
from web3._utils.normalizers import (
|
|
@@ -43,35 +57,79 @@ from web3._utils.transactions import (
|
|
|
43
57
|
)
|
|
44
58
|
from web3.exceptions import (
|
|
45
59
|
BadFunctionCallOutput,
|
|
60
|
+
Web3ValueError,
|
|
46
61
|
)
|
|
47
62
|
from web3.types import (
|
|
48
|
-
|
|
49
|
-
ABIFunction,
|
|
63
|
+
ABIElementIdentifier,
|
|
50
64
|
BlockIdentifier,
|
|
51
|
-
|
|
65
|
+
RPCEndpoint,
|
|
52
66
|
StateOverride,
|
|
67
|
+
TContractEvent,
|
|
53
68
|
TContractFn,
|
|
54
69
|
TxParams,
|
|
55
70
|
)
|
|
71
|
+
from web3.utils.abi import (
|
|
72
|
+
get_abi_element,
|
|
73
|
+
)
|
|
56
74
|
|
|
57
75
|
if TYPE_CHECKING:
|
|
58
76
|
from web3 import ( # noqa: F401
|
|
59
77
|
AsyncWeb3,
|
|
60
78
|
Web3,
|
|
61
79
|
)
|
|
80
|
+
from web3.providers.persistent import ( # noqa: F401
|
|
81
|
+
PersistentConnectionProvider,
|
|
82
|
+
)
|
|
62
83
|
|
|
63
84
|
ACCEPTABLE_EMPTY_STRINGS = ["0x", b"0x", "", b""]
|
|
64
85
|
|
|
65
86
|
|
|
87
|
+
@curry
|
|
88
|
+
def format_contract_call_return_data_curried(
|
|
89
|
+
async_w3: Union["AsyncWeb3", "Web3"],
|
|
90
|
+
decode_tuples: bool,
|
|
91
|
+
fn_abi: ABICallable,
|
|
92
|
+
abi_element_identifier: ABIElementIdentifier,
|
|
93
|
+
normalizers: Tuple[Callable[..., Any], ...],
|
|
94
|
+
output_types: Sequence[TypeStr],
|
|
95
|
+
return_data: Any,
|
|
96
|
+
) -> Any:
|
|
97
|
+
"""
|
|
98
|
+
Helper function for formatting contract call return data for batch requests. Curry
|
|
99
|
+
with all arguments except `return_data` and process `return_data` once it is
|
|
100
|
+
available.
|
|
101
|
+
"""
|
|
102
|
+
try:
|
|
103
|
+
output_data = async_w3.codec.decode(output_types, return_data)
|
|
104
|
+
except DecodingError as e:
|
|
105
|
+
msg = (
|
|
106
|
+
f"Could not decode contract function call to {abi_element_identifier} "
|
|
107
|
+
f"with return data: {str(return_data)}, output_types: {output_types}"
|
|
108
|
+
)
|
|
109
|
+
raise BadFunctionCallOutput(msg) from e
|
|
110
|
+
|
|
111
|
+
_normalizers = itertools.chain(
|
|
112
|
+
BASE_RETURN_NORMALIZERS,
|
|
113
|
+
normalizers,
|
|
114
|
+
)
|
|
115
|
+
normalized_data = map_abi_data(_normalizers, output_types, output_data)
|
|
116
|
+
|
|
117
|
+
if decode_tuples and fn_abi["type"] == "function":
|
|
118
|
+
decoded = named_tree(fn_abi["outputs"], normalized_data)
|
|
119
|
+
normalized_data = recursive_dict_to_namedtuple(decoded)
|
|
120
|
+
|
|
121
|
+
return normalized_data[0] if len(normalized_data) == 1 else normalized_data
|
|
122
|
+
|
|
123
|
+
|
|
66
124
|
def call_contract_function(
|
|
67
125
|
w3: "Web3",
|
|
68
126
|
address: ChecksumAddress,
|
|
69
127
|
normalizers: Tuple[Callable[..., Any], ...],
|
|
70
|
-
|
|
128
|
+
abi_element_identifier: ABIElementIdentifier,
|
|
71
129
|
transaction: TxParams,
|
|
72
130
|
block_id: Optional[BlockIdentifier] = None,
|
|
73
131
|
contract_abi: Optional[ABI] = None,
|
|
74
|
-
|
|
132
|
+
abi_callable: Optional[ABICallable] = None,
|
|
75
133
|
state_override: Optional[StateOverride] = None,
|
|
76
134
|
ccip_read_enabled: Optional[bool] = None,
|
|
77
135
|
decode_tuples: Optional[bool] = False,
|
|
@@ -85,9 +143,9 @@ def call_contract_function(
|
|
|
85
143
|
call_transaction = prepare_transaction(
|
|
86
144
|
address,
|
|
87
145
|
w3,
|
|
88
|
-
|
|
146
|
+
abi_element_identifier=abi_element_identifier,
|
|
89
147
|
contract_abi=contract_abi,
|
|
90
|
-
|
|
148
|
+
abi_callable=abi_callable,
|
|
91
149
|
transaction=transaction,
|
|
92
150
|
fn_args=args,
|
|
93
151
|
fn_kwargs=kwargs,
|
|
@@ -100,12 +158,50 @@ def call_contract_function(
|
|
|
100
158
|
ccip_read_enabled=ccip_read_enabled,
|
|
101
159
|
)
|
|
102
160
|
|
|
103
|
-
if
|
|
104
|
-
|
|
105
|
-
|
|
161
|
+
if abi_callable is None:
|
|
162
|
+
abi_callable = cast(
|
|
163
|
+
ABIFunction,
|
|
164
|
+
get_abi_element(
|
|
165
|
+
contract_abi,
|
|
166
|
+
abi_element_identifier,
|
|
167
|
+
*args,
|
|
168
|
+
abi_codec=w3.codec,
|
|
169
|
+
**kwargs,
|
|
170
|
+
),
|
|
106
171
|
)
|
|
107
172
|
|
|
108
|
-
|
|
173
|
+
# get the output types, which only exist for function types
|
|
174
|
+
output_types = []
|
|
175
|
+
if abi_callable["type"] == "function":
|
|
176
|
+
output_types = get_abi_output_types(abi_callable)
|
|
177
|
+
|
|
178
|
+
provider = w3.provider
|
|
179
|
+
if hasattr(provider, "_is_batching") and provider._is_batching:
|
|
180
|
+
BatchingReturnData: TypeAlias = Tuple[Tuple[RPCEndpoint, Any], Tuple[Any, ...]]
|
|
181
|
+
request_information = tuple(cast(BatchingReturnData, return_data))
|
|
182
|
+
method_and_params = request_information[0]
|
|
183
|
+
|
|
184
|
+
# append return data formatting to result formatters
|
|
185
|
+
current_response_formatters = request_information[1]
|
|
186
|
+
current_result_formatters = current_response_formatters[0]
|
|
187
|
+
updated_result_formatters = compose(
|
|
188
|
+
# contract call return data formatter
|
|
189
|
+
format_contract_call_return_data_curried(
|
|
190
|
+
w3,
|
|
191
|
+
decode_tuples,
|
|
192
|
+
abi_callable,
|
|
193
|
+
abi_element_identifier,
|
|
194
|
+
normalizers,
|
|
195
|
+
output_types,
|
|
196
|
+
),
|
|
197
|
+
current_result_formatters,
|
|
198
|
+
)
|
|
199
|
+
response_formatters = (
|
|
200
|
+
updated_result_formatters, # result formatters
|
|
201
|
+
current_response_formatters[1], # error formatters
|
|
202
|
+
current_response_formatters[2], # null result formatters
|
|
203
|
+
)
|
|
204
|
+
return (method_and_params, response_formatters)
|
|
109
205
|
|
|
110
206
|
try:
|
|
111
207
|
output_data = w3.codec.decode(output_types, return_data)
|
|
@@ -123,7 +219,7 @@ def call_contract_function(
|
|
|
123
219
|
)
|
|
124
220
|
else:
|
|
125
221
|
msg = (
|
|
126
|
-
f"Could not decode contract function call to {
|
|
222
|
+
f"Could not decode contract function call to {abi_element_identifier} "
|
|
127
223
|
f"with return data: {str(return_data)}, output_types: {output_types}"
|
|
128
224
|
)
|
|
129
225
|
raise BadFunctionCallOutput(msg) from e
|
|
@@ -134,8 +230,8 @@ def call_contract_function(
|
|
|
134
230
|
)
|
|
135
231
|
normalized_data = map_abi_data(_normalizers, output_types, output_data)
|
|
136
232
|
|
|
137
|
-
if decode_tuples:
|
|
138
|
-
decoded = named_tree(
|
|
233
|
+
if decode_tuples and abi_callable["type"] == "function":
|
|
234
|
+
decoded = named_tree(abi_callable["outputs"], normalized_data)
|
|
139
235
|
normalized_data = recursive_dict_to_namedtuple(decoded)
|
|
140
236
|
|
|
141
237
|
if len(normalized_data) == 1:
|
|
@@ -147,7 +243,7 @@ def call_contract_function(
|
|
|
147
243
|
def transact_with_contract_function(
|
|
148
244
|
address: ChecksumAddress,
|
|
149
245
|
w3: "Web3",
|
|
150
|
-
|
|
246
|
+
abi_element_identifier: Optional[ABIElementIdentifier] = None,
|
|
151
247
|
transaction: Optional[TxParams] = None,
|
|
152
248
|
contract_abi: Optional[ABI] = None,
|
|
153
249
|
fn_abi: Optional[ABIFunction] = None,
|
|
@@ -161,10 +257,10 @@ def transact_with_contract_function(
|
|
|
161
257
|
transact_transaction = prepare_transaction(
|
|
162
258
|
address,
|
|
163
259
|
w3,
|
|
164
|
-
|
|
260
|
+
abi_element_identifier=abi_element_identifier,
|
|
165
261
|
contract_abi=contract_abi,
|
|
166
262
|
transaction=transaction,
|
|
167
|
-
|
|
263
|
+
abi_callable=fn_abi,
|
|
168
264
|
fn_args=args,
|
|
169
265
|
fn_kwargs=kwargs,
|
|
170
266
|
)
|
|
@@ -176,7 +272,7 @@ def transact_with_contract_function(
|
|
|
176
272
|
def estimate_gas_for_function(
|
|
177
273
|
address: ChecksumAddress,
|
|
178
274
|
w3: "Web3",
|
|
179
|
-
|
|
275
|
+
abi_element_identifier: Optional[ABIElementIdentifier] = None,
|
|
180
276
|
transaction: Optional[TxParams] = None,
|
|
181
277
|
contract_abi: Optional[ABI] = None,
|
|
182
278
|
fn_abi: Optional[ABIFunction] = None,
|
|
@@ -185,7 +281,8 @@ def estimate_gas_for_function(
|
|
|
185
281
|
*args: Any,
|
|
186
282
|
**kwargs: Any,
|
|
187
283
|
) -> int:
|
|
188
|
-
"""
|
|
284
|
+
"""
|
|
285
|
+
Estimates gas cost a function call would take.
|
|
189
286
|
|
|
190
287
|
Don't call this directly, instead use :meth:`Contract.estimate_gas`
|
|
191
288
|
on your contract instance.
|
|
@@ -193,9 +290,9 @@ def estimate_gas_for_function(
|
|
|
193
290
|
estimate_transaction = prepare_transaction(
|
|
194
291
|
address,
|
|
195
292
|
w3,
|
|
196
|
-
|
|
293
|
+
abi_element_identifier=abi_element_identifier,
|
|
197
294
|
contract_abi=contract_abi,
|
|
198
|
-
|
|
295
|
+
abi_callable=fn_abi,
|
|
199
296
|
transaction=transaction,
|
|
200
297
|
fn_args=args,
|
|
201
298
|
fn_kwargs=kwargs,
|
|
@@ -207,14 +304,15 @@ def estimate_gas_for_function(
|
|
|
207
304
|
def build_transaction_for_function(
|
|
208
305
|
address: ChecksumAddress,
|
|
209
306
|
w3: "Web3",
|
|
210
|
-
|
|
307
|
+
abi_element_identifier: Optional[ABIElementIdentifier] = None,
|
|
211
308
|
transaction: Optional[TxParams] = None,
|
|
212
309
|
contract_abi: Optional[ABI] = None,
|
|
213
310
|
fn_abi: Optional[ABIFunction] = None,
|
|
214
311
|
*args: Any,
|
|
215
312
|
**kwargs: Any,
|
|
216
313
|
) -> TxParams:
|
|
217
|
-
"""
|
|
314
|
+
"""
|
|
315
|
+
Builds a dictionary with the fields required to make the given transaction
|
|
218
316
|
|
|
219
317
|
Don't call this directly, instead use :meth:`Contract.build_transaction`
|
|
220
318
|
on your contract instance.
|
|
@@ -222,9 +320,9 @@ def build_transaction_for_function(
|
|
|
222
320
|
prepared_transaction = prepare_transaction(
|
|
223
321
|
address,
|
|
224
322
|
w3,
|
|
225
|
-
|
|
323
|
+
abi_element_identifier=abi_element_identifier,
|
|
226
324
|
contract_abi=contract_abi,
|
|
227
|
-
|
|
325
|
+
abi_callable=fn_abi,
|
|
228
326
|
transaction=transaction,
|
|
229
327
|
fn_args=args,
|
|
230
328
|
fn_kwargs=kwargs,
|
|
@@ -242,14 +340,20 @@ def find_functions_by_identifier(
|
|
|
242
340
|
callable_check: Callable[..., Any],
|
|
243
341
|
function_type: Type[TContractFn],
|
|
244
342
|
) -> List[TContractFn]:
|
|
245
|
-
|
|
343
|
+
"""
|
|
344
|
+
Given a contract ABI, return a list of TContractFunction instances.
|
|
345
|
+
"""
|
|
346
|
+
fns_abi = sorted(
|
|
347
|
+
filter_abi_by_type("function", contract_abi),
|
|
348
|
+
key=lambda fn: (fn["name"], len(fn.get("inputs", []))),
|
|
349
|
+
)
|
|
246
350
|
return [
|
|
247
351
|
function_type.factory(
|
|
248
|
-
fn_abi
|
|
352
|
+
abi_to_signature(fn_abi),
|
|
249
353
|
w3=w3,
|
|
250
354
|
contract_abi=contract_abi,
|
|
251
355
|
address=address,
|
|
252
|
-
|
|
356
|
+
abi_element_identifier=abi_to_signature(fn_abi),
|
|
253
357
|
abi=fn_abi,
|
|
254
358
|
)
|
|
255
359
|
for fn_abi in fns_abi
|
|
@@ -260,15 +364,59 @@ def find_functions_by_identifier(
|
|
|
260
364
|
def get_function_by_identifier(
|
|
261
365
|
fns: Sequence[TContractFn], identifier: str
|
|
262
366
|
) -> TContractFn:
|
|
367
|
+
"""
|
|
368
|
+
Check that the provided list of TContractFunction instances contains one element and
|
|
369
|
+
return it.
|
|
370
|
+
"""
|
|
263
371
|
if len(fns) > 1:
|
|
264
|
-
raise
|
|
372
|
+
raise Web3ValueError(
|
|
265
373
|
f"Found multiple functions with matching {identifier}. " f"Found: {fns!r}"
|
|
266
374
|
)
|
|
267
375
|
elif len(fns) == 0:
|
|
268
|
-
raise
|
|
376
|
+
raise Web3ValueError(f"Could not find any function with matching {identifier}")
|
|
269
377
|
return fns[0]
|
|
270
378
|
|
|
271
379
|
|
|
380
|
+
def find_events_by_identifier(
|
|
381
|
+
contract_abi: ABI,
|
|
382
|
+
w3: Union["Web3", "AsyncWeb3"],
|
|
383
|
+
address: ChecksumAddress,
|
|
384
|
+
callable_check: Callable[..., Any],
|
|
385
|
+
event_type: Type[TContractEvent],
|
|
386
|
+
) -> List[TContractEvent]:
|
|
387
|
+
"""
|
|
388
|
+
Given a contract ABI, return a list of TContractEvent instances.
|
|
389
|
+
"""
|
|
390
|
+
event_abis = filter_abi_by_type("event", contract_abi)
|
|
391
|
+
return [
|
|
392
|
+
event_type.factory(
|
|
393
|
+
event_abi["name"],
|
|
394
|
+
w3=w3,
|
|
395
|
+
contract_abi=contract_abi,
|
|
396
|
+
address=address,
|
|
397
|
+
abi=event_abi,
|
|
398
|
+
)
|
|
399
|
+
for event_abi in event_abis
|
|
400
|
+
if callable_check(event_abi)
|
|
401
|
+
]
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
def get_event_by_identifier(
|
|
405
|
+
events: Sequence[TContractEvent], identifier: str
|
|
406
|
+
) -> TContractEvent:
|
|
407
|
+
"""
|
|
408
|
+
Check that the provided list of TContractEvent instances contains one element and
|
|
409
|
+
return it.
|
|
410
|
+
"""
|
|
411
|
+
if len(events) > 1:
|
|
412
|
+
raise Web3ValueError(
|
|
413
|
+
f"Found multiple events with matching {identifier}. " f"Found: {events!r}"
|
|
414
|
+
)
|
|
415
|
+
elif len(events) == 0:
|
|
416
|
+
raise Web3ValueError(f"Could not find any event with matching {identifier}")
|
|
417
|
+
return events[0]
|
|
418
|
+
|
|
419
|
+
|
|
272
420
|
# --- async --- #
|
|
273
421
|
|
|
274
422
|
|
|
@@ -276,7 +424,7 @@ async def async_call_contract_function(
|
|
|
276
424
|
async_w3: "AsyncWeb3",
|
|
277
425
|
address: ChecksumAddress,
|
|
278
426
|
normalizers: Tuple[Callable[..., Any], ...],
|
|
279
|
-
|
|
427
|
+
abi_element_identifier: ABIElementIdentifier,
|
|
280
428
|
transaction: TxParams,
|
|
281
429
|
block_id: Optional[BlockIdentifier] = None,
|
|
282
430
|
contract_abi: Optional[ABI] = None,
|
|
@@ -294,9 +442,9 @@ async def async_call_contract_function(
|
|
|
294
442
|
call_transaction = prepare_transaction(
|
|
295
443
|
address,
|
|
296
444
|
async_w3,
|
|
297
|
-
|
|
445
|
+
abi_element_identifier=abi_element_identifier,
|
|
298
446
|
contract_abi=contract_abi,
|
|
299
|
-
|
|
447
|
+
abi_callable=fn_abi,
|
|
300
448
|
transaction=transaction,
|
|
301
449
|
fn_args=args,
|
|
302
450
|
fn_kwargs=kwargs,
|
|
@@ -310,11 +458,60 @@ async def async_call_contract_function(
|
|
|
310
458
|
)
|
|
311
459
|
|
|
312
460
|
if fn_abi is None:
|
|
313
|
-
fn_abi =
|
|
314
|
-
|
|
461
|
+
fn_abi = cast(
|
|
462
|
+
ABIFunction,
|
|
463
|
+
get_abi_element(
|
|
464
|
+
contract_abi,
|
|
465
|
+
abi_element_identifier,
|
|
466
|
+
*args,
|
|
467
|
+
abi_codec=async_w3.codec,
|
|
468
|
+
**kwargs,
|
|
469
|
+
),
|
|
315
470
|
)
|
|
316
471
|
|
|
317
|
-
|
|
472
|
+
# get the output types, which only exist for function types
|
|
473
|
+
output_types = []
|
|
474
|
+
if fn_abi["type"] == "function":
|
|
475
|
+
output_types = get_abi_output_types(fn_abi)
|
|
476
|
+
|
|
477
|
+
if async_w3.provider._is_batching:
|
|
478
|
+
contract_call_return_data_formatter = format_contract_call_return_data_curried(
|
|
479
|
+
async_w3,
|
|
480
|
+
decode_tuples,
|
|
481
|
+
fn_abi,
|
|
482
|
+
abi_element_identifier,
|
|
483
|
+
normalizers,
|
|
484
|
+
output_types,
|
|
485
|
+
)
|
|
486
|
+
if async_w3.provider.has_persistent_connection:
|
|
487
|
+
# get the current request id
|
|
488
|
+
provider = cast("PersistentConnectionProvider", async_w3.provider)
|
|
489
|
+
current_request_id = provider._batch_request_counter - 1
|
|
490
|
+
provider._request_processor.append_result_formatter_for_request(
|
|
491
|
+
current_request_id, contract_call_return_data_formatter
|
|
492
|
+
)
|
|
493
|
+
else:
|
|
494
|
+
BatchingReturnData: TypeAlias = Tuple[
|
|
495
|
+
Tuple[RPCEndpoint, Any], Tuple[Any, ...]
|
|
496
|
+
]
|
|
497
|
+
request_information = tuple(cast(BatchingReturnData, return_data))
|
|
498
|
+
method_and_params = request_information[0]
|
|
499
|
+
|
|
500
|
+
# append return data formatter to result formatters
|
|
501
|
+
current_response_formatters = request_information[1]
|
|
502
|
+
current_result_formatters = current_response_formatters[0]
|
|
503
|
+
updated_result_formatters = compose(
|
|
504
|
+
contract_call_return_data_formatter,
|
|
505
|
+
current_result_formatters,
|
|
506
|
+
)
|
|
507
|
+
response_formatters = (
|
|
508
|
+
updated_result_formatters, # result formatters
|
|
509
|
+
current_response_formatters[1], # error formatters
|
|
510
|
+
current_response_formatters[2], # null result formatters
|
|
511
|
+
)
|
|
512
|
+
return (method_and_params, response_formatters)
|
|
513
|
+
|
|
514
|
+
return return_data
|
|
318
515
|
|
|
319
516
|
try:
|
|
320
517
|
output_data = async_w3.codec.decode(output_types, return_data)
|
|
@@ -332,7 +529,7 @@ async def async_call_contract_function(
|
|
|
332
529
|
)
|
|
333
530
|
else:
|
|
334
531
|
msg = (
|
|
335
|
-
f"Could not decode contract function call to {
|
|
532
|
+
f"Could not decode contract function call to {abi_element_identifier} "
|
|
336
533
|
f"with return data: {str(return_data)}, output_types: {output_types}"
|
|
337
534
|
)
|
|
338
535
|
raise BadFunctionCallOutput(msg) from e
|
|
@@ -347,16 +544,13 @@ async def async_call_contract_function(
|
|
|
347
544
|
decoded = named_tree(fn_abi["outputs"], normalized_data)
|
|
348
545
|
normalized_data = recursive_dict_to_namedtuple(decoded)
|
|
349
546
|
|
|
350
|
-
if len(normalized_data) == 1
|
|
351
|
-
return normalized_data[0]
|
|
352
|
-
else:
|
|
353
|
-
return normalized_data
|
|
547
|
+
return normalized_data[0] if len(normalized_data) == 1 else normalized_data
|
|
354
548
|
|
|
355
549
|
|
|
356
550
|
async def async_transact_with_contract_function(
|
|
357
551
|
address: ChecksumAddress,
|
|
358
552
|
async_w3: "AsyncWeb3",
|
|
359
|
-
|
|
553
|
+
abi_element_identifier: Optional[ABIElementIdentifier] = None,
|
|
360
554
|
transaction: Optional[TxParams] = None,
|
|
361
555
|
contract_abi: Optional[ABI] = None,
|
|
362
556
|
fn_abi: Optional[ABIFunction] = None,
|
|
@@ -370,10 +564,10 @@ async def async_transact_with_contract_function(
|
|
|
370
564
|
transact_transaction = prepare_transaction(
|
|
371
565
|
address,
|
|
372
566
|
async_w3,
|
|
373
|
-
|
|
567
|
+
abi_element_identifier=abi_element_identifier,
|
|
374
568
|
contract_abi=contract_abi,
|
|
375
569
|
transaction=transaction,
|
|
376
|
-
|
|
570
|
+
abi_callable=fn_abi,
|
|
377
571
|
fn_args=args,
|
|
378
572
|
fn_kwargs=kwargs,
|
|
379
573
|
)
|
|
@@ -385,7 +579,7 @@ async def async_transact_with_contract_function(
|
|
|
385
579
|
async def async_estimate_gas_for_function(
|
|
386
580
|
address: ChecksumAddress,
|
|
387
581
|
async_w3: "AsyncWeb3",
|
|
388
|
-
|
|
582
|
+
abi_element_identifier: Optional[ABIElementIdentifier] = None,
|
|
389
583
|
transaction: Optional[TxParams] = None,
|
|
390
584
|
contract_abi: Optional[ABI] = None,
|
|
391
585
|
fn_abi: Optional[ABIFunction] = None,
|
|
@@ -394,7 +588,8 @@ async def async_estimate_gas_for_function(
|
|
|
394
588
|
*args: Any,
|
|
395
589
|
**kwargs: Any,
|
|
396
590
|
) -> int:
|
|
397
|
-
"""
|
|
591
|
+
"""
|
|
592
|
+
Estimates gas cost a function call would take.
|
|
398
593
|
|
|
399
594
|
Don't call this directly, instead use :meth:`Contract.estimate_gas`
|
|
400
595
|
on your contract instance.
|
|
@@ -402,9 +597,9 @@ async def async_estimate_gas_for_function(
|
|
|
402
597
|
estimate_transaction = prepare_transaction(
|
|
403
598
|
address,
|
|
404
599
|
async_w3,
|
|
405
|
-
|
|
600
|
+
abi_element_identifier=abi_element_identifier,
|
|
406
601
|
contract_abi=contract_abi,
|
|
407
|
-
|
|
602
|
+
abi_callable=fn_abi,
|
|
408
603
|
transaction=transaction,
|
|
409
604
|
fn_args=args,
|
|
410
605
|
fn_kwargs=kwargs,
|
|
@@ -418,14 +613,15 @@ async def async_estimate_gas_for_function(
|
|
|
418
613
|
async def async_build_transaction_for_function(
|
|
419
614
|
address: ChecksumAddress,
|
|
420
615
|
async_w3: "AsyncWeb3",
|
|
421
|
-
|
|
616
|
+
abi_element_identifier: Optional[ABIElementIdentifier] = None,
|
|
422
617
|
transaction: Optional[TxParams] = None,
|
|
423
618
|
contract_abi: Optional[ABI] = None,
|
|
424
619
|
fn_abi: Optional[ABIFunction] = None,
|
|
425
620
|
*args: Any,
|
|
426
621
|
**kwargs: Any,
|
|
427
622
|
) -> TxParams:
|
|
428
|
-
"""
|
|
623
|
+
"""
|
|
624
|
+
Builds a dictionary with the fields required to make the given transaction
|
|
429
625
|
|
|
430
626
|
Don't call this directly, instead use :meth:`Contract.build_transaction`
|
|
431
627
|
on your contract instance.
|
|
@@ -433,9 +629,9 @@ async def async_build_transaction_for_function(
|
|
|
433
629
|
prepared_transaction = prepare_transaction(
|
|
434
630
|
address,
|
|
435
631
|
async_w3,
|
|
436
|
-
|
|
632
|
+
abi_element_identifier=abi_element_identifier,
|
|
437
633
|
contract_abi=contract_abi,
|
|
438
|
-
|
|
634
|
+
abi_callable=fn_abi,
|
|
439
635
|
transaction=transaction,
|
|
440
636
|
fn_args=args,
|
|
441
637
|
fn_kwargs=kwargs,
|