web3 7.5.0__py3-none-any.whl → 7.6.1__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/ambiguous_function_contract.py +42 -0
- web3/_utils/contract_sources/contract_data/event_contracts.py +49 -4
- web3/_utils/contracts.py +49 -8
- 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 +216 -62
- web3/contract/base_contract.py +176 -110
- web3/contract/contract.py +227 -64
- web3/contract/utils.py +7 -3
- web3/eth/async_eth.py +11 -0
- web3/eth/eth.py +11 -0
- web3/providers/eth_tester/defaults.py +1 -0
- web3/providers/ipc.py +1 -1
- web3/providers/persistent/async_ipc.py +1 -1
- web3/utils/abi.py +300 -85
- web3/utils/address.py +8 -0
- {web3-7.5.0.dist-info → web3-7.6.1.dist-info}/METADATA +8 -8
- {web3-7.5.0.dist-info → web3-7.6.1.dist-info}/RECORD +24 -23
- {web3-7.5.0.dist-info → web3-7.6.1.dist-info}/LICENSE +0 -0
- {web3-7.5.0.dist-info → web3-7.6.1.dist-info}/WHEEL +0 -0
- {web3-7.5.0.dist-info → web3-7.6.1.dist-info}/top_level.txt +0 -0
web3/contract/base_contract.py
CHANGED
|
@@ -49,6 +49,8 @@ from hexbytes import (
|
|
|
49
49
|
from web3._utils.abi import (
|
|
50
50
|
fallback_func_abi_exists,
|
|
51
51
|
find_constructor_abi_element_by_type,
|
|
52
|
+
get_abi_element_signature,
|
|
53
|
+
get_name_from_abi_element_identifier,
|
|
52
54
|
is_array_type,
|
|
53
55
|
receive_func_abi_exists,
|
|
54
56
|
)
|
|
@@ -96,7 +98,6 @@ from web3.exceptions import (
|
|
|
96
98
|
InvalidEventABI,
|
|
97
99
|
LogTopicError,
|
|
98
100
|
MismatchedABI,
|
|
99
|
-
NoABIEventsFound,
|
|
100
101
|
NoABIFound,
|
|
101
102
|
NoABIFunctionsFound,
|
|
102
103
|
Web3AttributeError,
|
|
@@ -121,10 +122,10 @@ from web3.types import (
|
|
|
121
122
|
TxReceipt,
|
|
122
123
|
)
|
|
123
124
|
from web3.utils.abi import (
|
|
125
|
+
_get_any_abi_signature_with_name,
|
|
124
126
|
check_if_arguments_can_be_encoded,
|
|
125
127
|
get_abi_element,
|
|
126
128
|
get_abi_element_info,
|
|
127
|
-
get_event_abi,
|
|
128
129
|
)
|
|
129
130
|
|
|
130
131
|
if TYPE_CHECKING:
|
|
@@ -153,26 +154,55 @@ class BaseContractEvent:
|
|
|
153
154
|
|
|
154
155
|
address: ChecksumAddress = None
|
|
155
156
|
event_name: str = None
|
|
157
|
+
name: str = None
|
|
158
|
+
abi_element_identifier: ABIElementIdentifier = None
|
|
159
|
+
signature: str = None
|
|
156
160
|
w3: Union["Web3", "AsyncWeb3"] = None
|
|
157
161
|
contract_abi: ABI = None
|
|
158
162
|
abi: ABIEvent = None
|
|
163
|
+
argument_names: Tuple[str, ...] = tuple()
|
|
164
|
+
argument_types: Tuple[str, ...] = tuple()
|
|
165
|
+
args: Any = None
|
|
166
|
+
kwargs: Any = None
|
|
159
167
|
|
|
160
|
-
def __init__(self, *argument_names:
|
|
161
|
-
self.
|
|
162
|
-
self.name =
|
|
168
|
+
def __init__(self, *argument_names: str, abi: Optional[ABIEvent] = None) -> None:
|
|
169
|
+
self.abi_element_identifier = type(self).__name__
|
|
170
|
+
self.name = get_name_from_abi_element_identifier(self.abi_element_identifier)
|
|
171
|
+
self.event_name = self.name
|
|
163
172
|
|
|
164
|
-
if
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
173
|
+
if abi:
|
|
174
|
+
self.abi = abi
|
|
175
|
+
|
|
176
|
+
self.signature = abi_to_signature(self.abi)
|
|
177
|
+
|
|
178
|
+
if argument_names:
|
|
168
179
|
self.argument_names = argument_names
|
|
169
180
|
|
|
181
|
+
event_inputs = self.abi.get("inputs", [])
|
|
182
|
+
self.argument_names = tuple([input.get("name", None) for input in event_inputs])
|
|
183
|
+
self.argument_types = tuple([input["type"] for input in event_inputs])
|
|
184
|
+
|
|
170
185
|
def __repr__(self) -> str:
|
|
171
|
-
|
|
186
|
+
if self.abi:
|
|
187
|
+
return f"<Event {abi_to_signature(self.abi)}>"
|
|
188
|
+
return f"<Event {get_abi_element_signature(self.abi_element_identifier)}>"
|
|
172
189
|
|
|
173
|
-
@
|
|
190
|
+
@combomethod
|
|
174
191
|
def _get_event_abi(cls) -> ABIEvent:
|
|
175
|
-
|
|
192
|
+
if cls.abi:
|
|
193
|
+
return cls.abi
|
|
194
|
+
|
|
195
|
+
return cast(
|
|
196
|
+
ABIEvent,
|
|
197
|
+
get_abi_element(
|
|
198
|
+
filter_abi_by_type("event", cls.contract_abi),
|
|
199
|
+
cls.abi_element_identifier,
|
|
200
|
+
abi_codec=cls.w3.codec,
|
|
201
|
+
),
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
def _set_event_info(self) -> None:
|
|
205
|
+
self.abi = self._get_event_abi()
|
|
176
206
|
|
|
177
207
|
@combomethod
|
|
178
208
|
def process_receipt(
|
|
@@ -275,9 +305,7 @@ class BaseContractEvent:
|
|
|
275
305
|
def factory(
|
|
276
306
|
cls, class_name: str, **kwargs: Any
|
|
277
307
|
) -> Union["ContractEvent", "AsyncContractEvent"]:
|
|
278
|
-
return PropertyCheckingFactory(class_name, (cls,), kwargs)(
|
|
279
|
-
abi=kwargs.get("abi")
|
|
280
|
-
)
|
|
308
|
+
return PropertyCheckingFactory(class_name, (cls,), kwargs)()
|
|
281
309
|
|
|
282
310
|
@staticmethod
|
|
283
311
|
def check_for_forbidden_api_filter_arguments(
|
|
@@ -367,12 +395,10 @@ class BaseContractEvent:
|
|
|
367
395
|
|
|
368
396
|
_filters = dict(**argument_filters)
|
|
369
397
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
self.check_for_forbidden_api_filter_arguments(event_abi, _filters)
|
|
398
|
+
self.check_for_forbidden_api_filter_arguments(self.abi, _filters)
|
|
373
399
|
|
|
374
400
|
_, event_filter_params = construct_event_filter_params(
|
|
375
|
-
self.
|
|
401
|
+
self.abi,
|
|
376
402
|
self.w3.codec,
|
|
377
403
|
contract_address=self.address,
|
|
378
404
|
argument_filters=_filters,
|
|
@@ -435,48 +461,36 @@ class BaseContractEvents:
|
|
|
435
461
|
contract_event_type: Union[Type["ContractEvent"], Type["AsyncContractEvent"]],
|
|
436
462
|
address: Optional[ChecksumAddress] = None,
|
|
437
463
|
) -> None:
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
setattr(
|
|
443
|
-
self,
|
|
444
|
-
event["name"],
|
|
445
|
-
contract_event_type.factory(
|
|
446
|
-
event["name"],
|
|
447
|
-
w3=w3,
|
|
448
|
-
contract_abi=self.abi,
|
|
449
|
-
address=address,
|
|
450
|
-
event_name=event["name"],
|
|
451
|
-
abi=event,
|
|
452
|
-
),
|
|
453
|
-
)
|
|
464
|
+
self.abi = abi
|
|
465
|
+
self.w3 = w3
|
|
466
|
+
self.address = address
|
|
467
|
+
_events: Sequence[ABIEvent] = None
|
|
454
468
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
"Are you sure you provided the correct contract abi?",
|
|
460
|
-
)
|
|
461
|
-
elif event_name not in self.__dict__["_events"]:
|
|
462
|
-
raise ABIEventNotFound(
|
|
463
|
-
f"The event '{event_name}' was not found in this contract's abi. ",
|
|
464
|
-
"Are you sure you provided the correct contract abi?",
|
|
469
|
+
if self.abi:
|
|
470
|
+
_events = sorted(
|
|
471
|
+
filter_abi_by_type("event", self.abi),
|
|
472
|
+
key=lambda evt: (evt["name"], len(evt.get("inputs", []))),
|
|
465
473
|
)
|
|
466
|
-
|
|
467
|
-
|
|
474
|
+
for event in _events:
|
|
475
|
+
abi_signature = abi_to_signature(event)
|
|
476
|
+
event_factory = contract_event_type.factory(
|
|
477
|
+
abi_signature,
|
|
478
|
+
w3=self.w3,
|
|
479
|
+
contract_abi=self.abi,
|
|
480
|
+
address=self.address,
|
|
481
|
+
abi=event,
|
|
482
|
+
)
|
|
468
483
|
|
|
469
|
-
|
|
470
|
-
|
|
484
|
+
# Set event name on instance if it does not already exist
|
|
485
|
+
if event["name"] not in self.__dict__:
|
|
486
|
+
setattr(self, event["name"], event_factory)
|
|
471
487
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
488
|
+
# Set underscore prefixed event signature on instance
|
|
489
|
+
# Handles ambiguity in overloaded contract events
|
|
490
|
+
setattr(self, f"_{abi_signature}", event_factory)
|
|
475
491
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
for event in self._events:
|
|
479
|
-
yield self[event["name"]]
|
|
492
|
+
if _events:
|
|
493
|
+
self._events = _events
|
|
480
494
|
|
|
481
495
|
def __hasattr__(self, event_name: str) -> bool:
|
|
482
496
|
try:
|
|
@@ -494,52 +508,78 @@ class BaseContractFunction:
|
|
|
494
508
|
"""
|
|
495
509
|
|
|
496
510
|
address: ChecksumAddress = None
|
|
511
|
+
fn_name: str = None
|
|
512
|
+
name: str = None
|
|
513
|
+
signature: str = None
|
|
497
514
|
abi_element_identifier: ABIElementIdentifier = None
|
|
498
515
|
w3: Union["Web3", "AsyncWeb3"] = None
|
|
499
516
|
contract_abi: ABI = None
|
|
500
517
|
abi: ABIFunction = None
|
|
501
518
|
transaction: TxParams = None
|
|
502
519
|
arguments: Tuple[Any, ...] = None
|
|
503
|
-
decode_tuples: Optional[bool] =
|
|
520
|
+
decode_tuples: Optional[bool] = None
|
|
521
|
+
argument_names: Tuple[str, ...] = tuple()
|
|
522
|
+
argument_types: Tuple[str, ...] = tuple()
|
|
504
523
|
args: Any = None
|
|
505
524
|
kwargs: Any = None
|
|
506
525
|
|
|
507
526
|
def __init__(self, abi: Optional[ABIFunction] = None) -> None:
|
|
508
|
-
self.
|
|
509
|
-
|
|
527
|
+
if not self.abi_element_identifier:
|
|
528
|
+
self.abi_element_identifier = type(self).__name__
|
|
510
529
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
530
|
+
self.name = get_name_from_abi_element_identifier(self.abi_element_identifier)
|
|
531
|
+
self.fn_name = self.name
|
|
532
|
+
|
|
533
|
+
if abi:
|
|
534
|
+
self.abi = abi
|
|
535
|
+
|
|
536
|
+
self.signature = abi_to_signature(self.abi)
|
|
537
|
+
|
|
538
|
+
event_inputs = self.abi.get("inputs", [])
|
|
539
|
+
self.argument_names = tuple([input.get("name", None) for input in event_inputs])
|
|
540
|
+
self.argument_types = tuple([input["type"] for input in event_inputs])
|
|
541
|
+
|
|
542
|
+
@combomethod
|
|
543
|
+
def _get_abi(cls) -> ABIFunction:
|
|
544
|
+
if not cls.args and not cls.kwargs:
|
|
545
|
+
# If no args or kwargs are provided, get the ABI element by name
|
|
546
|
+
return cast(
|
|
514
547
|
ABIFunction,
|
|
515
548
|
get_abi_element(
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
abi_codec=self.w3.codec,
|
|
520
|
-
**self.kwargs,
|
|
549
|
+
cls.contract_abi,
|
|
550
|
+
get_abi_element_signature(cls.abi_element_identifier),
|
|
551
|
+
abi_codec=cls.w3.codec,
|
|
521
552
|
),
|
|
522
553
|
)
|
|
523
554
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
555
|
+
return cast(
|
|
556
|
+
ABIFunction,
|
|
557
|
+
get_abi_element(
|
|
558
|
+
cls.contract_abi,
|
|
559
|
+
get_name_from_abi_element_identifier(cls.abi_element_identifier),
|
|
560
|
+
*cls.args,
|
|
561
|
+
abi_codec=cls.w3.codec,
|
|
562
|
+
**cls.kwargs,
|
|
563
|
+
),
|
|
564
|
+
)
|
|
533
565
|
|
|
566
|
+
def _set_function_info(self) -> None:
|
|
567
|
+
self.selector = encode_hex(b"")
|
|
534
568
|
if self.abi_element_identifier in [
|
|
569
|
+
"fallback",
|
|
570
|
+
"receive",
|
|
535
571
|
FallbackFn,
|
|
536
572
|
ReceiveFn,
|
|
537
573
|
]:
|
|
574
|
+
self.selector = encode_hex(function_abi_to_4byte_selector(self.abi))
|
|
538
575
|
self.arguments = None
|
|
539
|
-
|
|
576
|
+
elif is_text(self.abi_element_identifier):
|
|
577
|
+
self.selector = encode_hex(function_abi_to_4byte_selector(self.abi))
|
|
540
578
|
self.arguments = get_normalized_abi_inputs(
|
|
541
579
|
self.abi, *self.args, **self.kwargs
|
|
542
580
|
)
|
|
581
|
+
else:
|
|
582
|
+
raise Web3TypeError("Unsupported function identifier")
|
|
543
583
|
|
|
544
584
|
def _get_call_txparams(self, transaction: Optional[TxParams] = None) -> TxParams:
|
|
545
585
|
if transaction is None:
|
|
@@ -671,20 +711,20 @@ class BaseContractFunction:
|
|
|
671
711
|
if self.arguments is not None:
|
|
672
712
|
_repr += f" bound to {self.arguments!r}"
|
|
673
713
|
return _repr + ">"
|
|
674
|
-
return f"<Function {self.
|
|
714
|
+
return f"<Function {get_abi_element_signature(self.abi_element_identifier)}>"
|
|
675
715
|
|
|
676
716
|
@classmethod
|
|
677
717
|
def factory(
|
|
678
718
|
cls, class_name: str, **kwargs: Any
|
|
679
719
|
) -> Union["ContractFunction", "AsyncContractFunction"]:
|
|
680
|
-
return PropertyCheckingFactory(class_name, (cls,), kwargs)(
|
|
681
|
-
abi=kwargs.get("abi")
|
|
682
|
-
)
|
|
720
|
+
return PropertyCheckingFactory(class_name, (cls,), kwargs)()
|
|
683
721
|
|
|
684
722
|
|
|
685
723
|
class BaseContractFunctions:
|
|
686
724
|
"""Class containing contract function objects"""
|
|
687
725
|
|
|
726
|
+
_functions: Sequence[ABIFunction] = None
|
|
727
|
+
|
|
688
728
|
def __init__(
|
|
689
729
|
self,
|
|
690
730
|
abi: ABI,
|
|
@@ -698,32 +738,38 @@ class BaseContractFunctions:
|
|
|
698
738
|
self.abi = abi
|
|
699
739
|
self.w3 = w3
|
|
700
740
|
self.address = address
|
|
741
|
+
_functions: Sequence[ABIFunction] = None
|
|
701
742
|
|
|
702
743
|
if self.abi:
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
744
|
+
# Function with least number of inputs is first
|
|
745
|
+
# This ensures ambiguity will always be deterministic
|
|
746
|
+
# Prefer function without arguments if present, otherwise
|
|
747
|
+
# just use the first available
|
|
748
|
+
_functions = sorted(
|
|
749
|
+
filter_abi_by_type("function", self.abi),
|
|
750
|
+
key=lambda fn: (fn["name"], len(fn.get("inputs", []))),
|
|
751
|
+
)
|
|
752
|
+
for func in _functions:
|
|
753
|
+
abi_signature = abi_to_signature(func)
|
|
754
|
+
function_factory = contract_function_class.factory(
|
|
755
|
+
abi_signature,
|
|
756
|
+
w3=self.w3,
|
|
757
|
+
contract_abi=self.abi,
|
|
758
|
+
address=self.address,
|
|
759
|
+
decode_tuples=decode_tuples,
|
|
760
|
+
abi=func,
|
|
716
761
|
)
|
|
717
762
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
763
|
+
# Set function name on instance if it does not already exist
|
|
764
|
+
if func["name"] not in self.__dict__:
|
|
765
|
+
setattr(self, func["name"], function_factory)
|
|
721
766
|
|
|
722
|
-
|
|
723
|
-
|
|
767
|
+
# Set function signature on instance
|
|
768
|
+
# Handles ambiguity in overloaded contract functions
|
|
769
|
+
setattr(self, f"_{abi_signature}", function_factory)
|
|
724
770
|
|
|
725
|
-
|
|
726
|
-
|
|
771
|
+
if _functions:
|
|
772
|
+
self._functions = _functions
|
|
727
773
|
|
|
728
774
|
def __hasattr__(self, function_name: str) -> bool:
|
|
729
775
|
try:
|
|
@@ -813,7 +859,7 @@ class BaseContract:
|
|
|
813
859
|
@combomethod
|
|
814
860
|
def all_functions(
|
|
815
861
|
self,
|
|
816
|
-
) -> "BaseContractFunction":
|
|
862
|
+
) -> List["BaseContractFunction"]:
|
|
817
863
|
"""
|
|
818
864
|
Return all functions in the contract.
|
|
819
865
|
"""
|
|
@@ -843,7 +889,7 @@ class BaseContract:
|
|
|
843
889
|
return self.get_function_by_identifier(fns, "signature")
|
|
844
890
|
|
|
845
891
|
@combomethod
|
|
846
|
-
def find_functions_by_name(self, fn_name: str) -> "BaseContractFunction":
|
|
892
|
+
def find_functions_by_name(self, fn_name: str) -> List["BaseContractFunction"]:
|
|
847
893
|
"""
|
|
848
894
|
Return all functions with matching name.
|
|
849
895
|
Raises a Web3ValueError if there is no match or more than one is found.
|
|
@@ -1080,12 +1126,14 @@ class BaseContract:
|
|
|
1080
1126
|
address: Optional[ChecksumAddress] = None,
|
|
1081
1127
|
) -> "BaseContractFunction":
|
|
1082
1128
|
if abi and fallback_func_abi_exists(abi):
|
|
1129
|
+
fallback_abi = filter_abi_by_type("fallback", abi)[0]
|
|
1083
1130
|
return function_type.factory(
|
|
1084
1131
|
"fallback",
|
|
1085
1132
|
w3=w3,
|
|
1086
1133
|
contract_abi=abi,
|
|
1087
1134
|
address=address,
|
|
1088
1135
|
abi_element_identifier=FallbackFn,
|
|
1136
|
+
abi=fallback_abi,
|
|
1089
1137
|
)()
|
|
1090
1138
|
|
|
1091
1139
|
return cast(function_type, NonExistentFallbackFunction()) # type: ignore
|
|
@@ -1098,12 +1146,14 @@ class BaseContract:
|
|
|
1098
1146
|
address: Optional[ChecksumAddress] = None,
|
|
1099
1147
|
) -> "BaseContractFunction":
|
|
1100
1148
|
if abi and receive_func_abi_exists(abi):
|
|
1149
|
+
receive_abi = filter_abi_by_type("receive", abi)[0]
|
|
1101
1150
|
return function_type.factory(
|
|
1102
1151
|
"receive",
|
|
1103
1152
|
w3=w3,
|
|
1104
1153
|
contract_abi=abi,
|
|
1105
1154
|
address=address,
|
|
1106
1155
|
abi_element_identifier=ReceiveFn,
|
|
1156
|
+
abi=receive_abi,
|
|
1107
1157
|
)()
|
|
1108
1158
|
|
|
1109
1159
|
return cast(function_type, NonExistentReceiveFunction()) # type: ignore
|
|
@@ -1138,6 +1188,9 @@ class BaseContract:
|
|
|
1138
1188
|
*args: Sequence[Any],
|
|
1139
1189
|
**kwargs: Dict[str, Any],
|
|
1140
1190
|
) -> ABIElement:
|
|
1191
|
+
if not args and not kwargs:
|
|
1192
|
+
fn_identifier = get_abi_element_signature(fn_identifier)
|
|
1193
|
+
|
|
1141
1194
|
return get_abi_element(
|
|
1142
1195
|
cls.abi,
|
|
1143
1196
|
fn_identifier,
|
|
@@ -1152,8 +1205,13 @@ class BaseContract:
|
|
|
1152
1205
|
event_name: Optional[str] = None,
|
|
1153
1206
|
argument_names: Optional[Sequence[str]] = None,
|
|
1154
1207
|
) -> ABIEvent:
|
|
1155
|
-
return
|
|
1156
|
-
|
|
1208
|
+
return cast(
|
|
1209
|
+
ABIEvent,
|
|
1210
|
+
get_abi_element(
|
|
1211
|
+
abi=cls.abi,
|
|
1212
|
+
abi_element_identifier=event_name,
|
|
1213
|
+
argument_names=argument_names,
|
|
1214
|
+
),
|
|
1157
1215
|
)
|
|
1158
1216
|
|
|
1159
1217
|
@combomethod
|
|
@@ -1219,7 +1277,9 @@ class BaseContractCaller:
|
|
|
1219
1277
|
|
|
1220
1278
|
def __getattr__(self, function_name: str) -> Any:
|
|
1221
1279
|
function_names = [
|
|
1222
|
-
fn["name"]
|
|
1280
|
+
get_name_from_abi_element_identifier(fn["name"])
|
|
1281
|
+
for fn in self._functions
|
|
1282
|
+
if fn.get("type") == "function"
|
|
1223
1283
|
]
|
|
1224
1284
|
if self.abi is None:
|
|
1225
1285
|
raise NoABIFound(
|
|
@@ -1230,7 +1290,7 @@ class BaseContractCaller:
|
|
|
1230
1290
|
"The ABI for this contract contains no function definitions. ",
|
|
1231
1291
|
"Are you sure you provided the correct contract ABI?",
|
|
1232
1292
|
)
|
|
1233
|
-
elif function_name not in function_names:
|
|
1293
|
+
elif get_name_from_abi_element_identifier(function_name) not in function_names:
|
|
1234
1294
|
functions_available = ", ".join(function_names)
|
|
1235
1295
|
raise ABIFunctionNotFound(
|
|
1236
1296
|
f"The function '{function_name}' was not found in this contract's ABI.",
|
|
@@ -1239,11 +1299,17 @@ class BaseContractCaller:
|
|
|
1239
1299
|
"Did you mean to call one of those functions?",
|
|
1240
1300
|
)
|
|
1241
1301
|
else:
|
|
1242
|
-
|
|
1302
|
+
function_identifier = function_name
|
|
1243
1303
|
|
|
1244
|
-
|
|
1304
|
+
if "(" not in function_name:
|
|
1305
|
+
function_identifier = _get_any_abi_signature_with_name(
|
|
1306
|
+
function_name, self._functions
|
|
1307
|
+
)
|
|
1308
|
+
return super().__getattribute__(function_identifier)
|
|
1309
|
+
|
|
1310
|
+
def __hasattr__(self, function_name: str) -> bool:
|
|
1245
1311
|
try:
|
|
1246
|
-
return
|
|
1312
|
+
return function_name in self.__dict__["_functions"]
|
|
1247
1313
|
except ABIFunctionNotFound:
|
|
1248
1314
|
return False
|
|
1249
1315
|
|