web3 7.4.0__py3-none-any.whl → 7.5.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/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 +5 -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/method_formatters.py +108 -1
- web3/_utils/module_testing/__init__.py +4 -0
- web3/_utils/module_testing/go_ethereum_debug_module.py +128 -0
- web3/_utils/rpc_abi.py +3 -0
- web3/contract/async_contract.py +45 -2
- web3/contract/base_contract.py +248 -63
- web3/contract/contract.py +41 -0
- web3/contract/utils.py +48 -0
- web3/geth.py +59 -0
- web3/main.py +4 -0
- web3/manager.py +10 -0
- web3/types.py +87 -2
- {web3-7.4.0.dist-info → web3-7.5.0.dist-info}/METADATA +2 -1
- {web3-7.4.0.dist-info → web3-7.5.0.dist-info}/RECORD +38 -37
- {web3-7.4.0.dist-info → web3-7.5.0.dist-info}/WHEEL +1 -1
- {web3-7.4.0.dist-info → web3-7.5.0.dist-info}/LICENSE +0 -0
- {web3-7.4.0.dist-info → web3-7.5.0.dist-info}/top_level.txt +0 -0
web3/contract/base_contract.py
CHANGED
|
@@ -38,6 +38,8 @@ from eth_utils import (
|
|
|
38
38
|
get_normalized_abi_inputs,
|
|
39
39
|
is_list_like,
|
|
40
40
|
is_text,
|
|
41
|
+
keccak,
|
|
42
|
+
to_bytes,
|
|
41
43
|
to_tuple,
|
|
42
44
|
)
|
|
43
45
|
from hexbytes import (
|
|
@@ -66,6 +68,7 @@ from web3._utils.empty import (
|
|
|
66
68
|
empty,
|
|
67
69
|
)
|
|
68
70
|
from web3._utils.encoding import (
|
|
71
|
+
hexstr_if_str,
|
|
69
72
|
to_4byte_hex,
|
|
70
73
|
to_hex,
|
|
71
74
|
)
|
|
@@ -130,8 +133,14 @@ if TYPE_CHECKING:
|
|
|
130
133
|
Web3,
|
|
131
134
|
)
|
|
132
135
|
|
|
133
|
-
from .async_contract import
|
|
134
|
-
|
|
136
|
+
from .async_contract import ( # noqa: F401
|
|
137
|
+
AsyncContractEvent,
|
|
138
|
+
AsyncContractFunction,
|
|
139
|
+
)
|
|
140
|
+
from .contract import ( # noqa: F401
|
|
141
|
+
ContractEvent,
|
|
142
|
+
ContractFunction,
|
|
143
|
+
)
|
|
135
144
|
|
|
136
145
|
|
|
137
146
|
class BaseContractEvent:
|
|
@@ -148,14 +157,18 @@ class BaseContractEvent:
|
|
|
148
157
|
contract_abi: ABI = None
|
|
149
158
|
abi: ABIEvent = None
|
|
150
159
|
|
|
151
|
-
def __init__(self, *argument_names: Tuple[str]) -> None:
|
|
160
|
+
def __init__(self, *argument_names: Tuple[str], abi: ABIEvent) -> None:
|
|
161
|
+
self.abi = abi
|
|
162
|
+
self.name = type(self).__name__
|
|
163
|
+
|
|
152
164
|
if argument_names is None:
|
|
153
165
|
# https://github.com/python/mypy/issues/6283
|
|
154
166
|
self.argument_names = tuple() # type: ignore
|
|
155
167
|
else:
|
|
156
168
|
self.argument_names = argument_names
|
|
157
169
|
|
|
158
|
-
|
|
170
|
+
def __repr__(self) -> str:
|
|
171
|
+
return f"<Event {abi_to_signature(self.abi)}>"
|
|
159
172
|
|
|
160
173
|
@classmethod
|
|
161
174
|
def _get_event_abi(cls) -> ABIEvent:
|
|
@@ -165,8 +178,9 @@ class BaseContractEvent:
|
|
|
165
178
|
def process_receipt(
|
|
166
179
|
self, txn_receipt: TxReceipt, errors: EventLogErrorFlags = WARN
|
|
167
180
|
) -> Iterable[EventData]:
|
|
168
|
-
return self._parse_logs(txn_receipt, errors)
|
|
181
|
+
return self._parse_logs(txn_receipt=txn_receipt, errors=errors)
|
|
169
182
|
|
|
183
|
+
@combomethod
|
|
170
184
|
@to_tuple
|
|
171
185
|
def _parse_logs(
|
|
172
186
|
self, txn_receipt: TxReceipt, errors: EventLogErrorFlags
|
|
@@ -258,8 +272,12 @@ class BaseContractEvent:
|
|
|
258
272
|
return event_filter_params
|
|
259
273
|
|
|
260
274
|
@classmethod
|
|
261
|
-
def factory(
|
|
262
|
-
|
|
275
|
+
def factory(
|
|
276
|
+
cls, class_name: str, **kwargs: Any
|
|
277
|
+
) -> Union["ContractEvent", "AsyncContractEvent"]:
|
|
278
|
+
return PropertyCheckingFactory(class_name, (cls,), kwargs)(
|
|
279
|
+
abi=kwargs.get("abi")
|
|
280
|
+
)
|
|
263
281
|
|
|
264
282
|
@staticmethod
|
|
265
283
|
def check_for_forbidden_api_filter_arguments(
|
|
@@ -414,7 +432,7 @@ class BaseContractEvents:
|
|
|
414
432
|
self,
|
|
415
433
|
abi: ABI,
|
|
416
434
|
w3: Union["Web3", "AsyncWeb3"],
|
|
417
|
-
contract_event_type: Type["
|
|
435
|
+
contract_event_type: Union[Type["ContractEvent"], Type["AsyncContractEvent"]],
|
|
418
436
|
address: Optional[ChecksumAddress] = None,
|
|
419
437
|
) -> None:
|
|
420
438
|
if abi:
|
|
@@ -430,6 +448,7 @@ class BaseContractEvents:
|
|
|
430
448
|
contract_abi=self.abi,
|
|
431
449
|
address=address,
|
|
432
450
|
event_name=event["name"],
|
|
451
|
+
abi=event,
|
|
433
452
|
),
|
|
434
453
|
)
|
|
435
454
|
|
|
@@ -658,7 +677,9 @@ class BaseContractFunction:
|
|
|
658
677
|
def factory(
|
|
659
678
|
cls, class_name: str, **kwargs: Any
|
|
660
679
|
) -> Union["ContractFunction", "AsyncContractFunction"]:
|
|
661
|
-
return PropertyCheckingFactory(class_name, (cls,), kwargs)(
|
|
680
|
+
return PropertyCheckingFactory(class_name, (cls,), kwargs)(
|
|
681
|
+
abi=kwargs.get("abi")
|
|
682
|
+
)
|
|
662
683
|
|
|
663
684
|
|
|
664
685
|
class BaseContractFunctions:
|
|
@@ -766,7 +787,7 @@ class BaseContract:
|
|
|
766
787
|
) -> HexStr:
|
|
767
788
|
"""
|
|
768
789
|
Encodes the arguments using the Ethereum ABI for the contract function
|
|
769
|
-
that matches the given name and arguments
|
|
790
|
+
that matches the given name and arguments.
|
|
770
791
|
|
|
771
792
|
:param data: defaults to function selector
|
|
772
793
|
"""
|
|
@@ -786,16 +807,27 @@ class BaseContract:
|
|
|
786
807
|
|
|
787
808
|
return encode_abi(cls.w3, element_info["abi"], element_info["arguments"], data)
|
|
788
809
|
|
|
810
|
+
#
|
|
811
|
+
# Functions API
|
|
812
|
+
#
|
|
789
813
|
@combomethod
|
|
790
814
|
def all_functions(
|
|
791
815
|
self,
|
|
792
816
|
) -> "BaseContractFunction":
|
|
817
|
+
"""
|
|
818
|
+
Return all functions in the contract.
|
|
819
|
+
"""
|
|
793
820
|
return self.find_functions_by_identifier(
|
|
794
821
|
self.abi, self.w3, self.address, lambda _: True
|
|
795
822
|
)
|
|
796
823
|
|
|
797
824
|
@combomethod
|
|
798
825
|
def get_function_by_signature(self, signature: str) -> "BaseContractFunction":
|
|
826
|
+
"""
|
|
827
|
+
Return a distinct function with matching signature.
|
|
828
|
+
Raises a Web3ValueError if the signature is invalid or if there is no match or
|
|
829
|
+
more than one is found.
|
|
830
|
+
"""
|
|
799
831
|
if " " in signature:
|
|
800
832
|
raise Web3ValueError(
|
|
801
833
|
"Function signature should not contain any spaces. "
|
|
@@ -812,6 +844,11 @@ class BaseContract:
|
|
|
812
844
|
|
|
813
845
|
@combomethod
|
|
814
846
|
def find_functions_by_name(self, fn_name: str) -> "BaseContractFunction":
|
|
847
|
+
"""
|
|
848
|
+
Return all functions with matching name.
|
|
849
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
850
|
+
"""
|
|
851
|
+
|
|
815
852
|
def callable_check(fn_abi: ABIFunction) -> bool:
|
|
816
853
|
return fn_abi["name"] == fn_name
|
|
817
854
|
|
|
@@ -821,6 +858,10 @@ class BaseContract:
|
|
|
821
858
|
|
|
822
859
|
@combomethod
|
|
823
860
|
def get_function_by_name(self, fn_name: str) -> "BaseContractFunction":
|
|
861
|
+
"""
|
|
862
|
+
Return a distinct function with matching name.
|
|
863
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
864
|
+
"""
|
|
824
865
|
fns = self.find_functions_by_name(fn_name)
|
|
825
866
|
return self.get_function_by_identifier(fns, "name")
|
|
826
867
|
|
|
@@ -828,6 +869,11 @@ class BaseContract:
|
|
|
828
869
|
def get_function_by_selector(
|
|
829
870
|
self, selector: Union[bytes, int, HexStr]
|
|
830
871
|
) -> "BaseContractFunction":
|
|
872
|
+
"""
|
|
873
|
+
Return a distinct function with matching 4byte selector.
|
|
874
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
875
|
+
"""
|
|
876
|
+
|
|
831
877
|
def callable_check(fn_abi: ABIFunction) -> bool:
|
|
832
878
|
return encode_hex(function_abi_to_4byte_selector(fn_abi)) == to_4byte_hex(
|
|
833
879
|
selector
|
|
@@ -842,6 +888,9 @@ class BaseContract:
|
|
|
842
888
|
def decode_function_input(
|
|
843
889
|
self, data: HexStr
|
|
844
890
|
) -> Tuple["BaseContractFunction", Dict[str, Any]]:
|
|
891
|
+
"""
|
|
892
|
+
Return a Tuple of the function selector and decoded arguments.
|
|
893
|
+
"""
|
|
845
894
|
func = self.get_function_by_selector(HexBytes(data)[:4])
|
|
846
895
|
arguments = decode_transaction_data(
|
|
847
896
|
func.abi, data, normalizers=BASE_RETURN_NORMALIZERS
|
|
@@ -850,6 +899,11 @@ class BaseContract:
|
|
|
850
899
|
|
|
851
900
|
@combomethod
|
|
852
901
|
def find_functions_by_args(self, *args: Any) -> "BaseContractFunction":
|
|
902
|
+
"""
|
|
903
|
+
Return all functions with matching args, checking each argument can be encoded
|
|
904
|
+
with the type.
|
|
905
|
+
"""
|
|
906
|
+
|
|
853
907
|
def callable_check(fn_abi: ABIFunction) -> bool:
|
|
854
908
|
return check_if_arguments_can_be_encoded(
|
|
855
909
|
fn_abi,
|
|
@@ -864,77 +918,119 @@ class BaseContract:
|
|
|
864
918
|
|
|
865
919
|
@combomethod
|
|
866
920
|
def get_function_by_args(self, *args: Any) -> "BaseContractFunction":
|
|
921
|
+
"""
|
|
922
|
+
Return a distinct function with matching args, checking each argument can be
|
|
923
|
+
encoded with the type.
|
|
924
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
925
|
+
"""
|
|
867
926
|
fns = self.find_functions_by_args(*args)
|
|
868
927
|
return self.get_function_by_identifier(fns, "args")
|
|
869
928
|
|
|
870
929
|
#
|
|
871
|
-
#
|
|
930
|
+
# Events API
|
|
872
931
|
#
|
|
873
|
-
|
|
932
|
+
@combomethod
|
|
933
|
+
def all_events(self) -> List["BaseContractEvent"]:
|
|
934
|
+
"""
|
|
935
|
+
Return all events in the contract.
|
|
936
|
+
"""
|
|
937
|
+
return self.find_events_by_identifier(
|
|
938
|
+
self.abi, self.w3, self.address, lambda _: True
|
|
939
|
+
)
|
|
874
940
|
|
|
875
|
-
@
|
|
876
|
-
def
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
transaction=transaction,
|
|
889
|
-
fn_args=fn_args,
|
|
890
|
-
fn_kwargs=fn_kwargs,
|
|
941
|
+
@combomethod
|
|
942
|
+
def get_event_by_signature(self, signature: str) -> "BaseContractEvent":
|
|
943
|
+
"""
|
|
944
|
+
Return a distinct event with matching signature.
|
|
945
|
+
Raises a Web3ValueError if the signature is invalid or if there is no match or
|
|
946
|
+
more than one is found.
|
|
947
|
+
"""
|
|
948
|
+
|
|
949
|
+
def callable_check(event_abi: ABIEvent) -> bool:
|
|
950
|
+
return abi_to_signature(event_abi) == signature.replace(" ", "")
|
|
951
|
+
|
|
952
|
+
events = self.find_events_by_identifier(
|
|
953
|
+
self.abi, self.w3, self.address, callable_check
|
|
891
954
|
)
|
|
955
|
+
return self.get_event_by_identifier(events, "signature")
|
|
892
956
|
|
|
893
|
-
@
|
|
894
|
-
def
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
**kwargs,
|
|
957
|
+
@combomethod
|
|
958
|
+
def find_events_by_name(self, event_name: str) -> List["BaseContractEvent"]:
|
|
959
|
+
"""
|
|
960
|
+
Return all events with matching name.
|
|
961
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
962
|
+
"""
|
|
963
|
+
|
|
964
|
+
def callable_check(fn_abi: ABIFunction) -> bool:
|
|
965
|
+
return fn_abi["name"] == event_name
|
|
966
|
+
|
|
967
|
+
return self.find_events_by_identifier(
|
|
968
|
+
self.abi, self.w3, self.address, callable_check
|
|
906
969
|
)
|
|
907
970
|
|
|
908
|
-
@
|
|
909
|
-
def
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
971
|
+
@combomethod
|
|
972
|
+
def get_event_by_name(self, event_name: str) -> "BaseContractEvent":
|
|
973
|
+
"""
|
|
974
|
+
Return a distinct event with matching name.
|
|
975
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
976
|
+
"""
|
|
977
|
+
events = self.find_events_by_name(event_name)
|
|
978
|
+
return self.get_event_by_identifier(events, "name")
|
|
979
|
+
|
|
980
|
+
@combomethod
|
|
981
|
+
def find_events_by_selector(
|
|
982
|
+
self, selector: Union[bytes, int, HexStr]
|
|
983
|
+
) -> List["BaseContractEvent"]:
|
|
984
|
+
"""
|
|
985
|
+
Return all events with matching selector.
|
|
986
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
987
|
+
"""
|
|
988
|
+
|
|
989
|
+
def callable_check(event_abi: ABIEvent) -> bool:
|
|
990
|
+
return encode_hex(
|
|
991
|
+
keccak(text=abi_to_signature(event_abi).replace(" ", ""))
|
|
992
|
+
) == encode_hex(hexstr_if_str(to_bytes, selector))
|
|
993
|
+
|
|
994
|
+
return self.find_events_by_identifier(
|
|
995
|
+
self.abi, self.w3, self.address, callable_check
|
|
916
996
|
)
|
|
917
997
|
|
|
918
998
|
@combomethod
|
|
919
|
-
def
|
|
920
|
-
|
|
921
|
-
) ->
|
|
922
|
-
|
|
999
|
+
def get_event_by_selector(
|
|
1000
|
+
self, selector: Union[bytes, int, HexStr]
|
|
1001
|
+
) -> "BaseContractEvent":
|
|
1002
|
+
"""
|
|
1003
|
+
Return a distinct event with matching keccak selector.
|
|
1004
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
1005
|
+
"""
|
|
1006
|
+
events = self.find_events_by_selector(selector)
|
|
1007
|
+
return self.get_event_by_identifier(events, "selector")
|
|
923
1008
|
|
|
924
|
-
|
|
925
|
-
|
|
1009
|
+
@combomethod
|
|
1010
|
+
def find_events_by_topic(self, topic: HexStr) -> List["BaseContractEvent"]:
|
|
1011
|
+
"""
|
|
1012
|
+
Return all events with matching topic.
|
|
1013
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
1014
|
+
"""
|
|
926
1015
|
|
|
927
|
-
|
|
928
|
-
|
|
1016
|
+
def callable_check(event_abi: ABIEvent) -> bool:
|
|
1017
|
+
return (
|
|
1018
|
+
encode_hex(keccak(text=abi_to_signature(event_abi).replace(" ", "")))
|
|
1019
|
+
== topic
|
|
929
1020
|
)
|
|
930
|
-
else:
|
|
931
|
-
if args or kwargs:
|
|
932
|
-
msg = "Constructor args were provided, but no constructor function was provided." # noqa: E501
|
|
933
|
-
raise Web3TypeError(msg)
|
|
934
1021
|
|
|
935
|
-
|
|
1022
|
+
return self.find_events_by_identifier(
|
|
1023
|
+
self.abi, self.w3, self.address, callable_check
|
|
1024
|
+
)
|
|
936
1025
|
|
|
937
|
-
|
|
1026
|
+
@combomethod
|
|
1027
|
+
def get_event_by_topic(self, topic: HexStr) -> "BaseContractEvent":
|
|
1028
|
+
"""
|
|
1029
|
+
Return a distinct event with matching topic.
|
|
1030
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
1031
|
+
"""
|
|
1032
|
+
events = self.find_events_by_topic(topic)
|
|
1033
|
+
return self.get_event_by_identifier(events, "topic")
|
|
938
1034
|
|
|
939
1035
|
@combomethod
|
|
940
1036
|
def find_functions_by_identifier(
|
|
@@ -956,6 +1052,26 @@ class BaseContract:
|
|
|
956
1052
|
"This method should be implemented in the inherited class"
|
|
957
1053
|
)
|
|
958
1054
|
|
|
1055
|
+
@combomethod
|
|
1056
|
+
def find_events_by_identifier(
|
|
1057
|
+
cls,
|
|
1058
|
+
contract_abi: ABI,
|
|
1059
|
+
w3: Union["Web3", "AsyncWeb3"],
|
|
1060
|
+
address: ChecksumAddress,
|
|
1061
|
+
callable_check: Callable[..., Any],
|
|
1062
|
+
) -> List[Any]:
|
|
1063
|
+
raise NotImplementedError(
|
|
1064
|
+
"This method should be implemented in the inherited class"
|
|
1065
|
+
)
|
|
1066
|
+
|
|
1067
|
+
@combomethod
|
|
1068
|
+
def get_event_by_identifier(
|
|
1069
|
+
cls, fns: Sequence["BaseContractEvent"], identifier: str
|
|
1070
|
+
) -> "BaseContractEvent":
|
|
1071
|
+
raise NotImplementedError(
|
|
1072
|
+
"This method should be implemented in the inherited class"
|
|
1073
|
+
)
|
|
1074
|
+
|
|
959
1075
|
@staticmethod
|
|
960
1076
|
def get_fallback_function(
|
|
961
1077
|
abi: ABI,
|
|
@@ -992,6 +1108,75 @@ class BaseContract:
|
|
|
992
1108
|
|
|
993
1109
|
return cast(function_type, NonExistentReceiveFunction()) # type: ignore
|
|
994
1110
|
|
|
1111
|
+
#
|
|
1112
|
+
# Private Helpers
|
|
1113
|
+
#
|
|
1114
|
+
_return_data_normalizers: Tuple[Callable[..., Any], ...] = tuple()
|
|
1115
|
+
|
|
1116
|
+
@classmethod
|
|
1117
|
+
def _prepare_transaction(
|
|
1118
|
+
cls,
|
|
1119
|
+
abi_element_identifier: ABIElementIdentifier,
|
|
1120
|
+
fn_args: Optional[Any] = None,
|
|
1121
|
+
fn_kwargs: Optional[Any] = None,
|
|
1122
|
+
transaction: Optional[TxParams] = None,
|
|
1123
|
+
) -> TxParams:
|
|
1124
|
+
return prepare_transaction(
|
|
1125
|
+
cls.address,
|
|
1126
|
+
cls.w3,
|
|
1127
|
+
abi_element_identifier=abi_element_identifier,
|
|
1128
|
+
contract_abi=cls.abi,
|
|
1129
|
+
transaction=transaction,
|
|
1130
|
+
fn_args=fn_args,
|
|
1131
|
+
fn_kwargs=fn_kwargs,
|
|
1132
|
+
)
|
|
1133
|
+
|
|
1134
|
+
@classmethod
|
|
1135
|
+
def _find_matching_fn_abi(
|
|
1136
|
+
cls,
|
|
1137
|
+
fn_identifier: Optional[ABIElementIdentifier] = None,
|
|
1138
|
+
*args: Sequence[Any],
|
|
1139
|
+
**kwargs: Dict[str, Any],
|
|
1140
|
+
) -> ABIElement:
|
|
1141
|
+
return get_abi_element(
|
|
1142
|
+
cls.abi,
|
|
1143
|
+
fn_identifier,
|
|
1144
|
+
*args,
|
|
1145
|
+
abi_codec=cls.w3.codec,
|
|
1146
|
+
**kwargs,
|
|
1147
|
+
)
|
|
1148
|
+
|
|
1149
|
+
@classmethod
|
|
1150
|
+
def _get_event_abi(
|
|
1151
|
+
cls,
|
|
1152
|
+
event_name: Optional[str] = None,
|
|
1153
|
+
argument_names: Optional[Sequence[str]] = None,
|
|
1154
|
+
) -> ABIEvent:
|
|
1155
|
+
return get_event_abi(
|
|
1156
|
+
abi=cls.abi, event_name=event_name, argument_names=argument_names
|
|
1157
|
+
)
|
|
1158
|
+
|
|
1159
|
+
@combomethod
|
|
1160
|
+
def _encode_constructor_data(
|
|
1161
|
+
cls, *args: Sequence[Any], **kwargs: Dict[str, Any]
|
|
1162
|
+
) -> HexStr:
|
|
1163
|
+
constructor_abi = find_constructor_abi_element_by_type(cls.abi)
|
|
1164
|
+
|
|
1165
|
+
if constructor_abi:
|
|
1166
|
+
arguments = get_normalized_abi_inputs(constructor_abi, *args, **kwargs)
|
|
1167
|
+
|
|
1168
|
+
deploy_data = add_0x_prefix(
|
|
1169
|
+
encode_abi(cls.w3, constructor_abi, arguments, data=cls.bytecode)
|
|
1170
|
+
)
|
|
1171
|
+
else:
|
|
1172
|
+
if args or kwargs:
|
|
1173
|
+
msg = "Constructor args were provided, but no constructor function was provided." # noqa: E501
|
|
1174
|
+
raise Web3TypeError(msg)
|
|
1175
|
+
|
|
1176
|
+
deploy_data = to_hex(cls.bytecode)
|
|
1177
|
+
|
|
1178
|
+
return deploy_data
|
|
1179
|
+
|
|
995
1180
|
|
|
996
1181
|
class BaseContractCaller:
|
|
997
1182
|
"""
|
web3/contract/contract.py
CHANGED
|
@@ -14,6 +14,7 @@ from typing import (
|
|
|
14
14
|
|
|
15
15
|
from eth_typing import (
|
|
16
16
|
ABI,
|
|
17
|
+
ABIEvent,
|
|
17
18
|
ChecksumAddress,
|
|
18
19
|
)
|
|
19
20
|
from eth_utils import (
|
|
@@ -75,7 +76,9 @@ from web3.contract.utils import (
|
|
|
75
76
|
build_transaction_for_function,
|
|
76
77
|
call_contract_function,
|
|
77
78
|
estimate_gas_for_function,
|
|
79
|
+
find_events_by_identifier,
|
|
78
80
|
find_functions_by_identifier,
|
|
81
|
+
get_event_by_identifier,
|
|
79
82
|
get_function_by_identifier,
|
|
80
83
|
transact_with_contract_function,
|
|
81
84
|
)
|
|
@@ -94,6 +97,9 @@ from web3.types import (
|
|
|
94
97
|
StateOverride,
|
|
95
98
|
TxParams,
|
|
96
99
|
)
|
|
100
|
+
from web3.utils.abi import (
|
|
101
|
+
get_abi_element,
|
|
102
|
+
)
|
|
97
103
|
|
|
98
104
|
if TYPE_CHECKING:
|
|
99
105
|
from ens import ENS # noqa: F401
|
|
@@ -104,6 +110,17 @@ class ContractEvent(BaseContractEvent):
|
|
|
104
110
|
# mypy types
|
|
105
111
|
w3: "Web3"
|
|
106
112
|
|
|
113
|
+
def __call__(self) -> "ContractEvent":
|
|
114
|
+
clone = copy.copy(self)
|
|
115
|
+
|
|
116
|
+
if not self.abi:
|
|
117
|
+
self.abi = cast(
|
|
118
|
+
ABIEvent,
|
|
119
|
+
get_abi_element(self.contract_abi, self.event_name),
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
return clone
|
|
123
|
+
|
|
107
124
|
@combomethod
|
|
108
125
|
def get_logs(
|
|
109
126
|
self,
|
|
@@ -238,6 +255,12 @@ class ContractEvent(BaseContractEvent):
|
|
|
238
255
|
builder.address = self.address
|
|
239
256
|
return builder
|
|
240
257
|
|
|
258
|
+
@classmethod
|
|
259
|
+
def factory(cls, class_name: str, **kwargs: Any) -> Self:
|
|
260
|
+
return PropertyCheckingFactory(class_name, (cls,), kwargs)(
|
|
261
|
+
abi=kwargs.get("abi")
|
|
262
|
+
)
|
|
263
|
+
|
|
241
264
|
|
|
242
265
|
class ContractEvents(BaseContractEvents):
|
|
243
266
|
def __init__(
|
|
@@ -562,6 +585,24 @@ class Contract(BaseContract):
|
|
|
562
585
|
) -> "ContractFunction":
|
|
563
586
|
return get_function_by_identifier(fns, identifier)
|
|
564
587
|
|
|
588
|
+
@combomethod
|
|
589
|
+
def find_events_by_identifier(
|
|
590
|
+
cls,
|
|
591
|
+
contract_abi: ABI,
|
|
592
|
+
w3: "Web3",
|
|
593
|
+
address: ChecksumAddress,
|
|
594
|
+
callable_check: Callable[..., Any],
|
|
595
|
+
) -> List["ContractEvent"]:
|
|
596
|
+
return find_events_by_identifier(
|
|
597
|
+
contract_abi, w3, address, callable_check, ContractEvent
|
|
598
|
+
)
|
|
599
|
+
|
|
600
|
+
@combomethod
|
|
601
|
+
def get_event_by_identifier(
|
|
602
|
+
cls, events: Sequence["ContractEvent"], identifier: str
|
|
603
|
+
) -> "ContractEvent":
|
|
604
|
+
return get_event_by_identifier(events, identifier)
|
|
605
|
+
|
|
565
606
|
|
|
566
607
|
class ContractCaller(BaseContractCaller):
|
|
567
608
|
# mypy types
|
web3/contract/utils.py
CHANGED
|
@@ -63,6 +63,7 @@ from web3.types import (
|
|
|
63
63
|
BlockIdentifier,
|
|
64
64
|
RPCEndpoint,
|
|
65
65
|
StateOverride,
|
|
66
|
+
TContractEvent,
|
|
66
67
|
TContractFn,
|
|
67
68
|
TxParams,
|
|
68
69
|
)
|
|
@@ -338,6 +339,9 @@ def find_functions_by_identifier(
|
|
|
338
339
|
callable_check: Callable[..., Any],
|
|
339
340
|
function_type: Type[TContractFn],
|
|
340
341
|
) -> List[TContractFn]:
|
|
342
|
+
"""
|
|
343
|
+
Given a contract ABI, return a list of TContractFunction instances.
|
|
344
|
+
"""
|
|
341
345
|
fns_abi = filter_abi_by_type("function", contract_abi)
|
|
342
346
|
return [
|
|
343
347
|
function_type.factory(
|
|
@@ -356,6 +360,10 @@ def find_functions_by_identifier(
|
|
|
356
360
|
def get_function_by_identifier(
|
|
357
361
|
fns: Sequence[TContractFn], identifier: str
|
|
358
362
|
) -> TContractFn:
|
|
363
|
+
"""
|
|
364
|
+
Check that the provided list of TContractFunction instances contains one element and
|
|
365
|
+
return it.
|
|
366
|
+
"""
|
|
359
367
|
if len(fns) > 1:
|
|
360
368
|
raise Web3ValueError(
|
|
361
369
|
f"Found multiple functions with matching {identifier}. " f"Found: {fns!r}"
|
|
@@ -365,6 +373,46 @@ def get_function_by_identifier(
|
|
|
365
373
|
return fns[0]
|
|
366
374
|
|
|
367
375
|
|
|
376
|
+
def find_events_by_identifier(
|
|
377
|
+
contract_abi: ABI,
|
|
378
|
+
w3: Union["Web3", "AsyncWeb3"],
|
|
379
|
+
address: ChecksumAddress,
|
|
380
|
+
callable_check: Callable[..., Any],
|
|
381
|
+
event_type: Type[TContractEvent],
|
|
382
|
+
) -> List[TContractEvent]:
|
|
383
|
+
"""
|
|
384
|
+
Given a contract ABI, return a list of TContractEvent instances.
|
|
385
|
+
"""
|
|
386
|
+
event_abis = filter_abi_by_type("event", contract_abi)
|
|
387
|
+
return [
|
|
388
|
+
event_type.factory(
|
|
389
|
+
event_abi["name"],
|
|
390
|
+
w3=w3,
|
|
391
|
+
contract_abi=contract_abi,
|
|
392
|
+
address=address,
|
|
393
|
+
abi=event_abi,
|
|
394
|
+
)
|
|
395
|
+
for event_abi in event_abis
|
|
396
|
+
if callable_check(event_abi)
|
|
397
|
+
]
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
def get_event_by_identifier(
|
|
401
|
+
events: Sequence[TContractEvent], identifier: str
|
|
402
|
+
) -> TContractEvent:
|
|
403
|
+
"""
|
|
404
|
+
Check that the provided list of TContractEvent instances contains one element and
|
|
405
|
+
return it.
|
|
406
|
+
"""
|
|
407
|
+
if len(events) > 1:
|
|
408
|
+
raise Web3ValueError(
|
|
409
|
+
f"Found multiple events with matching {identifier}. " f"Found: {events!r}"
|
|
410
|
+
)
|
|
411
|
+
elif len(events) == 0:
|
|
412
|
+
raise Web3ValueError(f"Could not find any event with matching {identifier}")
|
|
413
|
+
return events[0]
|
|
414
|
+
|
|
415
|
+
|
|
368
416
|
# --- async --- #
|
|
369
417
|
|
|
370
418
|
|