web3 7.5.0__py3-none-any.whl → 7.6.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.
- web3/_utils/abi.py +59 -1
- web3/_utils/contract_sources/contract_data/event_contracts.py +49 -4
- web3/_utils/contracts.py +48 -7
- web3/_utils/method_formatters.py +1 -0
- web3/_utils/module_testing/eth_module.py +11 -0
- web3/_utils/rpc_abi.py +1 -0
- web3/_utils/validation.py +3 -0
- web3/contract/async_contract.py +159 -52
- web3/contract/base_contract.py +138 -102
- web3/contract/contract.py +154 -47
- web3/contract/utils.py +3 -2
- web3/eth/async_eth.py +11 -0
- web3/eth/eth.py +11 -0
- web3/providers/eth_tester/defaults.py +1 -0
- web3/utils/abi.py +308 -76
- {web3-7.5.0.dist-info → web3-7.6.0.dist-info}/METADATA +2 -2
- {web3-7.5.0.dist-info → web3-7.6.0.dist-info}/RECORD +20 -20
- {web3-7.5.0.dist-info → web3-7.6.0.dist-info}/LICENSE +0 -0
- {web3-7.5.0.dist-info → web3-7.6.0.dist-info}/WHEEL +0 -0
- {web3-7.5.0.dist-info → web3-7.6.0.dist-info}/top_level.txt +0 -0
web3/contract/async_contract.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import copy
|
|
2
1
|
from typing import (
|
|
3
2
|
TYPE_CHECKING,
|
|
4
3
|
Any,
|
|
@@ -15,14 +14,15 @@ from typing import (
|
|
|
15
14
|
|
|
16
15
|
from eth_typing import (
|
|
17
16
|
ABI,
|
|
18
|
-
ABIEvent,
|
|
19
17
|
ChecksumAddress,
|
|
20
18
|
)
|
|
21
19
|
from eth_utils import (
|
|
22
20
|
combomethod,
|
|
23
21
|
)
|
|
24
22
|
from eth_utils.abi import (
|
|
23
|
+
abi_to_signature,
|
|
25
24
|
get_abi_input_names,
|
|
25
|
+
get_abi_input_types,
|
|
26
26
|
get_all_function_abis,
|
|
27
27
|
)
|
|
28
28
|
from eth_utils.toolz import (
|
|
@@ -34,6 +34,9 @@ from hexbytes import (
|
|
|
34
34
|
|
|
35
35
|
from web3._utils.abi import (
|
|
36
36
|
fallback_func_abi_exists,
|
|
37
|
+
filter_by_types,
|
|
38
|
+
get_abi_element_signature,
|
|
39
|
+
get_name_from_abi_element_identifier,
|
|
37
40
|
receive_func_abi_exists,
|
|
38
41
|
)
|
|
39
42
|
from web3._utils.abi_element_identifiers import (
|
|
@@ -48,6 +51,8 @@ from web3._utils.compat import (
|
|
|
48
51
|
)
|
|
49
52
|
from web3._utils.contracts import (
|
|
50
53
|
async_parse_block_identifier,
|
|
54
|
+
copy_contract_event,
|
|
55
|
+
copy_contract_function,
|
|
51
56
|
)
|
|
52
57
|
from web3._utils.datatypes import (
|
|
53
58
|
PropertyCheckingFactory,
|
|
@@ -86,7 +91,9 @@ from web3.contract.utils import (
|
|
|
86
91
|
get_function_by_identifier,
|
|
87
92
|
)
|
|
88
93
|
from web3.exceptions import (
|
|
94
|
+
ABIEventNotFound,
|
|
89
95
|
ABIFunctionNotFound,
|
|
96
|
+
NoABIEventsFound,
|
|
90
97
|
NoABIFound,
|
|
91
98
|
NoABIFunctionsFound,
|
|
92
99
|
Web3AttributeError,
|
|
@@ -101,6 +108,8 @@ from web3.types import (
|
|
|
101
108
|
TxParams,
|
|
102
109
|
)
|
|
103
110
|
from web3.utils.abi import (
|
|
111
|
+
_get_any_abi_signature_with_name,
|
|
112
|
+
filter_abi_by_type,
|
|
104
113
|
get_abi_element,
|
|
105
114
|
)
|
|
106
115
|
|
|
@@ -113,16 +122,27 @@ class AsyncContractEvent(BaseContractEvent):
|
|
|
113
122
|
# mypy types
|
|
114
123
|
w3: "AsyncWeb3"
|
|
115
124
|
|
|
116
|
-
def __call__(self) -> "AsyncContractEvent":
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
125
|
+
def __call__(self, *args: Any, **kwargs: Any) -> "AsyncContractEvent":
|
|
126
|
+
event_abi = get_abi_element(
|
|
127
|
+
filter_abi_by_type("event", self.contract_abi),
|
|
128
|
+
self.name,
|
|
129
|
+
*args,
|
|
130
|
+
abi_codec=self.w3.codec,
|
|
131
|
+
**kwargs,
|
|
132
|
+
)
|
|
133
|
+
argument_types = get_abi_input_types(event_abi)
|
|
134
|
+
event_signature = str(
|
|
135
|
+
get_abi_element_signature(self.abi_element_identifier, argument_types)
|
|
136
|
+
)
|
|
137
|
+
contract_event = AsyncContractEvent.factory(
|
|
138
|
+
event_signature,
|
|
139
|
+
w3=self.w3,
|
|
140
|
+
contract_abi=self.contract_abi,
|
|
141
|
+
address=self.address,
|
|
142
|
+
abi_element_identifier=event_signature,
|
|
143
|
+
)
|
|
124
144
|
|
|
125
|
-
return
|
|
145
|
+
return copy_contract_event(contract_event, *args, **kwargs)
|
|
126
146
|
|
|
127
147
|
@combomethod
|
|
128
148
|
async def get_logs(
|
|
@@ -188,11 +208,9 @@ class AsyncContractEvent(BaseContractEvent):
|
|
|
188
208
|
same time as ``from_block`` or ``to_block``
|
|
189
209
|
:yield: Tuple of :class:`AttributeDict` instances
|
|
190
210
|
"""
|
|
191
|
-
event_abi = self._get_event_abi()
|
|
192
|
-
|
|
193
211
|
# validate ``argument_filters`` if present
|
|
194
212
|
if argument_filters is not None:
|
|
195
|
-
event_arg_names = get_abi_input_names(
|
|
213
|
+
event_arg_names = get_abi_input_names(self.abi)
|
|
196
214
|
if not all(arg in event_arg_names for arg in argument_filters.keys()):
|
|
197
215
|
raise Web3ValidationError(
|
|
198
216
|
"When filtering by argument names, all argument names must be "
|
|
@@ -200,17 +218,17 @@ class AsyncContractEvent(BaseContractEvent):
|
|
|
200
218
|
)
|
|
201
219
|
|
|
202
220
|
_filter_params = self._get_event_filter_params(
|
|
203
|
-
|
|
221
|
+
self.abi, argument_filters, from_block, to_block, block_hash
|
|
204
222
|
)
|
|
205
223
|
# call JSON-RPC API
|
|
206
224
|
logs = await self.w3.eth.get_logs(_filter_params)
|
|
207
225
|
|
|
208
226
|
# convert raw binary data to Python proxy objects as described by ABI:
|
|
209
227
|
all_event_logs = tuple(
|
|
210
|
-
get_event_data(self.w3.codec,
|
|
228
|
+
get_event_data(self.w3.codec, self.abi, entry) for entry in logs
|
|
211
229
|
)
|
|
212
230
|
filtered_logs = self._process_get_logs_argument_filters(
|
|
213
|
-
|
|
231
|
+
self.abi,
|
|
214
232
|
all_event_logs,
|
|
215
233
|
argument_filters,
|
|
216
234
|
)
|
|
@@ -231,7 +249,7 @@ class AsyncContractEvent(BaseContractEvent):
|
|
|
231
249
|
"""
|
|
232
250
|
Create filter object that tracks logs emitted by this contract event.
|
|
233
251
|
"""
|
|
234
|
-
filter_builder = AsyncEventFilterBuilder(self.
|
|
252
|
+
filter_builder = AsyncEventFilterBuilder(self.abi, self.w3.codec)
|
|
235
253
|
self._set_up_filter_builder(
|
|
236
254
|
argument_filters,
|
|
237
255
|
from_block,
|
|
@@ -241,9 +259,7 @@ class AsyncContractEvent(BaseContractEvent):
|
|
|
241
259
|
filter_builder,
|
|
242
260
|
)
|
|
243
261
|
log_filter = await filter_builder.deploy(self.w3)
|
|
244
|
-
log_filter.log_entry_formatter = get_event_data(
|
|
245
|
-
self.w3.codec, self._get_event_abi()
|
|
246
|
-
)
|
|
262
|
+
log_filter.log_entry_formatter = get_event_data(self.w3.codec, self.abi)
|
|
247
263
|
log_filter.builder = filter_builder
|
|
248
264
|
|
|
249
265
|
return log_filter
|
|
@@ -251,18 +267,16 @@ class AsyncContractEvent(BaseContractEvent):
|
|
|
251
267
|
@combomethod
|
|
252
268
|
def build_filter(self) -> AsyncEventFilterBuilder:
|
|
253
269
|
builder = AsyncEventFilterBuilder(
|
|
254
|
-
self.
|
|
270
|
+
self.abi,
|
|
255
271
|
self.w3.codec,
|
|
256
|
-
formatter=get_event_data(self.w3.codec, self.
|
|
272
|
+
formatter=get_event_data(self.w3.codec, self.abi),
|
|
257
273
|
)
|
|
258
274
|
builder.address = self.address
|
|
259
275
|
return builder
|
|
260
276
|
|
|
261
277
|
@classmethod
|
|
262
278
|
def factory(cls, class_name: str, **kwargs: Any) -> Self:
|
|
263
|
-
return PropertyCheckingFactory(class_name, (cls,), kwargs)(
|
|
264
|
-
abi=kwargs.get("abi")
|
|
265
|
-
)
|
|
279
|
+
return PropertyCheckingFactory(class_name, (cls,), kwargs)()
|
|
266
280
|
|
|
267
281
|
|
|
268
282
|
class AsyncContractEvents(BaseContractEvents):
|
|
@@ -271,28 +285,84 @@ class AsyncContractEvents(BaseContractEvents):
|
|
|
271
285
|
) -> None:
|
|
272
286
|
super().__init__(abi, w3, AsyncContractEvent, address)
|
|
273
287
|
|
|
288
|
+
def __iter__(self) -> Iterable["AsyncContractEvent"]:
|
|
289
|
+
if not hasattr(self, "_events") or not self._events:
|
|
290
|
+
return
|
|
291
|
+
|
|
292
|
+
for event in self._events:
|
|
293
|
+
yield self[abi_to_signature(event)]
|
|
294
|
+
|
|
295
|
+
def __getattr__(self, event_name: str) -> "AsyncContractEvent":
|
|
296
|
+
if super().__getattribute__("abi") is None:
|
|
297
|
+
raise NoABIFound(
|
|
298
|
+
"There is no ABI found for this contract.",
|
|
299
|
+
)
|
|
300
|
+
if "_events" not in self.__dict__ or len(self._events) == 0:
|
|
301
|
+
raise NoABIEventsFound(
|
|
302
|
+
"The abi for this contract contains no event definitions. ",
|
|
303
|
+
"Are you sure you provided the correct contract abi?",
|
|
304
|
+
)
|
|
305
|
+
elif get_name_from_abi_element_identifier(event_name) not in [
|
|
306
|
+
get_name_from_abi_element_identifier(event["name"])
|
|
307
|
+
for event in self._events
|
|
308
|
+
]:
|
|
309
|
+
raise ABIEventNotFound(
|
|
310
|
+
f"The event '{event_name}' was not found in this contract's abi. ",
|
|
311
|
+
"Are you sure you provided the correct contract abi?",
|
|
312
|
+
)
|
|
313
|
+
else:
|
|
314
|
+
event_abi = get_abi_element(self._events, event_name)
|
|
315
|
+
argument_types = get_abi_input_types(event_abi)
|
|
316
|
+
event_signature = str(get_abi_element_signature(event_name, argument_types))
|
|
317
|
+
return super().__getattribute__(event_signature)
|
|
318
|
+
|
|
319
|
+
def __getitem__(self, event_name: str) -> "AsyncContractEvent":
|
|
320
|
+
return getattr(self, event_name)
|
|
321
|
+
|
|
274
322
|
|
|
275
323
|
class AsyncContractFunction(BaseContractFunction):
|
|
276
324
|
# mypy types
|
|
277
325
|
w3: "AsyncWeb3"
|
|
278
326
|
|
|
279
327
|
def __call__(self, *args: Any, **kwargs: Any) -> "AsyncContractFunction":
|
|
280
|
-
|
|
281
|
-
if args
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
328
|
+
element_name = self.abi_element_identifier
|
|
329
|
+
if element_name in ["fallback", "receive"] or len(args) + len(kwargs):
|
|
330
|
+
# Use only the name if a fallback, receive function
|
|
331
|
+
# or when args/kwargs are present to find the proper element
|
|
332
|
+
element_name = self.fn_name
|
|
333
|
+
|
|
334
|
+
function_abi = get_abi_element(
|
|
335
|
+
filter_by_types(
|
|
336
|
+
["function", "constructor", "fallback", "receive"],
|
|
337
|
+
self.contract_abi,
|
|
338
|
+
),
|
|
339
|
+
element_name,
|
|
340
|
+
*args,
|
|
341
|
+
abi_codec=self.w3.codec,
|
|
342
|
+
**kwargs,
|
|
343
|
+
)
|
|
285
344
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
345
|
+
argument_types = None
|
|
346
|
+
if function_abi["type"] not in ["fallback", "receive"]:
|
|
347
|
+
argument_types = get_abi_input_types(function_abi)
|
|
348
|
+
|
|
349
|
+
function_signature = str(
|
|
350
|
+
get_abi_element_signature(self.abi_element_identifier, argument_types)
|
|
351
|
+
)
|
|
352
|
+
contract_function = AsyncContractFunction.factory(
|
|
353
|
+
function_signature,
|
|
354
|
+
w3=self.w3,
|
|
355
|
+
contract_abi=self.contract_abi,
|
|
356
|
+
address=self.address,
|
|
357
|
+
abi_element_identifier=function_signature,
|
|
358
|
+
decode_tuples=self.decode_tuples,
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
return copy_contract_function(contract_function, *args, **kwargs)
|
|
292
362
|
|
|
293
363
|
@classmethod
|
|
294
364
|
def factory(cls, class_name: str, **kwargs: Any) -> Self:
|
|
295
|
-
return PropertyCheckingFactory(class_name, (cls,), kwargs)(
|
|
365
|
+
return PropertyCheckingFactory(class_name, (cls,), kwargs)()
|
|
296
366
|
|
|
297
367
|
async def call(
|
|
298
368
|
self,
|
|
@@ -332,11 +402,13 @@ class AsyncContractFunction(BaseContractFunction):
|
|
|
332
402
|
|
|
333
403
|
block_id = await async_parse_block_identifier(self.w3, block_identifier)
|
|
334
404
|
|
|
405
|
+
abi_element_identifier = abi_to_signature(self.abi)
|
|
406
|
+
|
|
335
407
|
return await async_call_contract_function(
|
|
336
408
|
self.w3,
|
|
337
409
|
self.address,
|
|
338
410
|
self._return_data_normalizers,
|
|
339
|
-
|
|
411
|
+
abi_element_identifier,
|
|
340
412
|
call_transaction,
|
|
341
413
|
block_id,
|
|
342
414
|
self.contract_abi,
|
|
@@ -350,10 +422,11 @@ class AsyncContractFunction(BaseContractFunction):
|
|
|
350
422
|
|
|
351
423
|
async def transact(self, transaction: Optional[TxParams] = None) -> HexBytes:
|
|
352
424
|
setup_transaction = self._transact(transaction)
|
|
425
|
+
abi_element_identifier = abi_to_signature(self.abi)
|
|
353
426
|
return await async_transact_with_contract_function(
|
|
354
427
|
self.address,
|
|
355
428
|
self.w3,
|
|
356
|
-
|
|
429
|
+
abi_element_identifier,
|
|
357
430
|
setup_transaction,
|
|
358
431
|
self.contract_abi,
|
|
359
432
|
self.abi,
|
|
@@ -368,10 +441,11 @@ class AsyncContractFunction(BaseContractFunction):
|
|
|
368
441
|
state_override: Optional[StateOverride] = None,
|
|
369
442
|
) -> int:
|
|
370
443
|
setup_transaction = self._estimate_gas(transaction)
|
|
444
|
+
abi_element_identifier = abi_to_signature(self.abi)
|
|
371
445
|
return await async_estimate_gas_for_function(
|
|
372
446
|
self.address,
|
|
373
447
|
self.w3,
|
|
374
|
-
|
|
448
|
+
abi_element_identifier,
|
|
375
449
|
setup_transaction,
|
|
376
450
|
self.contract_abi,
|
|
377
451
|
self.abi,
|
|
@@ -385,10 +459,11 @@ class AsyncContractFunction(BaseContractFunction):
|
|
|
385
459
|
self, transaction: Optional[TxParams] = None
|
|
386
460
|
) -> TxParams:
|
|
387
461
|
built_transaction = self._build_transaction(transaction)
|
|
462
|
+
abi_element_identifier = abi_to_signature(self.abi)
|
|
388
463
|
return await async_build_transaction_for_function(
|
|
389
464
|
self.address,
|
|
390
465
|
self.w3,
|
|
391
|
-
|
|
466
|
+
abi_element_identifier,
|
|
392
467
|
built_transaction,
|
|
393
468
|
self.contract_abi,
|
|
394
469
|
self.abi,
|
|
@@ -439,23 +514,45 @@ class AsyncContractFunctions(BaseContractFunctions):
|
|
|
439
514
|
) -> None:
|
|
440
515
|
super().__init__(abi, w3, AsyncContractFunction, address, decode_tuples)
|
|
441
516
|
|
|
517
|
+
def __iter__(self) -> Iterable["AsyncContractFunction"]:
|
|
518
|
+
if not hasattr(self, "_functions") or not self._functions:
|
|
519
|
+
return
|
|
520
|
+
|
|
521
|
+
for func in self._functions:
|
|
522
|
+
yield self[abi_to_signature(func)]
|
|
523
|
+
|
|
442
524
|
def __getattr__(self, function_name: str) -> "AsyncContractFunction":
|
|
443
|
-
if
|
|
525
|
+
if super().__getattribute__("abi") is None:
|
|
444
526
|
raise NoABIFound(
|
|
445
527
|
"There is no ABI found for this contract.",
|
|
446
528
|
)
|
|
447
|
-
|
|
529
|
+
elif "_functions" not in self.__dict__ or len(self._functions) == 0:
|
|
448
530
|
raise NoABIFunctionsFound(
|
|
449
531
|
"The abi for this contract contains no function definitions. ",
|
|
450
532
|
"Are you sure you provided the correct contract abi?",
|
|
451
533
|
)
|
|
452
|
-
elif function_name not in
|
|
534
|
+
elif get_name_from_abi_element_identifier(function_name) not in [
|
|
535
|
+
get_name_from_abi_element_identifier(function["name"])
|
|
536
|
+
for function in self._functions
|
|
537
|
+
]:
|
|
453
538
|
raise ABIFunctionNotFound(
|
|
454
|
-
f"The function '{function_name}' was not found in this contract's
|
|
455
|
-
" Are you sure you provided the correct contract abi?",
|
|
539
|
+
f"The function '{function_name}' was not found in this contract's "
|
|
540
|
+
"abi. Are you sure you provided the correct contract abi?",
|
|
541
|
+
)
|
|
542
|
+
|
|
543
|
+
function_identifier = function_name
|
|
544
|
+
|
|
545
|
+
if "(" not in function_name:
|
|
546
|
+
function_identifier = _get_any_abi_signature_with_name(
|
|
547
|
+
function_name, self._functions
|
|
456
548
|
)
|
|
457
|
-
|
|
458
|
-
|
|
549
|
+
|
|
550
|
+
return super().__getattribute__(
|
|
551
|
+
function_identifier,
|
|
552
|
+
)
|
|
553
|
+
|
|
554
|
+
def __getitem__(self, function_name: str) -> "AsyncContractFunction":
|
|
555
|
+
return getattr(self, function_name)
|
|
459
556
|
|
|
460
557
|
|
|
461
558
|
class AsyncContract(BaseContract):
|
|
@@ -523,6 +620,16 @@ class AsyncContract(BaseContract):
|
|
|
523
620
|
normalizers=normalizers,
|
|
524
621
|
),
|
|
525
622
|
)
|
|
623
|
+
|
|
624
|
+
if contract.abi:
|
|
625
|
+
for abi in contract.abi:
|
|
626
|
+
abi_name = abi.get("name")
|
|
627
|
+
if abi_name in ["abi", "address"]:
|
|
628
|
+
raise Web3AttributeError(
|
|
629
|
+
f"Contract contains a reserved word `{abi_name}` "
|
|
630
|
+
f"and could not be instantiated."
|
|
631
|
+
)
|
|
632
|
+
|
|
526
633
|
contract.functions = AsyncContractFunctions(
|
|
527
634
|
contract.abi, contract.w3, decode_tuples=contract.decode_tuples
|
|
528
635
|
)
|
|
@@ -623,12 +730,12 @@ class AsyncContractCaller(BaseContractCaller):
|
|
|
623
730
|
self._functions = get_all_function_abis(self.abi)
|
|
624
731
|
|
|
625
732
|
for func in self._functions:
|
|
733
|
+
abi_signature = abi_to_signature(func)
|
|
626
734
|
fn = AsyncContractFunction.factory(
|
|
627
|
-
|
|
735
|
+
abi_signature,
|
|
628
736
|
w3=w3,
|
|
629
737
|
contract_abi=self.abi,
|
|
630
738
|
address=self.address,
|
|
631
|
-
abi_element_identifier=func["name"],
|
|
632
739
|
decode_tuples=decode_tuples,
|
|
633
740
|
)
|
|
634
741
|
|
|
@@ -640,7 +747,7 @@ class AsyncContractCaller(BaseContractCaller):
|
|
|
640
747
|
ccip_read_enabled=ccip_read_enabled,
|
|
641
748
|
)
|
|
642
749
|
|
|
643
|
-
setattr(self,
|
|
750
|
+
setattr(self, abi_signature, caller_method)
|
|
644
751
|
|
|
645
752
|
def __call__(
|
|
646
753
|
self,
|