web3 7.7.0__py3-none-any.whl → 7.8.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/async_ens.py +1 -1
- ens/ens.py +1 -1
- web3/_utils/events.py +1 -1
- web3/_utils/http_session_manager.py +19 -1
- web3/_utils/module_testing/eth_module.py +3 -0
- web3/_utils/module_testing/module_testing_utils.py +0 -42
- web3/_utils/module_testing/persistent_connection_provider.py +38 -0
- web3/beacon/api_endpoints.py +10 -0
- web3/beacon/async_beacon.py +47 -0
- web3/beacon/beacon.py +45 -0
- web3/contract/async_contract.py +2 -206
- web3/contract/base_contract.py +208 -12
- web3/contract/contract.py +2 -205
- web3/datastructures.py +4 -0
- web3/manager.py +62 -18
- web3/middleware/base.py +14 -6
- web3/providers/async_base.py +5 -4
- web3/providers/base.py +3 -3
- web3/providers/persistent/request_processor.py +11 -1
- web3/providers/persistent/subscription_manager.py +110 -45
- web3/providers/rpc/async_rpc.py +8 -3
- web3/providers/rpc/rpc.py +8 -3
- web3/types.py +10 -11
- web3/utils/subscriptions.py +5 -1
- {web3-7.7.0.dist-info → web3-7.8.0.dist-info}/LICENSE +1 -1
- {web3-7.7.0.dist-info → web3-7.8.0.dist-info}/METADATA +1 -1
- {web3-7.7.0.dist-info → web3-7.8.0.dist-info}/RECORD +29 -29
- {web3-7.7.0.dist-info → web3-7.8.0.dist-info}/WHEEL +0 -0
- {web3-7.7.0.dist-info → web3-7.8.0.dist-info}/top_level.txt +0 -0
web3/contract/async_contract.py
CHANGED
|
@@ -14,7 +14,6 @@ from typing import (
|
|
|
14
14
|
|
|
15
15
|
from eth_typing import (
|
|
16
16
|
ABI,
|
|
17
|
-
ABIFunction,
|
|
18
17
|
ChecksumAddress,
|
|
19
18
|
)
|
|
20
19
|
from eth_utils import (
|
|
@@ -22,7 +21,6 @@ from eth_utils import (
|
|
|
22
21
|
)
|
|
23
22
|
from eth_utils.abi import (
|
|
24
23
|
abi_to_signature,
|
|
25
|
-
filter_abi_by_type,
|
|
26
24
|
get_abi_input_names,
|
|
27
25
|
)
|
|
28
26
|
from eth_utils.toolz import (
|
|
@@ -34,7 +32,6 @@ from hexbytes import (
|
|
|
34
32
|
|
|
35
33
|
from web3._utils.abi import (
|
|
36
34
|
fallback_func_abi_exists,
|
|
37
|
-
get_name_from_abi_element_identifier,
|
|
38
35
|
receive_func_abi_exists,
|
|
39
36
|
)
|
|
40
37
|
from web3._utils.abi_element_identifiers import (
|
|
@@ -49,8 +46,6 @@ from web3._utils.compat import (
|
|
|
49
46
|
)
|
|
50
47
|
from web3._utils.contracts import (
|
|
51
48
|
async_parse_block_identifier,
|
|
52
|
-
copy_contract_event,
|
|
53
|
-
copy_contract_function,
|
|
54
49
|
)
|
|
55
50
|
from web3._utils.datatypes import (
|
|
56
51
|
PropertyCheckingFactory,
|
|
@@ -89,12 +84,6 @@ from web3.contract.utils import (
|
|
|
89
84
|
get_function_by_identifier,
|
|
90
85
|
)
|
|
91
86
|
from web3.exceptions import (
|
|
92
|
-
ABIEventNotFound,
|
|
93
|
-
ABIFunctionNotFound,
|
|
94
|
-
MismatchedABI,
|
|
95
|
-
NoABIEventsFound,
|
|
96
|
-
NoABIFound,
|
|
97
|
-
NoABIFunctionsFound,
|
|
98
87
|
Web3AttributeError,
|
|
99
88
|
Web3TypeError,
|
|
100
89
|
Web3ValidationError,
|
|
@@ -106,12 +95,6 @@ from web3.types import (
|
|
|
106
95
|
StateOverride,
|
|
107
96
|
TxParams,
|
|
108
97
|
)
|
|
109
|
-
from web3.utils.abi import (
|
|
110
|
-
_filter_by_argument_count,
|
|
111
|
-
_get_any_abi_signature_with_name,
|
|
112
|
-
_mismatched_abi_error_diagnosis,
|
|
113
|
-
get_abi_element,
|
|
114
|
-
)
|
|
115
98
|
|
|
116
99
|
if TYPE_CHECKING:
|
|
117
100
|
from ens import AsyncENS # noqa: F401
|
|
@@ -122,9 +105,6 @@ class AsyncContractEvent(BaseContractEvent):
|
|
|
122
105
|
# mypy types
|
|
123
106
|
w3: "AsyncWeb3"
|
|
124
107
|
|
|
125
|
-
def __call__(self, *args: Any, **kwargs: Any) -> "AsyncContractEvent":
|
|
126
|
-
return copy_contract_event(self, *args, **kwargs)
|
|
127
|
-
|
|
128
108
|
@combomethod
|
|
129
109
|
async def get_logs(
|
|
130
110
|
self,
|
|
@@ -255,162 +235,18 @@ class AsyncContractEvent(BaseContractEvent):
|
|
|
255
235
|
builder.address = self.address
|
|
256
236
|
return builder
|
|
257
237
|
|
|
258
|
-
@classmethod
|
|
259
|
-
def factory(cls, class_name: str, **kwargs: Any) -> Self:
|
|
260
|
-
return PropertyCheckingFactory(class_name, (cls,), kwargs)()
|
|
261
238
|
|
|
262
|
-
|
|
263
|
-
class AsyncContractEvents(BaseContractEvents):
|
|
239
|
+
class AsyncContractEvents(BaseContractEvents[AsyncContractEvent]):
|
|
264
240
|
def __init__(
|
|
265
241
|
self, abi: ABI, w3: "AsyncWeb3", address: Optional[ChecksumAddress] = None
|
|
266
242
|
) -> None:
|
|
267
243
|
super().__init__(abi, w3, AsyncContractEvent, address)
|
|
268
244
|
|
|
269
|
-
def __iter__(self) -> Iterable["AsyncContractEvent"]:
|
|
270
|
-
if not hasattr(self, "_events") or not self._events:
|
|
271
|
-
return
|
|
272
|
-
|
|
273
|
-
for event in self._events:
|
|
274
|
-
yield self[abi_to_signature(event)]
|
|
275
|
-
|
|
276
|
-
def __getattr__(self, event_name: str) -> "AsyncContractEvent":
|
|
277
|
-
if super().__getattribute__("abi") is None:
|
|
278
|
-
raise NoABIFound(
|
|
279
|
-
"There is no ABI found for this contract.",
|
|
280
|
-
)
|
|
281
|
-
elif "_events" not in self.__dict__ or len(self._events) == 0:
|
|
282
|
-
raise NoABIEventsFound(
|
|
283
|
-
"The abi for this contract contains no event definitions. ",
|
|
284
|
-
"Are you sure you provided the correct contract abi?",
|
|
285
|
-
)
|
|
286
|
-
elif get_name_from_abi_element_identifier(event_name) not in [
|
|
287
|
-
get_name_from_abi_element_identifier(event["name"])
|
|
288
|
-
for event in self._events
|
|
289
|
-
]:
|
|
290
|
-
raise ABIEventNotFound(
|
|
291
|
-
f"The event '{event_name}' was not found in this contract's abi. ",
|
|
292
|
-
"Are you sure you provided the correct contract abi?",
|
|
293
|
-
)
|
|
294
|
-
|
|
295
|
-
if "(" not in event_name:
|
|
296
|
-
event_name = _get_any_abi_signature_with_name(event_name, self._events)
|
|
297
|
-
else:
|
|
298
|
-
event_name = f"_{event_name}"
|
|
299
|
-
|
|
300
|
-
return super().__getattribute__(event_name)
|
|
301
|
-
|
|
302
|
-
def __getitem__(self, event_name: str) -> "AsyncContractEvent":
|
|
303
|
-
return getattr(self, event_name)
|
|
304
|
-
|
|
305
245
|
|
|
306
246
|
class AsyncContractFunction(BaseContractFunction):
|
|
307
247
|
# mypy types
|
|
308
248
|
w3: "AsyncWeb3"
|
|
309
249
|
|
|
310
|
-
def __call__(self, *args: Any, **kwargs: Any) -> "AsyncContractFunction":
|
|
311
|
-
# When a function is called, check arguments to obtain the correct function
|
|
312
|
-
# in the contract. self will be used if all args and kwargs are
|
|
313
|
-
# encodable to self.abi, otherwise the correct function is obtained from
|
|
314
|
-
# the contract.
|
|
315
|
-
if (
|
|
316
|
-
self.abi_element_identifier in [FallbackFn, ReceiveFn]
|
|
317
|
-
or self.abi_element_identifier == "constructor"
|
|
318
|
-
):
|
|
319
|
-
return copy_contract_function(self, *args, **kwargs)
|
|
320
|
-
|
|
321
|
-
all_functions = cast(
|
|
322
|
-
List[ABIFunction],
|
|
323
|
-
filter_abi_by_type(
|
|
324
|
-
"function",
|
|
325
|
-
self.contract_abi,
|
|
326
|
-
),
|
|
327
|
-
)
|
|
328
|
-
# Filter functions by name to obtain function signatures
|
|
329
|
-
function_name = get_name_from_abi_element_identifier(
|
|
330
|
-
self.abi_element_identifier
|
|
331
|
-
)
|
|
332
|
-
function_abis = [
|
|
333
|
-
function for function in all_functions if function["name"] == function_name
|
|
334
|
-
]
|
|
335
|
-
num_args = len(args) + len(kwargs)
|
|
336
|
-
function_abis_with_arg_count = cast(
|
|
337
|
-
List[ABIFunction],
|
|
338
|
-
_filter_by_argument_count(
|
|
339
|
-
num_args,
|
|
340
|
-
function_abis,
|
|
341
|
-
),
|
|
342
|
-
)
|
|
343
|
-
|
|
344
|
-
if not len(function_abis_with_arg_count):
|
|
345
|
-
# Build an ABI without arguments to determine if one exists
|
|
346
|
-
function_abis_with_arg_count = [
|
|
347
|
-
ABIFunction({"type": "function", "name": function_name})
|
|
348
|
-
]
|
|
349
|
-
|
|
350
|
-
# Check that arguments in call match a function ABI
|
|
351
|
-
num_attempts = 0
|
|
352
|
-
function_abi_matches = []
|
|
353
|
-
contract_function = None
|
|
354
|
-
for abi in function_abis_with_arg_count:
|
|
355
|
-
try:
|
|
356
|
-
num_attempts += 1
|
|
357
|
-
|
|
358
|
-
# Search for a function ABI that matches the arguments used
|
|
359
|
-
function_abi_matches.append(
|
|
360
|
-
cast(
|
|
361
|
-
ABIFunction,
|
|
362
|
-
get_abi_element(
|
|
363
|
-
function_abis,
|
|
364
|
-
abi_to_signature(abi),
|
|
365
|
-
*args,
|
|
366
|
-
abi_codec=self.w3.codec,
|
|
367
|
-
**kwargs,
|
|
368
|
-
),
|
|
369
|
-
)
|
|
370
|
-
)
|
|
371
|
-
except MismatchedABI:
|
|
372
|
-
# ignore exceptions
|
|
373
|
-
continue
|
|
374
|
-
|
|
375
|
-
if len(function_abi_matches) == 1:
|
|
376
|
-
function_abi = function_abi_matches[0]
|
|
377
|
-
if abi_to_signature(self.abi) == abi_to_signature(function_abi):
|
|
378
|
-
contract_function = self
|
|
379
|
-
else:
|
|
380
|
-
# Found a match that is not self
|
|
381
|
-
contract_function = AsyncContractFunction.factory(
|
|
382
|
-
abi_to_signature(function_abi),
|
|
383
|
-
w3=self.w3,
|
|
384
|
-
contract_abi=self.contract_abi,
|
|
385
|
-
address=self.address,
|
|
386
|
-
abi_element_identifier=abi_to_signature(function_abi),
|
|
387
|
-
abi=function_abi,
|
|
388
|
-
)
|
|
389
|
-
else:
|
|
390
|
-
for abi in function_abi_matches:
|
|
391
|
-
if abi_to_signature(self.abi) == abi_to_signature(abi):
|
|
392
|
-
contract_function = self
|
|
393
|
-
break
|
|
394
|
-
else:
|
|
395
|
-
# Raise exception if multiple found
|
|
396
|
-
raise MismatchedABI(
|
|
397
|
-
_mismatched_abi_error_diagnosis(
|
|
398
|
-
function_name,
|
|
399
|
-
self.contract_abi,
|
|
400
|
-
len(function_abi_matches),
|
|
401
|
-
num_args,
|
|
402
|
-
*args,
|
|
403
|
-
abi_codec=self.w3.codec,
|
|
404
|
-
**kwargs,
|
|
405
|
-
)
|
|
406
|
-
)
|
|
407
|
-
|
|
408
|
-
return copy_contract_function(contract_function, *args, **kwargs)
|
|
409
|
-
|
|
410
|
-
@classmethod
|
|
411
|
-
def factory(cls, class_name: str, **kwargs: Any) -> Self:
|
|
412
|
-
return PropertyCheckingFactory(class_name, (cls,), kwargs)()
|
|
413
|
-
|
|
414
250
|
async def call(
|
|
415
251
|
self,
|
|
416
252
|
transaction: Optional[TxParams] = None,
|
|
@@ -551,7 +387,7 @@ class AsyncContractFunction(BaseContractFunction):
|
|
|
551
387
|
return cast(AsyncContractFunction, NonExistentReceiveFunction())
|
|
552
388
|
|
|
553
389
|
|
|
554
|
-
class AsyncContractFunctions(BaseContractFunctions):
|
|
390
|
+
class AsyncContractFunctions(BaseContractFunctions[AsyncContractFunction]):
|
|
555
391
|
def __init__(
|
|
556
392
|
self,
|
|
557
393
|
abi: ABI,
|
|
@@ -561,46 +397,6 @@ class AsyncContractFunctions(BaseContractFunctions):
|
|
|
561
397
|
) -> None:
|
|
562
398
|
super().__init__(abi, w3, AsyncContractFunction, address, decode_tuples)
|
|
563
399
|
|
|
564
|
-
def __iter__(self) -> Iterable["AsyncContractFunction"]:
|
|
565
|
-
if not hasattr(self, "_functions") or not self._functions:
|
|
566
|
-
return
|
|
567
|
-
|
|
568
|
-
for func in self._functions:
|
|
569
|
-
yield self[abi_to_signature(func)]
|
|
570
|
-
|
|
571
|
-
def __getattr__(self, function_name: str) -> "AsyncContractFunction":
|
|
572
|
-
if super().__getattribute__("abi") is None:
|
|
573
|
-
raise NoABIFound(
|
|
574
|
-
"There is no ABI found for this contract.",
|
|
575
|
-
)
|
|
576
|
-
elif "_functions" not in self.__dict__ or len(self._functions) == 0:
|
|
577
|
-
raise NoABIFunctionsFound(
|
|
578
|
-
"The abi for this contract contains no function definitions. ",
|
|
579
|
-
"Are you sure you provided the correct contract abi?",
|
|
580
|
-
)
|
|
581
|
-
elif get_name_from_abi_element_identifier(function_name) not in [
|
|
582
|
-
get_name_from_abi_element_identifier(function["name"])
|
|
583
|
-
for function in self._functions
|
|
584
|
-
]:
|
|
585
|
-
raise ABIFunctionNotFound(
|
|
586
|
-
f"The function '{function_name}' was not found in this ",
|
|
587
|
-
"contract's abi.",
|
|
588
|
-
)
|
|
589
|
-
|
|
590
|
-
if "(" not in function_name:
|
|
591
|
-
function_name = _get_any_abi_signature_with_name(
|
|
592
|
-
function_name, self._functions
|
|
593
|
-
)
|
|
594
|
-
else:
|
|
595
|
-
function_name = f"_{function_name}"
|
|
596
|
-
|
|
597
|
-
return super().__getattribute__(
|
|
598
|
-
function_name,
|
|
599
|
-
)
|
|
600
|
-
|
|
601
|
-
def __getitem__(self, function_name: str) -> "AsyncContractFunction":
|
|
602
|
-
return getattr(self, function_name)
|
|
603
|
-
|
|
604
400
|
|
|
605
401
|
class AsyncContract(BaseContract):
|
|
606
402
|
functions: AsyncContractFunctions = None
|
web3/contract/base_contract.py
CHANGED
|
@@ -4,6 +4,7 @@ from typing import (
|
|
|
4
4
|
Callable,
|
|
5
5
|
Collection,
|
|
6
6
|
Dict,
|
|
7
|
+
Generic,
|
|
7
8
|
Iterable,
|
|
8
9
|
List,
|
|
9
10
|
NoReturn,
|
|
@@ -58,7 +59,12 @@ from web3._utils.abi_element_identifiers import (
|
|
|
58
59
|
FallbackFn,
|
|
59
60
|
ReceiveFn,
|
|
60
61
|
)
|
|
62
|
+
from web3._utils.compat import (
|
|
63
|
+
Self,
|
|
64
|
+
)
|
|
61
65
|
from web3._utils.contracts import (
|
|
66
|
+
copy_contract_event,
|
|
67
|
+
copy_contract_function,
|
|
62
68
|
decode_transaction_data,
|
|
63
69
|
encode_abi,
|
|
64
70
|
prepare_transaction,
|
|
@@ -98,6 +104,7 @@ from web3.exceptions import (
|
|
|
98
104
|
InvalidEventABI,
|
|
99
105
|
LogTopicError,
|
|
100
106
|
MismatchedABI,
|
|
107
|
+
NoABIEventsFound,
|
|
101
108
|
NoABIFound,
|
|
102
109
|
NoABIFunctionsFound,
|
|
103
110
|
Web3AttributeError,
|
|
@@ -118,12 +125,16 @@ from web3.types import (
|
|
|
118
125
|
EventData,
|
|
119
126
|
FilterParams,
|
|
120
127
|
LogReceipt,
|
|
128
|
+
StateOverride,
|
|
129
|
+
TContractEvent,
|
|
121
130
|
TContractFn,
|
|
122
131
|
TxParams,
|
|
123
132
|
TxReceipt,
|
|
124
133
|
)
|
|
125
134
|
from web3.utils.abi import (
|
|
135
|
+
_filter_by_argument_count,
|
|
126
136
|
_get_any_abi_signature_with_name,
|
|
137
|
+
_mismatched_abi_error_diagnosis,
|
|
127
138
|
check_if_arguments_can_be_encoded,
|
|
128
139
|
get_abi_element,
|
|
129
140
|
get_abi_element_info,
|
|
@@ -189,6 +200,9 @@ class BaseContractEvent:
|
|
|
189
200
|
return f"<Event {abi_to_signature(self.abi)}>"
|
|
190
201
|
return f"<Event {get_abi_element_signature(self.abi_element_identifier)}>"
|
|
191
202
|
|
|
203
|
+
def __call__(self, *args: Any, **kwargs: Any) -> Self:
|
|
204
|
+
return copy_contract_event(self, *args, **kwargs)
|
|
205
|
+
|
|
192
206
|
@property
|
|
193
207
|
def topic(self) -> HexStr:
|
|
194
208
|
if self._topic is None:
|
|
@@ -310,9 +324,7 @@ class BaseContractEvent:
|
|
|
310
324
|
return event_filter_params
|
|
311
325
|
|
|
312
326
|
@classmethod
|
|
313
|
-
def factory(
|
|
314
|
-
cls, class_name: str, **kwargs: Any
|
|
315
|
-
) -> Union["ContractEvent", "AsyncContractEvent"]:
|
|
327
|
+
def factory(cls, class_name: str, **kwargs: Any) -> Self:
|
|
316
328
|
return PropertyCheckingFactory(class_name, (cls,), kwargs)()
|
|
317
329
|
|
|
318
330
|
@staticmethod
|
|
@@ -440,7 +452,7 @@ class BaseContractEvent:
|
|
|
440
452
|
filter_builder.args[arg].match_single(value)
|
|
441
453
|
|
|
442
454
|
|
|
443
|
-
class BaseContractEvents:
|
|
455
|
+
class BaseContractEvents(Generic[TContractEvent]):
|
|
444
456
|
"""
|
|
445
457
|
Class containing contract event objects
|
|
446
458
|
|
|
@@ -466,12 +478,13 @@ class BaseContractEvents:
|
|
|
466
478
|
self,
|
|
467
479
|
abi: ABI,
|
|
468
480
|
w3: Union["Web3", "AsyncWeb3"],
|
|
469
|
-
contract_event_type:
|
|
481
|
+
contract_event_type: Type[TContractEvent],
|
|
470
482
|
address: Optional[ChecksumAddress] = None,
|
|
471
483
|
) -> None:
|
|
472
484
|
self.abi = abi
|
|
473
485
|
self.w3 = w3
|
|
474
486
|
self.address = address
|
|
487
|
+
self.contract_event_type = contract_event_type
|
|
475
488
|
_events: Sequence[ABIEvent] = None
|
|
476
489
|
|
|
477
490
|
if self.abi:
|
|
@@ -506,6 +519,42 @@ class BaseContractEvents:
|
|
|
506
519
|
except ABIEventNotFound:
|
|
507
520
|
return False
|
|
508
521
|
|
|
522
|
+
def __getattr__(self, event_name: str) -> TContractEvent:
|
|
523
|
+
if super().__getattribute__("abi") is None:
|
|
524
|
+
raise NoABIFound(
|
|
525
|
+
"There is no ABI found for this contract.",
|
|
526
|
+
)
|
|
527
|
+
elif "_events" not in self.__dict__ or len(self._events) == 0:
|
|
528
|
+
raise NoABIEventsFound(
|
|
529
|
+
"The abi for this contract contains no event definitions. ",
|
|
530
|
+
"Are you sure you provided the correct contract abi?",
|
|
531
|
+
)
|
|
532
|
+
elif get_name_from_abi_element_identifier(event_name) not in [
|
|
533
|
+
get_name_from_abi_element_identifier(event["name"])
|
|
534
|
+
for event in self._events
|
|
535
|
+
]:
|
|
536
|
+
raise ABIEventNotFound(
|
|
537
|
+
f"The event '{event_name}' was not found in this contract's abi. ",
|
|
538
|
+
"Are you sure you provided the correct contract abi?",
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
if "(" not in event_name:
|
|
542
|
+
event_name = _get_any_abi_signature_with_name(event_name, self._events)
|
|
543
|
+
else:
|
|
544
|
+
event_name = f"_{event_name}"
|
|
545
|
+
|
|
546
|
+
return super().__getattribute__(event_name)
|
|
547
|
+
|
|
548
|
+
def __getitem__(self, event_name: str) -> TContractEvent:
|
|
549
|
+
return getattr(self, event_name)
|
|
550
|
+
|
|
551
|
+
def __iter__(self) -> Iterable[TContractEvent]:
|
|
552
|
+
if not hasattr(self, "_events") or not self._events:
|
|
553
|
+
return
|
|
554
|
+
|
|
555
|
+
for event in self._events:
|
|
556
|
+
yield self[abi_to_signature(event)]
|
|
557
|
+
|
|
509
558
|
|
|
510
559
|
class BaseContractFunction:
|
|
511
560
|
"""
|
|
@@ -721,14 +770,123 @@ class BaseContractFunction:
|
|
|
721
770
|
return _repr + ">"
|
|
722
771
|
return f"<Function {get_abi_element_signature(self.abi_element_identifier)}>"
|
|
723
772
|
|
|
773
|
+
def __call__(self, *args: Any, **kwargs: Any) -> Self:
|
|
774
|
+
# When a function is called, check arguments to obtain the correct function
|
|
775
|
+
# in the contract. self will be used if all args and kwargs are
|
|
776
|
+
# encodable to self.abi, otherwise the correct function is obtained from
|
|
777
|
+
# the contract.
|
|
778
|
+
if (
|
|
779
|
+
self.abi_element_identifier in [FallbackFn, ReceiveFn]
|
|
780
|
+
or self.abi_element_identifier == "constructor"
|
|
781
|
+
):
|
|
782
|
+
return copy_contract_function(self, *args, **kwargs)
|
|
783
|
+
|
|
784
|
+
all_functions = cast(
|
|
785
|
+
List[ABIFunction],
|
|
786
|
+
filter_abi_by_type(
|
|
787
|
+
"function",
|
|
788
|
+
self.contract_abi,
|
|
789
|
+
),
|
|
790
|
+
)
|
|
791
|
+
# Filter functions by name to obtain function signatures
|
|
792
|
+
function_name = get_name_from_abi_element_identifier(
|
|
793
|
+
self.abi_element_identifier
|
|
794
|
+
)
|
|
795
|
+
function_abis = [
|
|
796
|
+
function for function in all_functions if function["name"] == function_name
|
|
797
|
+
]
|
|
798
|
+
num_args = len(args) + len(kwargs)
|
|
799
|
+
function_abis_with_arg_count = cast(
|
|
800
|
+
List[ABIFunction],
|
|
801
|
+
_filter_by_argument_count(
|
|
802
|
+
num_args,
|
|
803
|
+
function_abis,
|
|
804
|
+
),
|
|
805
|
+
)
|
|
806
|
+
|
|
807
|
+
if not len(function_abis_with_arg_count):
|
|
808
|
+
# Build an ABI without arguments to determine if one exists
|
|
809
|
+
function_abis_with_arg_count = [
|
|
810
|
+
ABIFunction({"type": "function", "name": function_name})
|
|
811
|
+
]
|
|
812
|
+
|
|
813
|
+
function_abi_matches = []
|
|
814
|
+
contract_function = None
|
|
815
|
+
for abi in function_abis_with_arg_count:
|
|
816
|
+
try:
|
|
817
|
+
# Search for a function ABI that matches the arguments used
|
|
818
|
+
function_abi_matches.append(
|
|
819
|
+
cast(
|
|
820
|
+
ABIFunction,
|
|
821
|
+
get_abi_element(
|
|
822
|
+
function_abis,
|
|
823
|
+
abi_to_signature(abi),
|
|
824
|
+
*args,
|
|
825
|
+
abi_codec=self.w3.codec,
|
|
826
|
+
**kwargs,
|
|
827
|
+
),
|
|
828
|
+
)
|
|
829
|
+
)
|
|
830
|
+
except MismatchedABI:
|
|
831
|
+
# ignore exceptions
|
|
832
|
+
continue
|
|
833
|
+
|
|
834
|
+
if len(function_abi_matches) == 1:
|
|
835
|
+
function_abi = function_abi_matches[0]
|
|
836
|
+
if abi_to_signature(self.abi) == abi_to_signature(function_abi):
|
|
837
|
+
contract_function = self
|
|
838
|
+
else:
|
|
839
|
+
# Found a match that is not self
|
|
840
|
+
contract_function = self.__class__.factory(
|
|
841
|
+
abi_to_signature(function_abi),
|
|
842
|
+
w3=self.w3,
|
|
843
|
+
contract_abi=self.contract_abi,
|
|
844
|
+
address=self.address,
|
|
845
|
+
abi_element_identifier=abi_to_signature(function_abi),
|
|
846
|
+
abi=function_abi,
|
|
847
|
+
)
|
|
848
|
+
else:
|
|
849
|
+
for abi in function_abi_matches:
|
|
850
|
+
if abi_to_signature(self.abi) == abi_to_signature(abi):
|
|
851
|
+
contract_function = self
|
|
852
|
+
break
|
|
853
|
+
else:
|
|
854
|
+
# Raise exception if multiple found
|
|
855
|
+
raise MismatchedABI(
|
|
856
|
+
_mismatched_abi_error_diagnosis(
|
|
857
|
+
function_name,
|
|
858
|
+
self.contract_abi,
|
|
859
|
+
len(function_abi_matches),
|
|
860
|
+
num_args,
|
|
861
|
+
*args,
|
|
862
|
+
abi_codec=self.w3.codec,
|
|
863
|
+
**kwargs,
|
|
864
|
+
)
|
|
865
|
+
)
|
|
866
|
+
|
|
867
|
+
return copy_contract_function(contract_function, *args, **kwargs)
|
|
868
|
+
|
|
724
869
|
@classmethod
|
|
725
|
-
def factory(
|
|
726
|
-
cls, class_name: str, **kwargs: Any
|
|
727
|
-
) -> Union["ContractFunction", "AsyncContractFunction"]:
|
|
870
|
+
def factory(cls, class_name: str, **kwargs: Any) -> Self:
|
|
728
871
|
return PropertyCheckingFactory(class_name, (cls,), kwargs)()
|
|
729
872
|
|
|
873
|
+
def call(
|
|
874
|
+
self,
|
|
875
|
+
transaction: Optional[TxParams] = None,
|
|
876
|
+
block_identifier: Optional[BlockIdentifier] = None,
|
|
877
|
+
state_override: Optional[StateOverride] = None,
|
|
878
|
+
ccip_read_enabled: Optional[bool] = None,
|
|
879
|
+
) -> Any:
|
|
880
|
+
"""
|
|
881
|
+
Implementation of ``call`` should create a callable contract function
|
|
882
|
+
and execute it using the `eth_call` interface.
|
|
883
|
+
"""
|
|
884
|
+
raise NotImplementedError(
|
|
885
|
+
"This method should be implemented in the inherited class"
|
|
886
|
+
)
|
|
730
887
|
|
|
731
|
-
|
|
888
|
+
|
|
889
|
+
class BaseContractFunctions(Generic[TContractFn]):
|
|
732
890
|
"""Class containing contract function objects"""
|
|
733
891
|
|
|
734
892
|
_functions: Sequence[ABIFunction] = None
|
|
@@ -737,9 +895,7 @@ class BaseContractFunctions:
|
|
|
737
895
|
self,
|
|
738
896
|
abi: ABI,
|
|
739
897
|
w3: Union["Web3", "AsyncWeb3"],
|
|
740
|
-
contract_function_class:
|
|
741
|
-
Type["ContractFunction"], Type["AsyncContractFunction"]
|
|
742
|
-
],
|
|
898
|
+
contract_function_class: Type[TContractFn],
|
|
743
899
|
address: Optional[ChecksumAddress] = None,
|
|
744
900
|
decode_tuples: Optional[bool] = False,
|
|
745
901
|
) -> None:
|
|
@@ -785,6 +941,46 @@ class BaseContractFunctions:
|
|
|
785
941
|
except ABIFunctionNotFound:
|
|
786
942
|
return False
|
|
787
943
|
|
|
944
|
+
def __iter__(self) -> Iterable[TContractFn]:
|
|
945
|
+
if not hasattr(self, "_functions") or not self._functions:
|
|
946
|
+
return
|
|
947
|
+
|
|
948
|
+
for func in self._functions:
|
|
949
|
+
yield self[abi_to_signature(func)]
|
|
950
|
+
|
|
951
|
+
def __getattr__(self, function_name: str) -> TContractFn:
|
|
952
|
+
if super().__getattribute__("abi") is None:
|
|
953
|
+
raise NoABIFound(
|
|
954
|
+
"There is no ABI found for this contract.",
|
|
955
|
+
)
|
|
956
|
+
elif "_functions" not in self.__dict__ or len(self._functions) == 0:
|
|
957
|
+
raise NoABIFunctionsFound(
|
|
958
|
+
"The abi for this contract contains no function definitions. ",
|
|
959
|
+
"Are you sure you provided the correct contract abi?",
|
|
960
|
+
)
|
|
961
|
+
elif get_name_from_abi_element_identifier(function_name) not in [
|
|
962
|
+
get_name_from_abi_element_identifier(function["name"])
|
|
963
|
+
for function in self._functions
|
|
964
|
+
]:
|
|
965
|
+
raise ABIFunctionNotFound(
|
|
966
|
+
f"The function '{function_name}' was not found in this ",
|
|
967
|
+
"contract's abi.",
|
|
968
|
+
)
|
|
969
|
+
|
|
970
|
+
if "(" not in function_name:
|
|
971
|
+
function_name = _get_any_abi_signature_with_name(
|
|
972
|
+
function_name, self._functions
|
|
973
|
+
)
|
|
974
|
+
else:
|
|
975
|
+
function_name = f"_{function_name}"
|
|
976
|
+
|
|
977
|
+
return super().__getattribute__(
|
|
978
|
+
function_name,
|
|
979
|
+
)
|
|
980
|
+
|
|
981
|
+
def __getitem__(self, function_name: str) -> TContractFn:
|
|
982
|
+
return getattr(self, function_name)
|
|
983
|
+
|
|
788
984
|
|
|
789
985
|
class BaseContract:
|
|
790
986
|
"""
|