web3 7.0.0b1__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 +31 -21
- ens/base_ens.py +3 -1
- ens/contract_data.py +2 -2
- ens/ens.py +14 -11
- ens/exceptions.py +16 -29
- ens/specs/nf.json +1 -1
- ens/specs/normalization_spec.json +1 -1
- ens/utils.py +33 -41
- web3/__init__.py +23 -12
- web3/_utils/abi.py +162 -274
- 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 +56 -41
- 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 -43
- web3/manager.py +368 -101
- web3/method.py +43 -15
- web3/middleware/__init__.py +26 -8
- 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 +62 -26
- web3/providers/__init__.py +21 -0
- web3/providers/async_base.py +93 -38
- web3/providers/base.py +85 -40
- web3/providers/eth_tester/__init__.py +5 -0
- web3/providers/eth_tester/defaults.py +2 -55
- web3/providers/eth_tester/main.py +57 -35
- web3/providers/eth_tester/middleware.py +16 -17
- web3/providers/ipc.py +42 -18
- web3/providers/legacy_websocket.py +27 -2
- web3/providers/persistent/__init__.py +7 -0
- web3/providers/persistent/async_ipc.py +61 -121
- web3/providers/persistent/persistent.py +324 -17
- 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.0b1.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.0b1.dist-info → web3-7.7.0.dist-info}/WHEEL +1 -1
- {web3-7.0.0b1.dist-info → web3-7.7.0.dist-info}/top_level.txt +0 -1
- ethpm/__init__.py +0 -20
- ethpm/_utils/__init__.py +0 -0
- ethpm/_utils/backend.py +0 -93
- ethpm/_utils/cache.py +0 -44
- ethpm/_utils/chains.py +0 -119
- ethpm/_utils/contract.py +0 -35
- ethpm/_utils/deployments.py +0 -145
- ethpm/_utils/ipfs.py +0 -116
- ethpm/_utils/protobuf/__init__.py +0 -0
- ethpm/_utils/protobuf/ipfs_file_pb2.py +0 -33
- ethpm/_utils/registry.py +0 -29
- ethpm/assets/__init__.py +0 -0
- ethpm/assets/ens/v3.json +0 -1
- ethpm/assets/escrow/with_bytecode_v3.json +0 -1
- ethpm/assets/ipfs_file.proto +0 -32
- ethpm/assets/owned/output_v3.json +0 -1
- ethpm/assets/owned/with_contract_type_v3.json +0 -1
- ethpm/assets/registry/contracts/Authority.sol +0 -156
- ethpm/assets/registry/contracts/IndexedOrderedSetLib.sol +0 -106
- ethpm/assets/registry/contracts/PackageDB.sol +0 -225
- ethpm/assets/registry/contracts/PackageRegistry.sol +0 -361
- ethpm/assets/registry/contracts/PackageRegistryInterface.sol +0 -97
- ethpm/assets/registry/contracts/ReleaseDB.sol +0 -309
- ethpm/assets/registry/contracts/ReleaseValidator.sol +0 -152
- ethpm/assets/registry/solc_input.json +0 -1
- ethpm/assets/registry/solc_output.json +0 -1
- ethpm/assets/registry/v3.json +0 -1
- ethpm/assets/safe-math-lib/v3-strict-no-deployments.json +0 -1
- ethpm/assets/simple-registry/contracts/Ownable.sol +0 -63
- ethpm/assets/simple-registry/contracts/PackageRegistry.sol +0 -373
- ethpm/assets/simple-registry/contracts/PackageRegistryInterface.sol +0 -96
- ethpm/assets/simple-registry/solc_input.json +0 -33
- ethpm/assets/simple-registry/solc_output.json +0 -1
- ethpm/assets/simple-registry/v3.json +0 -1
- ethpm/assets/standard-token/output_v3.json +0 -1
- ethpm/assets/standard-token/with_bytecode_v3.json +0 -1
- ethpm/assets/vyper_registry/0.1.0.json +0 -1
- ethpm/assets/vyper_registry/registry.vy +0 -216
- ethpm/assets/vyper_registry/registry_with_delete.vy +0 -244
- ethpm/backends/__init__.py +0 -0
- ethpm/backends/base.py +0 -43
- ethpm/backends/http.py +0 -108
- ethpm/backends/ipfs.py +0 -219
- ethpm/backends/registry.py +0 -154
- ethpm/constants.py +0 -17
- ethpm/contract.py +0 -187
- ethpm/dependencies.py +0 -58
- ethpm/deployments.py +0 -80
- ethpm/ethpm-spec/examples/escrow/1.0.0-pretty.json +0 -146
- ethpm/ethpm-spec/examples/escrow/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/escrow/contracts/Escrow.sol +0 -32
- ethpm/ethpm-spec/examples/escrow/contracts/SafeSendLib.sol +0 -20
- ethpm/ethpm-spec/examples/escrow/v3-pretty.json +0 -171
- ethpm/ethpm-spec/examples/escrow/v3.json +0 -1
- ethpm/ethpm-spec/examples/owned/1.0.0-pretty.json +0 -21
- ethpm/ethpm-spec/examples/owned/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/owned/contracts/Owned.sol +0 -12
- ethpm/ethpm-spec/examples/owned/v3-pretty.json +0 -27
- ethpm/ethpm-spec/examples/owned/v3.json +0 -1
- ethpm/ethpm-spec/examples/piper-coin/1.0.0-pretty.json +0 -31
- ethpm/ethpm-spec/examples/piper-coin/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/piper-coin/v3-pretty.json +0 -21
- ethpm/ethpm-spec/examples/piper-coin/v3.json +0 -1
- ethpm/ethpm-spec/examples/safe-math-lib/1.0.0-pretty.json +0 -85
- ethpm/ethpm-spec/examples/safe-math-lib/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/safe-math-lib/contracts/SafeMathLib.sol +0 -24
- ethpm/ethpm-spec/examples/safe-math-lib/v3-pretty.json +0 -117
- ethpm/ethpm-spec/examples/safe-math-lib/v3.json +0 -1
- ethpm/ethpm-spec/examples/standard-token/1.0.0-pretty.json +0 -55
- ethpm/ethpm-spec/examples/standard-token/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/standard-token/contracts/AbstractToken.sol +0 -20
- ethpm/ethpm-spec/examples/standard-token/contracts/StandardToken.sol +0 -84
- ethpm/ethpm-spec/examples/standard-token/v3-pretty.json +0 -460
- ethpm/ethpm-spec/examples/standard-token/v3.json +0 -1
- ethpm/ethpm-spec/examples/transferable/1.0.0-pretty.json +0 -21
- ethpm/ethpm-spec/examples/transferable/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/transferable/contracts/Transferable.sol +0 -14
- ethpm/ethpm-spec/examples/transferable/v3-pretty.json +0 -27
- ethpm/ethpm-spec/examples/transferable/v3.json +0 -1
- ethpm/ethpm-spec/examples/wallet/1.0.0-pretty.json +0 -120
- ethpm/ethpm-spec/examples/wallet/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/wallet/contracts/Wallet.sol +0 -41
- ethpm/ethpm-spec/examples/wallet/v3-pretty.json +0 -181
- ethpm/ethpm-spec/examples/wallet/v3.json +0 -1
- ethpm/ethpm-spec/examples/wallet-with-send/1.0.0-pretty.json +0 -135
- ethpm/ethpm-spec/examples/wallet-with-send/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/wallet-with-send/contracts/WalletWithSend.sol +0 -18
- ethpm/ethpm-spec/examples/wallet-with-send/v3-pretty.json +0 -207
- ethpm/ethpm-spec/examples/wallet-with-send/v3.json +0 -1
- ethpm/ethpm-spec/spec/package.spec.json +0 -379
- ethpm/ethpm-spec/spec/v3.spec.json +0 -483
- ethpm/exceptions.py +0 -68
- ethpm/package.py +0 -438
- ethpm/tools/__init__.py +0 -4
- ethpm/tools/builder.py +0 -930
- ethpm/tools/checker.py +0 -312
- ethpm/tools/get_manifest.py +0 -19
- ethpm/uri.py +0 -141
- ethpm/validation/__init__.py +0 -0
- ethpm/validation/manifest.py +0 -146
- ethpm/validation/misc.py +0 -39
- ethpm/validation/package.py +0 -80
- ethpm/validation/uri.py +0 -163
- 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/pm.py +0 -602
- web3/tools/__init__.py +0 -4
- web3/tools/benchmark/__init__.py +0 -0
- web3/tools/benchmark/main.py +0 -185
- web3/tools/benchmark/node.py +0 -126
- web3/tools/benchmark/reporting.py +0 -39
- web3/tools/benchmark/utils.py +0 -69
- web3/tools/pytest_ethereum/__init__.py +0 -0
- web3/tools/pytest_ethereum/_utils.py +0 -145
- web3/tools/pytest_ethereum/deployer.py +0 -48
- web3/tools/pytest_ethereum/exceptions.py +0 -22
- web3/tools/pytest_ethereum/linker.py +0 -128
- web3/tools/pytest_ethereum/plugins.py +0 -33
- web3-7.0.0b1.dist-info/METADATA +0 -114
- web3-7.0.0b1.dist-info/RECORD +0 -280
- web3-7.0.0b1.dist-info/entry_points.txt +0 -2
- /web3/_utils/{function_identifiers.py → abi_element_identifiers.py} +0 -0
web3/contract/base_contract.py
CHANGED
|
@@ -16,18 +16,30 @@ from typing import (
|
|
|
16
16
|
)
|
|
17
17
|
import warnings
|
|
18
18
|
|
|
19
|
+
from eth_abi.exceptions import (
|
|
20
|
+
InsufficientDataBytes,
|
|
21
|
+
)
|
|
19
22
|
from eth_typing import (
|
|
23
|
+
ABI,
|
|
24
|
+
ABIElement,
|
|
25
|
+
ABIEvent,
|
|
26
|
+
ABIFunction,
|
|
20
27
|
Address,
|
|
21
28
|
ChecksumAddress,
|
|
22
29
|
HexStr,
|
|
23
30
|
)
|
|
24
31
|
from eth_utils import (
|
|
32
|
+
abi_to_signature,
|
|
25
33
|
add_0x_prefix,
|
|
26
34
|
combomethod,
|
|
27
35
|
encode_hex,
|
|
36
|
+
filter_abi_by_type,
|
|
28
37
|
function_abi_to_4byte_selector,
|
|
38
|
+
get_normalized_abi_inputs,
|
|
29
39
|
is_list_like,
|
|
30
40
|
is_text,
|
|
41
|
+
keccak,
|
|
42
|
+
to_bytes,
|
|
31
43
|
to_tuple,
|
|
32
44
|
)
|
|
33
45
|
from hexbytes import (
|
|
@@ -35,21 +47,20 @@ from hexbytes import (
|
|
|
35
47
|
)
|
|
36
48
|
|
|
37
49
|
from web3._utils.abi import (
|
|
38
|
-
abi_to_signature,
|
|
39
|
-
check_if_arguments_can_be_encoded,
|
|
40
50
|
fallback_func_abi_exists,
|
|
41
|
-
|
|
42
|
-
|
|
51
|
+
find_constructor_abi_element_by_type,
|
|
52
|
+
get_abi_element_signature,
|
|
53
|
+
get_name_from_abi_element_identifier,
|
|
43
54
|
is_array_type,
|
|
44
|
-
merge_args_and_kwargs,
|
|
45
55
|
receive_func_abi_exists,
|
|
46
56
|
)
|
|
57
|
+
from web3._utils.abi_element_identifiers import (
|
|
58
|
+
FallbackFn,
|
|
59
|
+
ReceiveFn,
|
|
60
|
+
)
|
|
47
61
|
from web3._utils.contracts import (
|
|
48
62
|
decode_transaction_data,
|
|
49
63
|
encode_abi,
|
|
50
|
-
find_matching_event_abi,
|
|
51
|
-
find_matching_fn_abi,
|
|
52
|
-
get_function_info,
|
|
53
64
|
prepare_transaction,
|
|
54
65
|
)
|
|
55
66
|
from web3._utils.datatypes import (
|
|
@@ -59,6 +70,7 @@ from web3._utils.empty import (
|
|
|
59
70
|
empty,
|
|
60
71
|
)
|
|
61
72
|
from web3._utils.encoding import (
|
|
73
|
+
hexstr_if_str,
|
|
62
74
|
to_4byte_hex,
|
|
63
75
|
to_hex,
|
|
64
76
|
)
|
|
@@ -71,10 +83,6 @@ from web3._utils.events import (
|
|
|
71
83
|
from web3._utils.filters import (
|
|
72
84
|
construct_event_filter_params,
|
|
73
85
|
)
|
|
74
|
-
from web3._utils.function_identifiers import (
|
|
75
|
-
FallbackFn,
|
|
76
|
-
ReceiveFn,
|
|
77
|
-
)
|
|
78
86
|
from web3._utils.normalizers import (
|
|
79
87
|
BASE_RETURN_NORMALIZERS,
|
|
80
88
|
)
|
|
@@ -83,16 +91,19 @@ from web3.datastructures import (
|
|
|
83
91
|
MutableAttributeDict,
|
|
84
92
|
)
|
|
85
93
|
from web3.exceptions import (
|
|
86
|
-
|
|
94
|
+
ABIEventNotFound,
|
|
95
|
+
ABIFallbackNotFound,
|
|
87
96
|
ABIFunctionNotFound,
|
|
88
|
-
|
|
97
|
+
ABIReceiveNotFound,
|
|
89
98
|
InvalidEventABI,
|
|
90
99
|
LogTopicError,
|
|
91
100
|
MismatchedABI,
|
|
92
|
-
NoABIEventsFound,
|
|
93
101
|
NoABIFound,
|
|
94
102
|
NoABIFunctionsFound,
|
|
103
|
+
Web3AttributeError,
|
|
104
|
+
Web3TypeError,
|
|
95
105
|
Web3ValidationError,
|
|
106
|
+
Web3ValueError,
|
|
96
107
|
)
|
|
97
108
|
from web3.logs import (
|
|
98
109
|
DISCARD,
|
|
@@ -102,17 +113,21 @@ from web3.logs import (
|
|
|
102
113
|
EventLogErrorFlags,
|
|
103
114
|
)
|
|
104
115
|
from web3.types import (
|
|
105
|
-
|
|
106
|
-
ABIEvent,
|
|
107
|
-
ABIFunction,
|
|
116
|
+
ABIElementIdentifier,
|
|
108
117
|
BlockIdentifier,
|
|
109
118
|
EventData,
|
|
110
119
|
FilterParams,
|
|
111
|
-
|
|
120
|
+
LogReceipt,
|
|
112
121
|
TContractFn,
|
|
113
122
|
TxParams,
|
|
114
123
|
TxReceipt,
|
|
115
124
|
)
|
|
125
|
+
from web3.utils.abi import (
|
|
126
|
+
_get_any_abi_signature_with_name,
|
|
127
|
+
check_if_arguments_can_be_encoded,
|
|
128
|
+
get_abi_element,
|
|
129
|
+
get_abi_element_info,
|
|
130
|
+
)
|
|
116
131
|
|
|
117
132
|
if TYPE_CHECKING:
|
|
118
133
|
from web3 import ( # noqa: F401
|
|
@@ -120,12 +135,19 @@ if TYPE_CHECKING:
|
|
|
120
135
|
Web3,
|
|
121
136
|
)
|
|
122
137
|
|
|
123
|
-
from .async_contract import
|
|
124
|
-
|
|
138
|
+
from .async_contract import ( # noqa: F401
|
|
139
|
+
AsyncContractEvent,
|
|
140
|
+
AsyncContractFunction,
|
|
141
|
+
)
|
|
142
|
+
from .contract import ( # noqa: F401
|
|
143
|
+
ContractEvent,
|
|
144
|
+
ContractFunction,
|
|
145
|
+
)
|
|
125
146
|
|
|
126
147
|
|
|
127
148
|
class BaseContractEvent:
|
|
128
|
-
"""
|
|
149
|
+
"""
|
|
150
|
+
Base class for contract events
|
|
129
151
|
|
|
130
152
|
An event accessed via the api `contract.events.myEvents(*args, **kwargs)`
|
|
131
153
|
is a subclass of this class.
|
|
@@ -133,29 +155,70 @@ class BaseContractEvent:
|
|
|
133
155
|
|
|
134
156
|
address: ChecksumAddress = None
|
|
135
157
|
event_name: str = None
|
|
158
|
+
name: str = None
|
|
159
|
+
abi_element_identifier: ABIElementIdentifier = None
|
|
160
|
+
signature: str = None
|
|
136
161
|
w3: Union["Web3", "AsyncWeb3"] = None
|
|
137
162
|
contract_abi: ABI = None
|
|
138
163
|
abi: ABIEvent = None
|
|
164
|
+
argument_names: Tuple[str, ...] = tuple()
|
|
165
|
+
argument_types: Tuple[str, ...] = tuple()
|
|
166
|
+
args: Any = None
|
|
167
|
+
kwargs: Any = None
|
|
168
|
+
_topic: HexStr = None
|
|
139
169
|
|
|
140
|
-
def __init__(self, *argument_names:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
170
|
+
def __init__(self, *argument_names: str, abi: Optional[ABIEvent] = None) -> None:
|
|
171
|
+
self.abi_element_identifier = type(self).__name__
|
|
172
|
+
self.name = get_name_from_abi_element_identifier(self.abi_element_identifier)
|
|
173
|
+
self.event_name = self.name
|
|
174
|
+
|
|
175
|
+
if abi:
|
|
176
|
+
self.abi = abi
|
|
177
|
+
|
|
178
|
+
self.signature = abi_to_signature(self.abi)
|
|
179
|
+
|
|
180
|
+
if argument_names:
|
|
145
181
|
self.argument_names = argument_names
|
|
146
182
|
|
|
147
|
-
|
|
183
|
+
event_inputs = self.abi.get("inputs", [])
|
|
184
|
+
self.argument_names = tuple([input.get("name", None) for input in event_inputs])
|
|
185
|
+
self.argument_types = tuple([input["type"] for input in event_inputs])
|
|
148
186
|
|
|
149
|
-
|
|
187
|
+
def __repr__(self) -> str:
|
|
188
|
+
if self.abi:
|
|
189
|
+
return f"<Event {abi_to_signature(self.abi)}>"
|
|
190
|
+
return f"<Event {get_abi_element_signature(self.abi_element_identifier)}>"
|
|
191
|
+
|
|
192
|
+
@property
|
|
193
|
+
def topic(self) -> HexStr:
|
|
194
|
+
if self._topic is None:
|
|
195
|
+
self._topic = encode_hex(keccak(text=self.signature))
|
|
196
|
+
return self._topic
|
|
197
|
+
|
|
198
|
+
@combomethod
|
|
150
199
|
def _get_event_abi(cls) -> ABIEvent:
|
|
151
|
-
|
|
200
|
+
if cls.abi:
|
|
201
|
+
return cls.abi
|
|
202
|
+
|
|
203
|
+
return cast(
|
|
204
|
+
ABIEvent,
|
|
205
|
+
get_abi_element(
|
|
206
|
+
filter_abi_by_type("event", cls.contract_abi),
|
|
207
|
+
cls.abi_element_identifier,
|
|
208
|
+
abi_codec=cls.w3.codec,
|
|
209
|
+
),
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
def _set_event_info(self) -> None:
|
|
213
|
+
self.abi = self._get_event_abi()
|
|
152
214
|
|
|
153
215
|
@combomethod
|
|
154
216
|
def process_receipt(
|
|
155
217
|
self, txn_receipt: TxReceipt, errors: EventLogErrorFlags = WARN
|
|
156
218
|
) -> Iterable[EventData]:
|
|
157
|
-
return self._parse_logs(txn_receipt, errors)
|
|
219
|
+
return self._parse_logs(txn_receipt=txn_receipt, errors=errors)
|
|
158
220
|
|
|
221
|
+
@combomethod
|
|
159
222
|
@to_tuple
|
|
160
223
|
def _parse_logs(
|
|
161
224
|
self, txn_receipt: TxReceipt, errors: EventLogErrorFlags
|
|
@@ -163,14 +226,20 @@ class BaseContractEvent:
|
|
|
163
226
|
try:
|
|
164
227
|
errors.name
|
|
165
228
|
except AttributeError:
|
|
166
|
-
raise
|
|
229
|
+
raise Web3AttributeError(
|
|
167
230
|
f"Error flag must be one of: {EventLogErrorFlags.flag_options()}"
|
|
168
231
|
)
|
|
169
232
|
|
|
170
233
|
for log in txn_receipt["logs"]:
|
|
171
234
|
try:
|
|
172
235
|
rich_log = get_event_data(self.w3.codec, self.abi, log)
|
|
173
|
-
except (
|
|
236
|
+
except (
|
|
237
|
+
MismatchedABI,
|
|
238
|
+
LogTopicError,
|
|
239
|
+
InvalidEventABI,
|
|
240
|
+
TypeError,
|
|
241
|
+
InsufficientDataBytes,
|
|
242
|
+
) as e:
|
|
174
243
|
if errors == DISCARD:
|
|
175
244
|
continue
|
|
176
245
|
elif errors == IGNORE:
|
|
@@ -185,13 +254,14 @@ class BaseContractEvent:
|
|
|
185
254
|
f"The log with transaction hash: {log['transactionHash']!r} "
|
|
186
255
|
f"and logIndex: {log['logIndex']} encountered the following "
|
|
187
256
|
f"error during processing: {type(e).__name__}({e}). It has "
|
|
188
|
-
"been discarded."
|
|
257
|
+
"been discarded.",
|
|
258
|
+
stacklevel=2,
|
|
189
259
|
)
|
|
190
260
|
continue
|
|
191
261
|
yield rich_log
|
|
192
262
|
|
|
193
263
|
@combomethod
|
|
194
|
-
def process_log(self, log:
|
|
264
|
+
def process_log(self, log: LogReceipt) -> EventData:
|
|
195
265
|
return get_event_data(self.w3.codec, self.abi, log)
|
|
196
266
|
|
|
197
267
|
@combomethod
|
|
@@ -199,12 +269,12 @@ class BaseContractEvent:
|
|
|
199
269
|
self,
|
|
200
270
|
abi: ABIEvent,
|
|
201
271
|
argument_filters: Optional[Dict[str, Any]] = None,
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
272
|
+
from_block: Optional[BlockIdentifier] = None,
|
|
273
|
+
to_block: Optional[BlockIdentifier] = None,
|
|
274
|
+
block_hash: Optional[HexBytes] = None,
|
|
205
275
|
) -> FilterParams:
|
|
206
276
|
if not self.address:
|
|
207
|
-
raise
|
|
277
|
+
raise Web3TypeError(
|
|
208
278
|
"This method can be only called on "
|
|
209
279
|
"an instated contract with an address"
|
|
210
280
|
)
|
|
@@ -214,11 +284,12 @@ class BaseContractEvent:
|
|
|
214
284
|
|
|
215
285
|
_filters = dict(**argument_filters)
|
|
216
286
|
|
|
217
|
-
blkhash_set =
|
|
218
|
-
blknum_set =
|
|
287
|
+
blkhash_set = block_hash is not None
|
|
288
|
+
blknum_set = from_block is not None or to_block is not None
|
|
219
289
|
if blkhash_set and blknum_set:
|
|
220
290
|
raise Web3ValidationError(
|
|
221
|
-
"
|
|
291
|
+
"`block_hash` cannot be set at the same time as "
|
|
292
|
+
"`from_block` or `to_block`"
|
|
222
293
|
)
|
|
223
294
|
|
|
224
295
|
# Construct JSON-RPC raw filter presentation based on human readable
|
|
@@ -228,19 +299,21 @@ class BaseContractEvent:
|
|
|
228
299
|
self.w3.codec,
|
|
229
300
|
contract_address=self.address,
|
|
230
301
|
argument_filters=_filters,
|
|
231
|
-
|
|
232
|
-
|
|
302
|
+
from_block=from_block,
|
|
303
|
+
to_block=to_block,
|
|
233
304
|
address=self.address,
|
|
234
305
|
)
|
|
235
306
|
|
|
236
|
-
if
|
|
237
|
-
event_filter_params["blockHash"] =
|
|
307
|
+
if block_hash is not None:
|
|
308
|
+
event_filter_params["blockHash"] = block_hash
|
|
238
309
|
|
|
239
310
|
return event_filter_params
|
|
240
311
|
|
|
241
312
|
@classmethod
|
|
242
|
-
def factory(
|
|
243
|
-
|
|
313
|
+
def factory(
|
|
314
|
+
cls, class_name: str, **kwargs: Any
|
|
315
|
+
) -> Union["ContractEvent", "AsyncContractEvent"]:
|
|
316
|
+
return PropertyCheckingFactory(class_name, (cls,), kwargs)()
|
|
244
317
|
|
|
245
318
|
@staticmethod
|
|
246
319
|
def check_for_forbidden_api_filter_arguments(
|
|
@@ -251,12 +324,12 @@ class BaseContractEvent:
|
|
|
251
324
|
for filter_name, filter_value in _filters.items():
|
|
252
325
|
_input = name_indexed_inputs[filter_name]
|
|
253
326
|
if is_array_type(_input["type"]):
|
|
254
|
-
raise
|
|
327
|
+
raise Web3TypeError(
|
|
255
328
|
"createFilter no longer supports array type filter arguments. "
|
|
256
329
|
"see the build_filter method for filtering array type filters."
|
|
257
330
|
)
|
|
258
331
|
if is_list_like(filter_value) and is_dynamic_sized_type(_input["type"]):
|
|
259
|
-
raise
|
|
332
|
+
raise Web3TypeError(
|
|
260
333
|
"createFilter no longer supports setting filter argument options "
|
|
261
334
|
"for dynamic sized types. See the build_filter method for setting "
|
|
262
335
|
"filters with the match_any method."
|
|
@@ -314,15 +387,15 @@ class BaseContractEvent:
|
|
|
314
387
|
def _set_up_filter_builder(
|
|
315
388
|
self,
|
|
316
389
|
argument_filters: Optional[Dict[str, Any]] = None,
|
|
317
|
-
|
|
318
|
-
|
|
390
|
+
from_block: Optional[BlockIdentifier] = None,
|
|
391
|
+
to_block: BlockIdentifier = "latest",
|
|
319
392
|
address: Optional[ChecksumAddress] = None,
|
|
320
393
|
topics: Optional[Sequence[Any]] = None,
|
|
321
394
|
filter_builder: Union[EventFilterBuilder, AsyncEventFilterBuilder] = None,
|
|
322
395
|
) -> None:
|
|
323
|
-
if
|
|
324
|
-
raise
|
|
325
|
-
"Missing mandatory keyword argument to create_filter:
|
|
396
|
+
if from_block is None:
|
|
397
|
+
raise Web3TypeError(
|
|
398
|
+
"Missing mandatory keyword argument to create_filter: `from_block`"
|
|
326
399
|
)
|
|
327
400
|
|
|
328
401
|
if argument_filters is None:
|
|
@@ -330,17 +403,15 @@ class BaseContractEvent:
|
|
|
330
403
|
|
|
331
404
|
_filters = dict(**argument_filters)
|
|
332
405
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
self.check_for_forbidden_api_filter_arguments(event_abi, _filters)
|
|
406
|
+
self.check_for_forbidden_api_filter_arguments(self.abi, _filters)
|
|
336
407
|
|
|
337
408
|
_, event_filter_params = construct_event_filter_params(
|
|
338
|
-
self.
|
|
409
|
+
self.abi,
|
|
339
410
|
self.w3.codec,
|
|
340
411
|
contract_address=self.address,
|
|
341
412
|
argument_filters=_filters,
|
|
342
|
-
|
|
343
|
-
|
|
413
|
+
from_block=from_block,
|
|
414
|
+
to_block=to_block,
|
|
344
415
|
address=address,
|
|
345
416
|
topics=topics,
|
|
346
417
|
)
|
|
@@ -348,8 +419,8 @@ class BaseContractEvent:
|
|
|
348
419
|
filter_builder.address = cast(
|
|
349
420
|
ChecksumAddress, event_filter_params.get("address")
|
|
350
421
|
)
|
|
351
|
-
filter_builder.
|
|
352
|
-
filter_builder.
|
|
422
|
+
filter_builder.from_block = event_filter_params.get("fromBlock")
|
|
423
|
+
filter_builder.to_block = event_filter_params.get("toBlock")
|
|
353
424
|
match_any_vals = {
|
|
354
425
|
arg: value
|
|
355
426
|
for arg, value in _filters.items()
|
|
@@ -370,7 +441,8 @@ class BaseContractEvent:
|
|
|
370
441
|
|
|
371
442
|
|
|
372
443
|
class BaseContractEvents:
|
|
373
|
-
"""
|
|
444
|
+
"""
|
|
445
|
+
Class containing contract event objects
|
|
374
446
|
|
|
375
447
|
This is available via:
|
|
376
448
|
|
|
@@ -394,99 +466,128 @@ class BaseContractEvents:
|
|
|
394
466
|
self,
|
|
395
467
|
abi: ABI,
|
|
396
468
|
w3: Union["Web3", "AsyncWeb3"],
|
|
397
|
-
contract_event_type: Type["
|
|
469
|
+
contract_event_type: Union[Type["ContractEvent"], Type["AsyncContractEvent"]],
|
|
398
470
|
address: Optional[ChecksumAddress] = None,
|
|
399
471
|
) -> None:
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
setattr(
|
|
405
|
-
self,
|
|
406
|
-
event["name"],
|
|
407
|
-
contract_event_type.factory(
|
|
408
|
-
event["name"],
|
|
409
|
-
w3=w3,
|
|
410
|
-
contract_abi=self.abi,
|
|
411
|
-
address=address,
|
|
412
|
-
event_name=event["name"],
|
|
413
|
-
),
|
|
414
|
-
)
|
|
472
|
+
self.abi = abi
|
|
473
|
+
self.w3 = w3
|
|
474
|
+
self.address = address
|
|
475
|
+
_events: Sequence[ABIEvent] = None
|
|
415
476
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
"Are you sure you provided the correct contract abi?",
|
|
421
|
-
)
|
|
422
|
-
elif event_name not in self.__dict__["_events"]:
|
|
423
|
-
raise ABIEventFunctionNotFound(
|
|
424
|
-
f"The event '{event_name}' was not found in this contract's abi. ",
|
|
425
|
-
"Are you sure you provided the correct contract abi?",
|
|
477
|
+
if self.abi:
|
|
478
|
+
_events = sorted(
|
|
479
|
+
filter_abi_by_type("event", self.abi),
|
|
480
|
+
key=lambda evt: (evt["name"], len(evt.get("inputs", []))),
|
|
426
481
|
)
|
|
427
|
-
|
|
428
|
-
|
|
482
|
+
for event in _events:
|
|
483
|
+
abi_signature = abi_to_signature(event)
|
|
484
|
+
event_factory = contract_event_type.factory(
|
|
485
|
+
abi_signature,
|
|
486
|
+
w3=self.w3,
|
|
487
|
+
contract_abi=self.abi,
|
|
488
|
+
address=self.address,
|
|
489
|
+
abi=event,
|
|
490
|
+
)
|
|
429
491
|
|
|
430
|
-
|
|
431
|
-
|
|
492
|
+
# Set event name on instance if it does not already exist
|
|
493
|
+
if event["name"] not in self.__dict__:
|
|
494
|
+
setattr(self, event["name"], event_factory)
|
|
432
495
|
|
|
433
|
-
|
|
434
|
-
|
|
496
|
+
# Set underscore prefixed event signature on instance
|
|
497
|
+
# Handles ambiguity in overloaded contract events
|
|
498
|
+
setattr(self, f"_{abi_signature}", event_factory)
|
|
435
499
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
for event in self._events:
|
|
439
|
-
yield self[event["name"]]
|
|
500
|
+
if _events:
|
|
501
|
+
self._events = _events
|
|
440
502
|
|
|
441
503
|
def __hasattr__(self, event_name: str) -> bool:
|
|
442
504
|
try:
|
|
443
505
|
return event_name in self.__dict__["_events"]
|
|
444
|
-
except
|
|
506
|
+
except ABIEventNotFound:
|
|
445
507
|
return False
|
|
446
508
|
|
|
447
509
|
|
|
448
510
|
class BaseContractFunction:
|
|
449
|
-
"""
|
|
511
|
+
"""
|
|
512
|
+
Base class for contract functions
|
|
450
513
|
|
|
451
514
|
A function accessed via the api `contract.functions.myMethod(*args, **kwargs)`
|
|
452
515
|
is a subclass of this class.
|
|
453
516
|
"""
|
|
454
517
|
|
|
455
518
|
address: ChecksumAddress = None
|
|
456
|
-
|
|
519
|
+
fn_name: str = None
|
|
520
|
+
name: str = None
|
|
521
|
+
signature: str = None
|
|
522
|
+
abi_element_identifier: ABIElementIdentifier = None
|
|
457
523
|
w3: Union["Web3", "AsyncWeb3"] = None
|
|
458
524
|
contract_abi: ABI = None
|
|
459
525
|
abi: ABIFunction = None
|
|
460
526
|
transaction: TxParams = None
|
|
461
527
|
arguments: Tuple[Any, ...] = None
|
|
462
|
-
decode_tuples: Optional[bool] =
|
|
528
|
+
decode_tuples: Optional[bool] = None
|
|
529
|
+
argument_names: Tuple[str, ...] = tuple()
|
|
530
|
+
argument_types: Tuple[str, ...] = tuple()
|
|
463
531
|
args: Any = None
|
|
464
532
|
kwargs: Any = None
|
|
465
533
|
|
|
466
534
|
def __init__(self, abi: Optional[ABIFunction] = None) -> None:
|
|
467
|
-
self.
|
|
468
|
-
|
|
535
|
+
if not self.abi_element_identifier:
|
|
536
|
+
self.abi_element_identifier = type(self).__name__
|
|
469
537
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
538
|
+
self.name = get_name_from_abi_element_identifier(self.abi_element_identifier)
|
|
539
|
+
self.fn_name = self.name
|
|
540
|
+
|
|
541
|
+
if abi:
|
|
542
|
+
self.abi = abi
|
|
543
|
+
|
|
544
|
+
self.signature = abi_to_signature(self.abi)
|
|
545
|
+
|
|
546
|
+
event_inputs = self.abi.get("inputs", [])
|
|
547
|
+
self.argument_names = tuple([input.get("name", None) for input in event_inputs])
|
|
548
|
+
self.argument_types = tuple([input["type"] for input in event_inputs])
|
|
549
|
+
|
|
550
|
+
@combomethod
|
|
551
|
+
def _get_abi(cls) -> ABIFunction:
|
|
552
|
+
if not cls.args and not cls.kwargs:
|
|
553
|
+
# If no args or kwargs are provided, get the ABI element by name
|
|
554
|
+
return cast(
|
|
555
|
+
ABIFunction,
|
|
556
|
+
get_abi_element(
|
|
557
|
+
cls.contract_abi,
|
|
558
|
+
get_abi_element_signature(cls.abi_element_identifier),
|
|
559
|
+
abi_codec=cls.w3.codec,
|
|
560
|
+
),
|
|
478
561
|
)
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
562
|
+
|
|
563
|
+
return cast(
|
|
564
|
+
ABIFunction,
|
|
565
|
+
get_abi_element(
|
|
566
|
+
cls.contract_abi,
|
|
567
|
+
get_name_from_abi_element_identifier(cls.abi_element_identifier),
|
|
568
|
+
*cls.args,
|
|
569
|
+
abi_codec=cls.w3.codec,
|
|
570
|
+
**cls.kwargs,
|
|
571
|
+
),
|
|
572
|
+
)
|
|
573
|
+
|
|
574
|
+
def _set_function_info(self) -> None:
|
|
575
|
+
self.selector = encode_hex(b"")
|
|
576
|
+
if self.abi_element_identifier in [
|
|
577
|
+
"fallback",
|
|
578
|
+
"receive",
|
|
579
|
+
FallbackFn,
|
|
580
|
+
ReceiveFn,
|
|
581
|
+
]:
|
|
582
|
+
self.selector = encode_hex(function_abi_to_4byte_selector(self.abi))
|
|
583
|
+
self.arguments = None
|
|
584
|
+
elif is_text(self.abi_element_identifier):
|
|
585
|
+
self.selector = encode_hex(function_abi_to_4byte_selector(self.abi))
|
|
586
|
+
self.arguments = get_normalized_abi_inputs(
|
|
587
|
+
self.abi, *self.args, **self.kwargs
|
|
485
588
|
)
|
|
486
589
|
else:
|
|
487
|
-
raise
|
|
488
|
-
|
|
489
|
-
self.arguments = merge_args_and_kwargs(self.abi, self.args, self.kwargs)
|
|
590
|
+
raise Web3TypeError("Unsupported function identifier")
|
|
490
591
|
|
|
491
592
|
def _get_call_txparams(self, transaction: Optional[TxParams] = None) -> TxParams:
|
|
492
593
|
if transaction is None:
|
|
@@ -495,26 +596,25 @@ class BaseContractFunction:
|
|
|
495
596
|
call_transaction = cast(TxParams, dict(**transaction))
|
|
496
597
|
|
|
497
598
|
if "data" in call_transaction:
|
|
498
|
-
raise
|
|
599
|
+
raise Web3ValueError("Cannot set 'data' field in call transaction")
|
|
499
600
|
|
|
500
601
|
if self.address:
|
|
501
602
|
call_transaction.setdefault("to", self.address)
|
|
502
603
|
if self.w3.eth.default_account is not empty:
|
|
503
|
-
# type ignored b/c check prevents an empty default_account
|
|
504
604
|
call_transaction.setdefault(
|
|
505
605
|
"from",
|
|
506
|
-
self.w3.eth.default_account,
|
|
606
|
+
cast(ChecksumAddress, self.w3.eth.default_account),
|
|
507
607
|
)
|
|
508
608
|
|
|
509
609
|
if "to" not in call_transaction:
|
|
510
610
|
if isinstance(self, type):
|
|
511
|
-
raise
|
|
611
|
+
raise Web3ValueError(
|
|
512
612
|
"When using `Contract.[methodtype].[method].call()` from"
|
|
513
613
|
" a contract factory you "
|
|
514
614
|
"must provide a `to` address with the transaction"
|
|
515
615
|
)
|
|
516
616
|
else:
|
|
517
|
-
raise
|
|
617
|
+
raise Web3ValueError(
|
|
518
618
|
"Please ensure that this contract instance has an address."
|
|
519
619
|
)
|
|
520
620
|
|
|
@@ -527,24 +627,23 @@ class BaseContractFunction:
|
|
|
527
627
|
transact_transaction = cast(TxParams, dict(**transaction))
|
|
528
628
|
|
|
529
629
|
if "data" in transact_transaction:
|
|
530
|
-
raise
|
|
630
|
+
raise Web3ValueError("Cannot set 'data' field in transact transaction")
|
|
531
631
|
|
|
532
632
|
if self.address is not None:
|
|
533
633
|
transact_transaction.setdefault("to", self.address)
|
|
534
634
|
if self.w3.eth.default_account is not empty:
|
|
535
|
-
# type ignored b/c check prevents an empty default_account
|
|
536
635
|
transact_transaction.setdefault(
|
|
537
|
-
"from", self.w3.eth.default_account
|
|
636
|
+
"from", cast(ChecksumAddress, self.w3.eth.default_account)
|
|
538
637
|
)
|
|
539
638
|
|
|
540
639
|
if "to" not in transact_transaction:
|
|
541
640
|
if isinstance(self, type):
|
|
542
|
-
raise
|
|
641
|
+
raise Web3ValueError(
|
|
543
642
|
"When using `Contract.transact` from a contract factory you "
|
|
544
643
|
"must provide a `to` address with the transaction"
|
|
545
644
|
)
|
|
546
645
|
else:
|
|
547
|
-
raise
|
|
646
|
+
raise Web3ValueError(
|
|
548
647
|
"Please ensure that this contract instance has an address."
|
|
549
648
|
)
|
|
550
649
|
return transact_transaction
|
|
@@ -556,26 +655,25 @@ class BaseContractFunction:
|
|
|
556
655
|
estimate_gas_transaction = cast(TxParams, dict(**transaction))
|
|
557
656
|
|
|
558
657
|
if "data" in estimate_gas_transaction:
|
|
559
|
-
raise
|
|
658
|
+
raise Web3ValueError("Cannot set 'data' field in estimate_gas transaction")
|
|
560
659
|
if "to" in estimate_gas_transaction:
|
|
561
|
-
raise
|
|
660
|
+
raise Web3ValueError("Cannot set to in estimate_gas transaction")
|
|
562
661
|
|
|
563
662
|
if self.address:
|
|
564
663
|
estimate_gas_transaction.setdefault("to", self.address)
|
|
565
664
|
if self.w3.eth.default_account is not empty:
|
|
566
|
-
# type ignored b/c check prevents an empty default_account
|
|
567
665
|
estimate_gas_transaction.setdefault(
|
|
568
|
-
"from", self.w3.eth.default_account
|
|
666
|
+
"from", cast(ChecksumAddress, self.w3.eth.default_account)
|
|
569
667
|
)
|
|
570
668
|
|
|
571
669
|
if "to" not in estimate_gas_transaction:
|
|
572
670
|
if isinstance(self, type):
|
|
573
|
-
raise
|
|
671
|
+
raise Web3ValueError(
|
|
574
672
|
"When using `Contract.estimate_gas` from a contract factory "
|
|
575
673
|
"you must provide a `to` address with the transaction"
|
|
576
674
|
)
|
|
577
675
|
else:
|
|
578
|
-
raise
|
|
676
|
+
raise Web3ValueError(
|
|
579
677
|
"Please ensure that this contract instance has an address."
|
|
580
678
|
)
|
|
581
679
|
return estimate_gas_transaction
|
|
@@ -587,21 +685,23 @@ class BaseContractFunction:
|
|
|
587
685
|
built_transaction = cast(TxParams, dict(**transaction))
|
|
588
686
|
|
|
589
687
|
if "data" in built_transaction:
|
|
590
|
-
raise
|
|
688
|
+
raise Web3ValueError("Cannot set 'data' field in build transaction")
|
|
591
689
|
|
|
592
690
|
if not self.address and "to" not in built_transaction:
|
|
593
|
-
raise
|
|
691
|
+
raise Web3ValueError(
|
|
594
692
|
"When using `ContractFunction.build_transaction` from a contract "
|
|
595
693
|
"factory you must provide a `to` address with the transaction"
|
|
596
694
|
)
|
|
597
695
|
if self.address and "to" in built_transaction:
|
|
598
|
-
raise
|
|
696
|
+
raise Web3ValueError(
|
|
697
|
+
"Cannot set 'to' field in contract call build transaction"
|
|
698
|
+
)
|
|
599
699
|
|
|
600
700
|
if self.address:
|
|
601
701
|
built_transaction.setdefault("to", self.address)
|
|
602
702
|
|
|
603
703
|
if "to" not in built_transaction:
|
|
604
|
-
raise
|
|
704
|
+
raise Web3ValueError(
|
|
605
705
|
"Please ensure that this contract instance has an address."
|
|
606
706
|
)
|
|
607
707
|
|
|
@@ -619,18 +719,20 @@ class BaseContractFunction:
|
|
|
619
719
|
if self.arguments is not None:
|
|
620
720
|
_repr += f" bound to {self.arguments!r}"
|
|
621
721
|
return _repr + ">"
|
|
622
|
-
return f"<Function {self.
|
|
722
|
+
return f"<Function {get_abi_element_signature(self.abi_element_identifier)}>"
|
|
623
723
|
|
|
624
724
|
@classmethod
|
|
625
725
|
def factory(
|
|
626
726
|
cls, class_name: str, **kwargs: Any
|
|
627
727
|
) -> Union["ContractFunction", "AsyncContractFunction"]:
|
|
628
|
-
return PropertyCheckingFactory(class_name, (cls,), kwargs)(
|
|
728
|
+
return PropertyCheckingFactory(class_name, (cls,), kwargs)()
|
|
629
729
|
|
|
630
730
|
|
|
631
731
|
class BaseContractFunctions:
|
|
632
732
|
"""Class containing contract function objects"""
|
|
633
733
|
|
|
734
|
+
_functions: Sequence[ABIFunction] = None
|
|
735
|
+
|
|
634
736
|
def __init__(
|
|
635
737
|
self,
|
|
636
738
|
abi: ABI,
|
|
@@ -644,32 +746,38 @@ class BaseContractFunctions:
|
|
|
644
746
|
self.abi = abi
|
|
645
747
|
self.w3 = w3
|
|
646
748
|
self.address = address
|
|
749
|
+
_functions: Sequence[ABIFunction] = None
|
|
647
750
|
|
|
648
751
|
if self.abi:
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
752
|
+
# Function with least number of inputs is first
|
|
753
|
+
# This ensures ambiguity will always be deterministic
|
|
754
|
+
# Prefer function without arguments if present, otherwise
|
|
755
|
+
# just use the first available
|
|
756
|
+
_functions = sorted(
|
|
757
|
+
filter_abi_by_type("function", self.abi),
|
|
758
|
+
key=lambda fn: (fn["name"], len(fn.get("inputs", []))),
|
|
759
|
+
)
|
|
760
|
+
for func in _functions:
|
|
761
|
+
abi_signature = abi_to_signature(func)
|
|
762
|
+
function_factory = contract_function_class.factory(
|
|
763
|
+
abi_signature,
|
|
764
|
+
w3=self.w3,
|
|
765
|
+
contract_abi=self.abi,
|
|
766
|
+
address=self.address,
|
|
767
|
+
decode_tuples=decode_tuples,
|
|
768
|
+
abi=func,
|
|
662
769
|
)
|
|
663
770
|
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
771
|
+
# Set function name on instance if it does not already exist
|
|
772
|
+
if func["name"] not in self.__dict__:
|
|
773
|
+
setattr(self, func["name"], function_factory)
|
|
667
774
|
|
|
668
|
-
|
|
669
|
-
|
|
775
|
+
# Set function signature on instance
|
|
776
|
+
# Handles ambiguity in overloaded contract functions
|
|
777
|
+
setattr(self, f"_{abi_signature}", function_factory)
|
|
670
778
|
|
|
671
|
-
|
|
672
|
-
|
|
779
|
+
if _functions:
|
|
780
|
+
self._functions = _functions
|
|
673
781
|
|
|
674
782
|
def __hasattr__(self, function_name: str) -> bool:
|
|
675
783
|
try:
|
|
@@ -679,7 +787,8 @@ class BaseContractFunctions:
|
|
|
679
787
|
|
|
680
788
|
|
|
681
789
|
class BaseContract:
|
|
682
|
-
"""
|
|
790
|
+
"""
|
|
791
|
+
Base class for Contract proxy classes.
|
|
683
792
|
|
|
684
793
|
First you need to create your Contract classes using
|
|
685
794
|
:meth:`web3.eth.Eth.contract` that takes compiled Solidity contract
|
|
@@ -723,44 +832,58 @@ class BaseContract:
|
|
|
723
832
|
# Public API
|
|
724
833
|
#
|
|
725
834
|
@combomethod
|
|
726
|
-
def
|
|
835
|
+
def encode_abi(
|
|
727
836
|
cls,
|
|
728
|
-
|
|
837
|
+
abi_element_identifier: str,
|
|
729
838
|
args: Optional[Any] = None,
|
|
730
839
|
kwargs: Optional[Any] = None,
|
|
731
840
|
data: Optional[HexStr] = None,
|
|
732
841
|
) -> HexStr:
|
|
733
842
|
"""
|
|
734
843
|
Encodes the arguments using the Ethereum ABI for the contract function
|
|
735
|
-
that matches the given name and arguments
|
|
844
|
+
that matches the given name and arguments.
|
|
736
845
|
|
|
737
846
|
:param data: defaults to function selector
|
|
738
847
|
"""
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
848
|
+
args = args or tuple()
|
|
849
|
+
kwargs = kwargs or {}
|
|
850
|
+
|
|
851
|
+
element_info = get_abi_element_info(
|
|
852
|
+
cls.abi,
|
|
853
|
+
abi_element_identifier,
|
|
854
|
+
*args,
|
|
855
|
+
abi_codec=cls.w3.codec,
|
|
856
|
+
**kwargs,
|
|
745
857
|
)
|
|
746
858
|
|
|
747
859
|
if data is None:
|
|
748
|
-
data =
|
|
860
|
+
data = element_info["selector"]
|
|
749
861
|
|
|
750
|
-
return encode_abi(cls.w3,
|
|
862
|
+
return encode_abi(cls.w3, element_info["abi"], element_info["arguments"], data)
|
|
751
863
|
|
|
864
|
+
#
|
|
865
|
+
# Functions API
|
|
866
|
+
#
|
|
752
867
|
@combomethod
|
|
753
868
|
def all_functions(
|
|
754
869
|
self,
|
|
755
|
-
) -> "BaseContractFunction":
|
|
870
|
+
) -> List["BaseContractFunction"]:
|
|
871
|
+
"""
|
|
872
|
+
Return all functions in the contract.
|
|
873
|
+
"""
|
|
756
874
|
return self.find_functions_by_identifier(
|
|
757
875
|
self.abi, self.w3, self.address, lambda _: True
|
|
758
876
|
)
|
|
759
877
|
|
|
760
878
|
@combomethod
|
|
761
879
|
def get_function_by_signature(self, signature: str) -> "BaseContractFunction":
|
|
880
|
+
"""
|
|
881
|
+
Return a distinct function with matching signature.
|
|
882
|
+
Raises a Web3ValueError if the signature is invalid or if there is no match or
|
|
883
|
+
more than one is found.
|
|
884
|
+
"""
|
|
762
885
|
if " " in signature:
|
|
763
|
-
raise
|
|
886
|
+
raise Web3ValueError(
|
|
764
887
|
"Function signature should not contain any spaces. "
|
|
765
888
|
f"Found spaces in input: {signature}"
|
|
766
889
|
)
|
|
@@ -774,7 +897,12 @@ class BaseContract:
|
|
|
774
897
|
return self.get_function_by_identifier(fns, "signature")
|
|
775
898
|
|
|
776
899
|
@combomethod
|
|
777
|
-
def find_functions_by_name(self, fn_name: str) -> "BaseContractFunction":
|
|
900
|
+
def find_functions_by_name(self, fn_name: str) -> List["BaseContractFunction"]:
|
|
901
|
+
"""
|
|
902
|
+
Return all functions with matching name.
|
|
903
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
904
|
+
"""
|
|
905
|
+
|
|
778
906
|
def callable_check(fn_abi: ABIFunction) -> bool:
|
|
779
907
|
return fn_abi["name"] == fn_name
|
|
780
908
|
|
|
@@ -784,6 +912,10 @@ class BaseContract:
|
|
|
784
912
|
|
|
785
913
|
@combomethod
|
|
786
914
|
def get_function_by_name(self, fn_name: str) -> "BaseContractFunction":
|
|
915
|
+
"""
|
|
916
|
+
Return a distinct function with matching name.
|
|
917
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
918
|
+
"""
|
|
787
919
|
fns = self.find_functions_by_name(fn_name)
|
|
788
920
|
return self.get_function_by_identifier(fns, "name")
|
|
789
921
|
|
|
@@ -791,10 +923,15 @@ class BaseContract:
|
|
|
791
923
|
def get_function_by_selector(
|
|
792
924
|
self, selector: Union[bytes, int, HexStr]
|
|
793
925
|
) -> "BaseContractFunction":
|
|
926
|
+
"""
|
|
927
|
+
Return a distinct function with matching 4byte selector.
|
|
928
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
929
|
+
"""
|
|
930
|
+
|
|
794
931
|
def callable_check(fn_abi: ABIFunction) -> bool:
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
932
|
+
return encode_hex(function_abi_to_4byte_selector(fn_abi)) == to_4byte_hex(
|
|
933
|
+
selector
|
|
934
|
+
)
|
|
798
935
|
|
|
799
936
|
fns = self.find_functions_by_identifier(
|
|
800
937
|
self.abi, self.w3, self.address, callable_check
|
|
@@ -805,9 +942,10 @@ class BaseContract:
|
|
|
805
942
|
def decode_function_input(
|
|
806
943
|
self, data: HexStr
|
|
807
944
|
) -> Tuple["BaseContractFunction", Dict[str, Any]]:
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
945
|
+
"""
|
|
946
|
+
Return a Tuple of the function selector and decoded arguments.
|
|
947
|
+
"""
|
|
948
|
+
func = self.get_function_by_selector(HexBytes(data)[:4])
|
|
811
949
|
arguments = decode_transaction_data(
|
|
812
950
|
func.abi, data, normalizers=BASE_RETURN_NORMALIZERS
|
|
813
951
|
)
|
|
@@ -815,9 +953,17 @@ class BaseContract:
|
|
|
815
953
|
|
|
816
954
|
@combomethod
|
|
817
955
|
def find_functions_by_args(self, *args: Any) -> "BaseContractFunction":
|
|
956
|
+
"""
|
|
957
|
+
Return all functions with matching args, checking each argument can be encoded
|
|
958
|
+
with the type.
|
|
959
|
+
"""
|
|
960
|
+
|
|
818
961
|
def callable_check(fn_abi: ABIFunction) -> bool:
|
|
819
962
|
return check_if_arguments_can_be_encoded(
|
|
820
|
-
fn_abi,
|
|
963
|
+
fn_abi,
|
|
964
|
+
*args,
|
|
965
|
+
abi_codec=self.w3.codec,
|
|
966
|
+
**{},
|
|
821
967
|
)
|
|
822
968
|
|
|
823
969
|
return self.find_functions_by_identifier(
|
|
@@ -826,78 +972,119 @@ class BaseContract:
|
|
|
826
972
|
|
|
827
973
|
@combomethod
|
|
828
974
|
def get_function_by_args(self, *args: Any) -> "BaseContractFunction":
|
|
975
|
+
"""
|
|
976
|
+
Return a distinct function with matching args, checking each argument can be
|
|
977
|
+
encoded with the type.
|
|
978
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
979
|
+
"""
|
|
829
980
|
fns = self.find_functions_by_args(*args)
|
|
830
981
|
return self.get_function_by_identifier(fns, "args")
|
|
831
982
|
|
|
832
983
|
#
|
|
833
|
-
#
|
|
984
|
+
# Events API
|
|
834
985
|
#
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
fn_kwargs: Optional[Any] = None,
|
|
843
|
-
transaction: Optional[TxParams] = None,
|
|
844
|
-
) -> TxParams:
|
|
845
|
-
return prepare_transaction(
|
|
846
|
-
cls.address,
|
|
847
|
-
cls.w3,
|
|
848
|
-
fn_identifier=fn_name,
|
|
849
|
-
contract_abi=cls.abi,
|
|
850
|
-
transaction=transaction,
|
|
851
|
-
fn_args=fn_args,
|
|
852
|
-
fn_kwargs=fn_kwargs,
|
|
986
|
+
@combomethod
|
|
987
|
+
def all_events(self) -> List["BaseContractEvent"]:
|
|
988
|
+
"""
|
|
989
|
+
Return all events in the contract.
|
|
990
|
+
"""
|
|
991
|
+
return self.find_events_by_identifier(
|
|
992
|
+
self.abi, self.w3, self.address, lambda _: True
|
|
853
993
|
)
|
|
854
994
|
|
|
855
|
-
@
|
|
856
|
-
def
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
995
|
+
@combomethod
|
|
996
|
+
def get_event_by_signature(self, signature: str) -> "BaseContractEvent":
|
|
997
|
+
"""
|
|
998
|
+
Return a distinct event with matching signature.
|
|
999
|
+
Raises a Web3ValueError if the signature is invalid or if there is no match or
|
|
1000
|
+
more than one is found.
|
|
1001
|
+
"""
|
|
1002
|
+
|
|
1003
|
+
def callable_check(event_abi: ABIEvent) -> bool:
|
|
1004
|
+
return abi_to_signature(event_abi) == signature.replace(" ", "")
|
|
1005
|
+
|
|
1006
|
+
events = self.find_events_by_identifier(
|
|
1007
|
+
self.abi, self.w3, self.address, callable_check
|
|
864
1008
|
)
|
|
1009
|
+
return self.get_event_by_identifier(events, "signature")
|
|
865
1010
|
|
|
866
|
-
@
|
|
867
|
-
def
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
1011
|
+
@combomethod
|
|
1012
|
+
def find_events_by_name(self, event_name: str) -> List["BaseContractEvent"]:
|
|
1013
|
+
"""
|
|
1014
|
+
Return all events with matching name.
|
|
1015
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
1016
|
+
"""
|
|
1017
|
+
|
|
1018
|
+
def callable_check(fn_abi: ABIFunction) -> bool:
|
|
1019
|
+
return fn_abi["name"] == event_name
|
|
1020
|
+
|
|
1021
|
+
return self.find_events_by_identifier(
|
|
1022
|
+
self.abi, self.w3, self.address, callable_check
|
|
874
1023
|
)
|
|
875
1024
|
|
|
876
1025
|
@combomethod
|
|
877
|
-
def
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
1026
|
+
def get_event_by_name(self, event_name: str) -> "BaseContractEvent":
|
|
1027
|
+
"""
|
|
1028
|
+
Return a distinct event with matching name.
|
|
1029
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
1030
|
+
"""
|
|
1031
|
+
events = self.find_events_by_name(event_name)
|
|
1032
|
+
return self.get_event_by_identifier(events, "name")
|
|
881
1033
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
1034
|
+
@combomethod
|
|
1035
|
+
def find_events_by_selector(
|
|
1036
|
+
self, selector: Union[bytes, int, HexStr]
|
|
1037
|
+
) -> List["BaseContractEvent"]:
|
|
1038
|
+
"""
|
|
1039
|
+
Return all events with matching selector.
|
|
1040
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
1041
|
+
"""
|
|
887
1042
|
|
|
888
|
-
|
|
1043
|
+
def callable_check(event_abi: ABIEvent) -> bool:
|
|
1044
|
+
return encode_hex(
|
|
1045
|
+
keccak(text=abi_to_signature(event_abi).replace(" ", ""))
|
|
1046
|
+
) == encode_hex(hexstr_if_str(to_bytes, selector))
|
|
889
1047
|
|
|
890
|
-
|
|
891
|
-
|
|
1048
|
+
return self.find_events_by_identifier(
|
|
1049
|
+
self.abi, self.w3, self.address, callable_check
|
|
1050
|
+
)
|
|
1051
|
+
|
|
1052
|
+
@combomethod
|
|
1053
|
+
def get_event_by_selector(
|
|
1054
|
+
self, selector: Union[bytes, int, HexStr]
|
|
1055
|
+
) -> "BaseContractEvent":
|
|
1056
|
+
"""
|
|
1057
|
+
Return a distinct event with matching keccak selector.
|
|
1058
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
1059
|
+
"""
|
|
1060
|
+
events = self.find_events_by_selector(selector)
|
|
1061
|
+
return self.get_event_by_identifier(events, "selector")
|
|
1062
|
+
|
|
1063
|
+
@combomethod
|
|
1064
|
+
def find_events_by_topic(self, topic: HexStr) -> List["BaseContractEvent"]:
|
|
1065
|
+
"""
|
|
1066
|
+
Return all events with matching topic.
|
|
1067
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
1068
|
+
"""
|
|
1069
|
+
|
|
1070
|
+
def callable_check(event_abi: ABIEvent) -> bool:
|
|
1071
|
+
return (
|
|
1072
|
+
encode_hex(keccak(text=abi_to_signature(event_abi).replace(" ", "")))
|
|
1073
|
+
== topic
|
|
892
1074
|
)
|
|
893
|
-
else:
|
|
894
|
-
if args is not None or kwargs is not None:
|
|
895
|
-
msg = "Constructor args were provided, but no constructor function was provided." # noqa: E501
|
|
896
|
-
raise TypeError(msg)
|
|
897
1075
|
|
|
898
|
-
|
|
1076
|
+
return self.find_events_by_identifier(
|
|
1077
|
+
self.abi, self.w3, self.address, callable_check
|
|
1078
|
+
)
|
|
899
1079
|
|
|
900
|
-
|
|
1080
|
+
@combomethod
|
|
1081
|
+
def get_event_by_topic(self, topic: HexStr) -> "BaseContractEvent":
|
|
1082
|
+
"""
|
|
1083
|
+
Return a distinct event with matching topic.
|
|
1084
|
+
Raises a Web3ValueError if there is no match or more than one is found.
|
|
1085
|
+
"""
|
|
1086
|
+
events = self.find_events_by_topic(topic)
|
|
1087
|
+
return self.get_event_by_identifier(events, "topic")
|
|
901
1088
|
|
|
902
1089
|
@combomethod
|
|
903
1090
|
def find_functions_by_identifier(
|
|
@@ -919,6 +1106,26 @@ class BaseContract:
|
|
|
919
1106
|
"This method should be implemented in the inherited class"
|
|
920
1107
|
)
|
|
921
1108
|
|
|
1109
|
+
@combomethod
|
|
1110
|
+
def find_events_by_identifier(
|
|
1111
|
+
cls,
|
|
1112
|
+
contract_abi: ABI,
|
|
1113
|
+
w3: Union["Web3", "AsyncWeb3"],
|
|
1114
|
+
address: ChecksumAddress,
|
|
1115
|
+
callable_check: Callable[..., Any],
|
|
1116
|
+
) -> List[Any]:
|
|
1117
|
+
raise NotImplementedError(
|
|
1118
|
+
"This method should be implemented in the inherited class"
|
|
1119
|
+
)
|
|
1120
|
+
|
|
1121
|
+
@combomethod
|
|
1122
|
+
def get_event_by_identifier(
|
|
1123
|
+
cls, fns: Sequence["BaseContractEvent"], identifier: str
|
|
1124
|
+
) -> "BaseContractEvent":
|
|
1125
|
+
raise NotImplementedError(
|
|
1126
|
+
"This method should be implemented in the inherited class"
|
|
1127
|
+
)
|
|
1128
|
+
|
|
922
1129
|
@staticmethod
|
|
923
1130
|
def get_fallback_function(
|
|
924
1131
|
abi: ABI,
|
|
@@ -927,12 +1134,14 @@ class BaseContract:
|
|
|
927
1134
|
address: Optional[ChecksumAddress] = None,
|
|
928
1135
|
) -> "BaseContractFunction":
|
|
929
1136
|
if abi and fallback_func_abi_exists(abi):
|
|
1137
|
+
fallback_abi = filter_abi_by_type("fallback", abi)[0]
|
|
930
1138
|
return function_type.factory(
|
|
931
1139
|
"fallback",
|
|
932
1140
|
w3=w3,
|
|
933
1141
|
contract_abi=abi,
|
|
934
1142
|
address=address,
|
|
935
|
-
|
|
1143
|
+
abi_element_identifier=FallbackFn,
|
|
1144
|
+
abi=fallback_abi,
|
|
936
1145
|
)()
|
|
937
1146
|
|
|
938
1147
|
return cast(function_type, NonExistentFallbackFunction()) # type: ignore
|
|
@@ -945,16 +1154,95 @@ class BaseContract:
|
|
|
945
1154
|
address: Optional[ChecksumAddress] = None,
|
|
946
1155
|
) -> "BaseContractFunction":
|
|
947
1156
|
if abi and receive_func_abi_exists(abi):
|
|
1157
|
+
receive_abi = filter_abi_by_type("receive", abi)[0]
|
|
948
1158
|
return function_type.factory(
|
|
949
1159
|
"receive",
|
|
950
1160
|
w3=w3,
|
|
951
1161
|
contract_abi=abi,
|
|
952
1162
|
address=address,
|
|
953
|
-
|
|
1163
|
+
abi_element_identifier=ReceiveFn,
|
|
1164
|
+
abi=receive_abi,
|
|
954
1165
|
)()
|
|
955
1166
|
|
|
956
1167
|
return cast(function_type, NonExistentReceiveFunction()) # type: ignore
|
|
957
1168
|
|
|
1169
|
+
#
|
|
1170
|
+
# Private Helpers
|
|
1171
|
+
#
|
|
1172
|
+
_return_data_normalizers: Tuple[Callable[..., Any], ...] = tuple()
|
|
1173
|
+
|
|
1174
|
+
@classmethod
|
|
1175
|
+
def _prepare_transaction(
|
|
1176
|
+
cls,
|
|
1177
|
+
abi_element_identifier: ABIElementIdentifier,
|
|
1178
|
+
fn_args: Optional[Any] = None,
|
|
1179
|
+
fn_kwargs: Optional[Any] = None,
|
|
1180
|
+
transaction: Optional[TxParams] = None,
|
|
1181
|
+
) -> TxParams:
|
|
1182
|
+
return prepare_transaction(
|
|
1183
|
+
cls.address,
|
|
1184
|
+
cls.w3,
|
|
1185
|
+
abi_element_identifier=abi_element_identifier,
|
|
1186
|
+
contract_abi=cls.abi,
|
|
1187
|
+
transaction=transaction,
|
|
1188
|
+
fn_args=fn_args,
|
|
1189
|
+
fn_kwargs=fn_kwargs,
|
|
1190
|
+
)
|
|
1191
|
+
|
|
1192
|
+
@classmethod
|
|
1193
|
+
def _find_matching_fn_abi(
|
|
1194
|
+
cls,
|
|
1195
|
+
fn_identifier: Optional[ABIElementIdentifier] = None,
|
|
1196
|
+
*args: Sequence[Any],
|
|
1197
|
+
**kwargs: Dict[str, Any],
|
|
1198
|
+
) -> ABIElement:
|
|
1199
|
+
if not args and not kwargs:
|
|
1200
|
+
fn_identifier = get_abi_element_signature(fn_identifier)
|
|
1201
|
+
|
|
1202
|
+
return get_abi_element(
|
|
1203
|
+
cls.abi,
|
|
1204
|
+
fn_identifier,
|
|
1205
|
+
*args,
|
|
1206
|
+
abi_codec=cls.w3.codec,
|
|
1207
|
+
**kwargs,
|
|
1208
|
+
)
|
|
1209
|
+
|
|
1210
|
+
@classmethod
|
|
1211
|
+
def _get_event_abi(
|
|
1212
|
+
cls,
|
|
1213
|
+
event_name: Optional[str] = None,
|
|
1214
|
+
argument_names: Optional[Sequence[str]] = None,
|
|
1215
|
+
) -> ABIEvent:
|
|
1216
|
+
return cast(
|
|
1217
|
+
ABIEvent,
|
|
1218
|
+
get_abi_element(
|
|
1219
|
+
abi=cls.abi,
|
|
1220
|
+
abi_element_identifier=event_name,
|
|
1221
|
+
argument_names=argument_names,
|
|
1222
|
+
),
|
|
1223
|
+
)
|
|
1224
|
+
|
|
1225
|
+
@combomethod
|
|
1226
|
+
def _encode_constructor_data(
|
|
1227
|
+
cls, *args: Sequence[Any], **kwargs: Dict[str, Any]
|
|
1228
|
+
) -> HexStr:
|
|
1229
|
+
constructor_abi = find_constructor_abi_element_by_type(cls.abi)
|
|
1230
|
+
|
|
1231
|
+
if constructor_abi:
|
|
1232
|
+
arguments = get_normalized_abi_inputs(constructor_abi, *args, **kwargs)
|
|
1233
|
+
|
|
1234
|
+
deploy_data = add_0x_prefix(
|
|
1235
|
+
encode_abi(cls.w3, constructor_abi, arguments, data=cls.bytecode)
|
|
1236
|
+
)
|
|
1237
|
+
else:
|
|
1238
|
+
if args or kwargs:
|
|
1239
|
+
msg = "Constructor args were provided, but no constructor function was provided." # noqa: E501
|
|
1240
|
+
raise Web3TypeError(msg)
|
|
1241
|
+
|
|
1242
|
+
deploy_data = to_hex(cls.bytecode)
|
|
1243
|
+
|
|
1244
|
+
return deploy_data
|
|
1245
|
+
|
|
958
1246
|
|
|
959
1247
|
class BaseContractCaller:
|
|
960
1248
|
"""
|
|
@@ -980,7 +1268,7 @@ class BaseContractCaller:
|
|
|
980
1268
|
"""
|
|
981
1269
|
|
|
982
1270
|
# mypy types
|
|
983
|
-
_functions:
|
|
1271
|
+
_functions: Sequence[ABIFunction]
|
|
984
1272
|
|
|
985
1273
|
def __init__(
|
|
986
1274
|
self,
|
|
@@ -996,6 +1284,11 @@ class BaseContractCaller:
|
|
|
996
1284
|
self._functions = []
|
|
997
1285
|
|
|
998
1286
|
def __getattr__(self, function_name: str) -> Any:
|
|
1287
|
+
function_names = [
|
|
1288
|
+
get_name_from_abi_element_identifier(fn["name"])
|
|
1289
|
+
for fn in self._functions
|
|
1290
|
+
if fn.get("type") == "function"
|
|
1291
|
+
]
|
|
999
1292
|
if self.abi is None:
|
|
1000
1293
|
raise NoABIFound(
|
|
1001
1294
|
"There is no ABI found for this contract.",
|
|
@@ -1005,8 +1298,8 @@ class BaseContractCaller:
|
|
|
1005
1298
|
"The ABI for this contract contains no function definitions. ",
|
|
1006
1299
|
"Are you sure you provided the correct contract ABI?",
|
|
1007
1300
|
)
|
|
1008
|
-
elif function_name not in
|
|
1009
|
-
functions_available = ", ".join(
|
|
1301
|
+
elif get_name_from_abi_element_identifier(function_name) not in function_names:
|
|
1302
|
+
functions_available = ", ".join(function_names)
|
|
1010
1303
|
raise ABIFunctionNotFound(
|
|
1011
1304
|
f"The function '{function_name}' was not found in this contract's ABI.",
|
|
1012
1305
|
" Here is a list of all of the function names found: ",
|
|
@@ -1014,11 +1307,17 @@ class BaseContractCaller:
|
|
|
1014
1307
|
"Did you mean to call one of those functions?",
|
|
1015
1308
|
)
|
|
1016
1309
|
else:
|
|
1017
|
-
|
|
1310
|
+
function_identifier = function_name
|
|
1018
1311
|
|
|
1019
|
-
|
|
1312
|
+
if "(" not in function_name:
|
|
1313
|
+
function_identifier = _get_any_abi_signature_with_name(
|
|
1314
|
+
function_name, self._functions
|
|
1315
|
+
)
|
|
1316
|
+
return super().__getattribute__(function_identifier)
|
|
1317
|
+
|
|
1318
|
+
def __hasattr__(self, function_name: str) -> bool:
|
|
1020
1319
|
try:
|
|
1021
|
-
return
|
|
1320
|
+
return function_name in self.__dict__["_functions"]
|
|
1022
1321
|
except ABIFunctionNotFound:
|
|
1023
1322
|
return False
|
|
1024
1323
|
|
|
@@ -1060,7 +1359,7 @@ class BaseContractConstructor:
|
|
|
1060
1359
|
|
|
1061
1360
|
@combomethod
|
|
1062
1361
|
def _encode_data_in_transaction(self, *args: Any, **kwargs: Any) -> HexStr:
|
|
1063
|
-
constructor_abi =
|
|
1362
|
+
constructor_abi = find_constructor_abi_element_by_type(self.abi)
|
|
1064
1363
|
|
|
1065
1364
|
if constructor_abi:
|
|
1066
1365
|
if not args:
|
|
@@ -1068,7 +1367,8 @@ class BaseContractConstructor:
|
|
|
1068
1367
|
if not kwargs:
|
|
1069
1368
|
kwargs = {}
|
|
1070
1369
|
|
|
1071
|
-
arguments =
|
|
1370
|
+
arguments = get_normalized_abi_inputs(constructor_abi, *args, **kwargs)
|
|
1371
|
+
|
|
1072
1372
|
data = add_0x_prefix(
|
|
1073
1373
|
encode_abi(self.w3, constructor_abi, arguments, data=self.bytecode)
|
|
1074
1374
|
)
|
|
@@ -1088,9 +1388,8 @@ class BaseContractConstructor:
|
|
|
1088
1388
|
)
|
|
1089
1389
|
|
|
1090
1390
|
if self.w3.eth.default_account is not empty:
|
|
1091
|
-
# type ignored b/c check prevents an empty default_account
|
|
1092
1391
|
estimate_gas_transaction.setdefault(
|
|
1093
|
-
"from", self.w3.eth.default_account
|
|
1392
|
+
"from", cast(ChecksumAddress, self.w3.eth.default_account)
|
|
1094
1393
|
)
|
|
1095
1394
|
|
|
1096
1395
|
estimate_gas_transaction["data"] = self.data_in_transaction
|
|
@@ -1107,9 +1406,8 @@ class BaseContractConstructor:
|
|
|
1107
1406
|
)
|
|
1108
1407
|
|
|
1109
1408
|
if self.w3.eth.default_account is not empty:
|
|
1110
|
-
# type ignored b/c check prevents an empty default_account
|
|
1111
1409
|
transact_transaction.setdefault(
|
|
1112
|
-
"from", self.w3.eth.default_account
|
|
1410
|
+
"from", cast(ChecksumAddress, self.w3.eth.default_account)
|
|
1113
1411
|
)
|
|
1114
1412
|
|
|
1115
1413
|
transact_transaction["data"] = self.data_in_transaction
|
|
@@ -1128,7 +1426,7 @@ class BaseContractConstructor:
|
|
|
1128
1426
|
) -> None:
|
|
1129
1427
|
keys_found = transaction.keys() & forbidden_keys
|
|
1130
1428
|
if keys_found:
|
|
1131
|
-
raise
|
|
1429
|
+
raise Web3ValueError(
|
|
1132
1430
|
f"Cannot set '{', '.join(keys_found)}' field(s) in transaction"
|
|
1133
1431
|
)
|
|
1134
1432
|
|
|
@@ -1136,7 +1434,7 @@ class BaseContractConstructor:
|
|
|
1136
1434
|
class NonExistentFallbackFunction:
|
|
1137
1435
|
@staticmethod
|
|
1138
1436
|
def _raise_exception() -> NoReturn:
|
|
1139
|
-
raise
|
|
1437
|
+
raise ABIFallbackNotFound("No fallback function was found in the contract ABI.")
|
|
1140
1438
|
|
|
1141
1439
|
def __getattr__(self, attr: Any) -> Callable[[], None]:
|
|
1142
1440
|
return self._raise_exception
|
|
@@ -1145,7 +1443,7 @@ class NonExistentFallbackFunction:
|
|
|
1145
1443
|
class NonExistentReceiveFunction:
|
|
1146
1444
|
@staticmethod
|
|
1147
1445
|
def _raise_exception() -> NoReturn:
|
|
1148
|
-
raise
|
|
1446
|
+
raise ABIReceiveNotFound("No receive function was found in the contract ABI.")
|
|
1149
1447
|
|
|
1150
1448
|
def __getattr__(self, attr: Any) -> Callable[[], None]:
|
|
1151
1449
|
return self._raise_exception
|