web3 7.0.0b2__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.
Files changed (144) hide show
  1. ens/__init__.py +13 -2
  2. ens/_normalization.py +4 -4
  3. ens/async_ens.py +27 -15
  4. ens/base_ens.py +3 -1
  5. ens/contract_data.py +2 -2
  6. ens/ens.py +10 -7
  7. ens/exceptions.py +16 -29
  8. ens/specs/nf.json +1 -1
  9. ens/specs/normalization_spec.json +1 -1
  10. ens/utils.py +24 -32
  11. web3/__init__.py +23 -12
  12. web3/_utils/abi.py +157 -263
  13. web3/_utils/async_transactions.py +34 -20
  14. web3/_utils/batching.py +217 -0
  15. web3/_utils/blocks.py +6 -2
  16. web3/_utils/caching/__init__.py +12 -0
  17. web3/_utils/caching/caching_utils.py +433 -0
  18. web3/_utils/caching/request_caching_validation.py +287 -0
  19. web3/_utils/compat/__init__.py +2 -3
  20. web3/_utils/contract_sources/compile_contracts.py +1 -1
  21. web3/_utils/contract_sources/contract_data/ambiguous_function_contract.py +42 -0
  22. web3/_utils/contract_sources/contract_data/arrays_contract.py +3 -3
  23. web3/_utils/contract_sources/contract_data/bytes_contracts.py +5 -5
  24. web3/_utils/contract_sources/contract_data/constructor_contracts.py +7 -7
  25. web3/_utils/contract_sources/contract_data/contract_caller_tester.py +3 -3
  26. web3/_utils/contract_sources/contract_data/emitter_contract.py +3 -3
  27. web3/_utils/contract_sources/contract_data/event_contracts.py +50 -5
  28. web3/_utils/contract_sources/contract_data/extended_resolver.py +3 -3
  29. web3/_utils/contract_sources/contract_data/fallback_function_contract.py +3 -3
  30. web3/_utils/contract_sources/contract_data/function_name_tester_contract.py +3 -3
  31. web3/_utils/contract_sources/contract_data/math_contract.py +3 -3
  32. web3/_utils/contract_sources/contract_data/offchain_lookup.py +3 -3
  33. web3/_utils/contract_sources/contract_data/offchain_resolver.py +3 -3
  34. web3/_utils/contract_sources/contract_data/panic_errors_contract.py +3 -3
  35. web3/_utils/contract_sources/contract_data/payable_tester.py +3 -3
  36. web3/_utils/contract_sources/contract_data/receive_function_contracts.py +5 -5
  37. web3/_utils/contract_sources/contract_data/reflector_contracts.py +3 -3
  38. web3/_utils/contract_sources/contract_data/revert_contract.py +3 -3
  39. web3/_utils/contract_sources/contract_data/simple_resolver.py +3 -3
  40. web3/_utils/contract_sources/contract_data/storage_contract.py +3 -3
  41. web3/_utils/contract_sources/contract_data/string_contract.py +3 -3
  42. web3/_utils/contract_sources/contract_data/tuple_contracts.py +5 -5
  43. web3/_utils/contracts.py +172 -220
  44. web3/_utils/datatypes.py +5 -1
  45. web3/_utils/decorators.py +6 -1
  46. web3/_utils/empty.py +1 -1
  47. web3/_utils/encoding.py +16 -12
  48. web3/_utils/error_formatters_utils.py +5 -3
  49. web3/_utils/events.py +78 -72
  50. web3/_utils/fee_utils.py +1 -3
  51. web3/_utils/filters.py +24 -22
  52. web3/_utils/formatters.py +2 -2
  53. web3/_utils/http.py +8 -2
  54. web3/_utils/http_session_manager.py +314 -0
  55. web3/_utils/math.py +14 -15
  56. web3/_utils/method_formatters.py +161 -34
  57. web3/_utils/module.py +2 -1
  58. web3/_utils/module_testing/__init__.py +3 -2
  59. web3/_utils/module_testing/eth_module.py +736 -583
  60. web3/_utils/module_testing/go_ethereum_debug_module.py +128 -0
  61. web3/_utils/module_testing/module_testing_utils.py +81 -24
  62. web3/_utils/module_testing/persistent_connection_provider.py +702 -220
  63. web3/_utils/module_testing/utils.py +114 -33
  64. web3/_utils/module_testing/web3_module.py +438 -17
  65. web3/_utils/normalizers.py +13 -11
  66. web3/_utils/rpc_abi.py +10 -22
  67. web3/_utils/threads.py +8 -7
  68. web3/_utils/transactions.py +32 -25
  69. web3/_utils/type_conversion.py +5 -1
  70. web3/_utils/validation.py +20 -17
  71. web3/beacon/__init__.py +5 -0
  72. web3/beacon/api_endpoints.py +3 -0
  73. web3/beacon/async_beacon.py +29 -6
  74. web3/beacon/beacon.py +24 -6
  75. web3/contract/__init__.py +7 -0
  76. web3/contract/async_contract.py +285 -82
  77. web3/contract/base_contract.py +556 -258
  78. web3/contract/contract.py +295 -84
  79. web3/contract/utils.py +251 -55
  80. web3/datastructures.py +49 -34
  81. web3/eth/__init__.py +7 -0
  82. web3/eth/async_eth.py +89 -69
  83. web3/eth/base_eth.py +7 -3
  84. web3/eth/eth.py +43 -66
  85. web3/exceptions.py +158 -83
  86. web3/gas_strategies/time_based.py +8 -6
  87. web3/geth.py +53 -184
  88. web3/main.py +77 -17
  89. web3/manager.py +362 -95
  90. web3/method.py +43 -15
  91. web3/middleware/__init__.py +17 -0
  92. web3/middleware/attrdict.py +12 -22
  93. web3/middleware/base.py +55 -2
  94. web3/middleware/filter.py +45 -23
  95. web3/middleware/formatting.py +6 -3
  96. web3/middleware/names.py +4 -1
  97. web3/middleware/signing.py +15 -6
  98. web3/middleware/stalecheck.py +2 -1
  99. web3/module.py +61 -25
  100. web3/providers/__init__.py +21 -0
  101. web3/providers/async_base.py +87 -32
  102. web3/providers/base.py +77 -32
  103. web3/providers/eth_tester/__init__.py +5 -0
  104. web3/providers/eth_tester/defaults.py +2 -55
  105. web3/providers/eth_tester/main.py +41 -15
  106. web3/providers/eth_tester/middleware.py +16 -17
  107. web3/providers/ipc.py +41 -17
  108. web3/providers/legacy_websocket.py +26 -1
  109. web3/providers/persistent/__init__.py +7 -0
  110. web3/providers/persistent/async_ipc.py +61 -121
  111. web3/providers/persistent/persistent.py +323 -16
  112. web3/providers/persistent/persistent_connection.py +54 -5
  113. web3/providers/persistent/request_processor.py +136 -56
  114. web3/providers/persistent/subscription_container.py +56 -0
  115. web3/providers/persistent/subscription_manager.py +233 -0
  116. web3/providers/persistent/websocket.py +29 -92
  117. web3/providers/rpc/__init__.py +5 -0
  118. web3/providers/rpc/async_rpc.py +73 -18
  119. web3/providers/rpc/rpc.py +73 -30
  120. web3/providers/rpc/utils.py +1 -13
  121. web3/scripts/install_pre_releases.py +33 -0
  122. web3/scripts/parse_pygeth_version.py +16 -0
  123. web3/testing.py +4 -4
  124. web3/tracing.py +9 -5
  125. web3/types.py +141 -74
  126. web3/utils/__init__.py +64 -5
  127. web3/utils/abi.py +790 -10
  128. web3/utils/address.py +8 -0
  129. web3/utils/async_exception_handling.py +20 -11
  130. web3/utils/caching.py +34 -4
  131. web3/utils/exception_handling.py +9 -12
  132. web3/utils/subscriptions.py +285 -0
  133. {web3-7.0.0b2.dist-info → web3-7.7.0.dist-info}/LICENSE +1 -1
  134. web3-7.7.0.dist-info/METADATA +130 -0
  135. web3-7.7.0.dist-info/RECORD +171 -0
  136. {web3-7.0.0b2.dist-info → web3-7.7.0.dist-info}/WHEEL +1 -1
  137. web3/_utils/caching.py +0 -155
  138. web3/_utils/contract_sources/contract_data/address_reflector.py +0 -29
  139. web3/_utils/module_testing/go_ethereum_personal_module.py +0 -300
  140. web3/_utils/request.py +0 -265
  141. web3-7.0.0b2.dist-info/METADATA +0 -106
  142. web3-7.0.0b2.dist-info/RECORD +0 -163
  143. /web3/_utils/{function_identifiers.py → abi_element_identifiers.py} +0 -0
  144. {web3-7.0.0b2.dist-info → web3-7.7.0.dist-info}/top_level.txt +0 -0
web3/_utils/contracts.py CHANGED
@@ -1,13 +1,14 @@
1
+ import copy
1
2
  import functools
2
3
  from typing import (
3
4
  TYPE_CHECKING,
4
5
  Any,
5
6
  Callable,
6
7
  Dict,
8
+ List,
7
9
  Optional,
8
10
  Sequence,
9
11
  Tuple,
10
- Type,
11
12
  Union,
12
13
  cast,
13
14
  )
@@ -19,6 +20,14 @@ from eth_abi.registry import (
19
20
  registry as default_registry,
20
21
  )
21
22
  from eth_typing import (
23
+ ABI,
24
+ ABICallable,
25
+ ABIConstructor,
26
+ ABIElement,
27
+ ABIEvent,
28
+ ABIFallback,
29
+ ABIFunction,
30
+ ABIReceive,
22
31
  ChecksumAddress,
23
32
  HexStr,
24
33
  TypeStr,
@@ -26,11 +35,9 @@ from eth_typing import (
26
35
  from eth_utils import (
27
36
  add_0x_prefix,
28
37
  encode_hex,
29
- function_abi_to_4byte_selector,
30
- is_binary_address,
31
- is_checksum_address,
32
- is_list_like,
33
- is_text,
38
+ filter_abi_by_name,
39
+ filter_abi_by_type,
40
+ get_abi_input_types,
34
41
  )
35
42
  from eth_utils.toolz import (
36
43
  pipe,
@@ -40,19 +47,10 @@ from hexbytes import (
40
47
  )
41
48
 
42
49
  from web3._utils.abi import (
43
- abi_to_signature,
44
- check_if_arguments_can_be_encoded,
45
- filter_by_argument_count,
46
50
  filter_by_argument_name,
47
- filter_by_encodability,
48
- filter_by_name,
49
- filter_by_type,
50
- get_abi_input_types,
51
- get_aligned_abi_inputs,
52
- get_fallback_func_abi,
53
- get_receive_func_abi,
51
+ get_abi_element_signature,
52
+ get_name_from_abi_element_identifier,
54
53
  map_abi_data,
55
- merge_args_and_kwargs,
56
54
  named_tree,
57
55
  )
58
56
  from web3._utils.blocks import (
@@ -61,10 +59,6 @@ from web3._utils.blocks import (
61
59
  from web3._utils.encoding import (
62
60
  to_hex,
63
61
  )
64
- from web3._utils.function_identifiers import (
65
- FallbackFn,
66
- ReceiveFn,
67
- )
68
62
  from web3._utils.method_formatters import (
69
63
  to_integer_if_hex,
70
64
  )
@@ -75,17 +69,24 @@ from web3._utils.normalizers import (
75
69
  abi_string_to_text,
76
70
  )
77
71
  from web3.exceptions import (
78
- BlockNumberOutofRange,
72
+ BlockNumberOutOfRange,
73
+ Web3TypeError,
79
74
  Web3ValidationError,
75
+ Web3ValueError,
80
76
  )
81
77
  from web3.types import (
82
- ABI,
83
- ABIEvent,
84
- ABIFunction,
78
+ ABIElementIdentifier,
85
79
  BlockIdentifier,
86
80
  BlockNumber,
81
+ TContractEvent,
82
+ TContractFn,
87
83
  TxParams,
88
84
  )
85
+ from web3.utils.abi import (
86
+ check_if_arguments_can_be_encoded,
87
+ get_abi_element,
88
+ get_abi_element_info,
89
+ )
89
90
 
90
91
  if TYPE_CHECKING:
91
92
  from web3 import ( # noqa: F401
@@ -94,130 +95,50 @@ if TYPE_CHECKING:
94
95
  )
95
96
 
96
97
 
97
- def extract_argument_types(*args: Sequence[Any]) -> str:
98
- """
99
- Takes a list of arguments and returns a string representation of the argument types,
100
- appropriately collapsing `tuple` types into the respective nested types.
101
- """
102
- collapsed_args = []
103
-
104
- for arg in args:
105
- if is_list_like(arg):
106
- collapsed_nested = []
107
- for nested in arg:
108
- if is_list_like(nested):
109
- collapsed_nested.append(f"({extract_argument_types(nested)})")
110
- else:
111
- collapsed_nested.append(_get_argument_readable_type(nested))
112
- collapsed_args.append(",".join(collapsed_nested))
113
- else:
114
- collapsed_args.append(_get_argument_readable_type(arg))
115
-
116
- return ",".join(collapsed_args)
117
-
118
-
119
98
  def find_matching_event_abi(
120
99
  abi: ABI,
121
100
  event_name: Optional[str] = None,
122
101
  argument_names: Optional[Sequence[str]] = None,
123
102
  ) -> ABIEvent:
124
- filters = [
125
- functools.partial(filter_by_type, "event"),
103
+ filters: List[functools.partial[Sequence[ABIElement]]] = [
104
+ functools.partial(filter_abi_by_type, "event"),
126
105
  ]
127
106
 
128
107
  if event_name is not None:
129
- filters.append(functools.partial(filter_by_name, event_name))
108
+ filters.append(functools.partial(filter_abi_by_name, event_name))
130
109
 
131
110
  if argument_names is not None:
132
111
  filters.append(functools.partial(filter_by_argument_name, argument_names))
133
112
 
134
- event_abi_candidates = pipe(abi, *filters)
113
+ event_abi_candidates: Sequence[ABIEvent] = pipe(abi, *filters)
135
114
 
136
115
  if len(event_abi_candidates) == 1:
137
116
  return event_abi_candidates[0]
138
117
  elif not event_abi_candidates:
139
- raise ValueError("No matching events found")
118
+ raise Web3ValueError("No matching events found")
140
119
  else:
141
- raise ValueError("Multiple events found")
142
-
143
-
144
- def find_matching_fn_abi(
145
- abi: ABI,
146
- abi_codec: ABICodec,
147
- fn_identifier: Optional[Union[str, Type[FallbackFn], Type[ReceiveFn]]] = None,
148
- args: Optional[Sequence[Any]] = None,
149
- kwargs: Optional[Any] = None,
150
- ) -> ABIFunction:
151
- args = args or tuple()
152
- kwargs = kwargs or dict()
153
- num_arguments = len(args) + len(kwargs)
154
-
155
- if fn_identifier is FallbackFn:
156
- return get_fallback_func_abi(abi)
157
-
158
- if fn_identifier is ReceiveFn:
159
- return get_receive_func_abi(abi)
160
-
161
- if not is_text(fn_identifier):
162
- raise TypeError("Unsupported function identifier")
163
-
164
- name_filter = functools.partial(filter_by_name, fn_identifier)
165
- arg_count_filter = functools.partial(filter_by_argument_count, num_arguments)
166
- encoding_filter = functools.partial(filter_by_encodability, abi_codec, args, kwargs)
167
-
168
- function_candidates = pipe(abi, name_filter, arg_count_filter, encoding_filter)
169
-
170
- if len(function_candidates) == 1:
171
- return function_candidates[0]
172
- else:
173
- matching_identifiers = name_filter(abi)
174
- matching_function_signatures = [
175
- abi_to_signature(func) for func in matching_identifiers
176
- ]
177
-
178
- arg_count_matches = len(arg_count_filter(matching_identifiers))
179
- encoding_matches = len(encoding_filter(matching_identifiers))
180
-
181
- if arg_count_matches == 0:
182
- diagnosis = (
183
- "\nFunction invocation failed due to improper number of arguments."
184
- )
185
- elif encoding_matches == 0:
186
- diagnosis = (
187
- "\nFunction invocation failed due to no matching argument types."
188
- )
189
- elif encoding_matches > 1:
190
- diagnosis = (
191
- "\nAmbiguous argument encoding. "
192
- "Provided arguments can be encoded to multiple functions "
193
- "matching this call."
194
- )
195
-
196
- collapsed_args = extract_argument_types(args)
197
- collapsed_kwargs = dict(
198
- {(k, extract_argument_types([v])) for k, v in kwargs.items()}
199
- )
200
- message = (
201
- f"\nCould not identify the intended function with name `{fn_identifier}`, "
202
- f"positional arguments with type(s) `{collapsed_args}` and "
203
- f"keyword arguments with type(s) `{collapsed_kwargs}`."
204
- f"\nFound {len(matching_identifiers)} function(s) with "
205
- f"the name `{fn_identifier}`: {matching_function_signatures}{diagnosis}"
206
- )
207
-
208
- raise Web3ValidationError(message)
120
+ raise Web3ValueError("Multiple events found")
209
121
 
210
122
 
211
123
  def encode_abi(
212
124
  w3: Union["AsyncWeb3", "Web3"],
213
- abi: ABIFunction,
125
+ abi: ABIElement,
214
126
  arguments: Sequence[Any],
215
127
  data: Optional[HexStr] = None,
216
128
  ) -> HexStr:
217
- argument_types = get_abi_input_types(abi)
218
-
219
- if not check_if_arguments_can_be_encoded(abi, w3.codec, arguments, {}):
220
- raise TypeError(
129
+ argument_types = []
130
+ try:
131
+ argument_types = get_abi_input_types(abi)
132
+ except ValueError:
133
+ # Use the default argument_types if the abi doesn't have inputs
134
+ pass
135
+
136
+ if not check_if_arguments_can_be_encoded(
137
+ abi,
138
+ *arguments,
139
+ abi_codec=w3.codec,
140
+ ):
141
+ raise Web3TypeError(
221
142
  "One or more arguments could not be encoded to the necessary "
222
143
  f"ABI type. Expected types are: {', '.join(argument_types)}"
223
144
  )
@@ -248,25 +169,45 @@ def encode_abi(
248
169
  def prepare_transaction(
249
170
  address: ChecksumAddress,
250
171
  w3: Union["AsyncWeb3", "Web3"],
251
- fn_identifier: Union[str, Type[FallbackFn], Type[ReceiveFn]],
172
+ abi_element_identifier: ABIElementIdentifier,
252
173
  contract_abi: Optional[ABI] = None,
253
- fn_abi: Optional[ABIFunction] = None,
174
+ abi_callable: Optional[ABICallable] = None,
254
175
  transaction: Optional[TxParams] = None,
255
176
  fn_args: Optional[Sequence[Any]] = None,
256
177
  fn_kwargs: Optional[Any] = None,
257
178
  ) -> TxParams:
258
179
  """
259
- :parameter `is_function_abi` is used to distinguish function abi from contract abi
260
180
  Returns a dictionary of the transaction that could be used to call this
261
181
  TODO: make this a public API
262
182
  TODO: add new prepare_deploy_transaction API
263
183
  """
264
- if fn_abi is None:
265
- fn_abi = find_matching_fn_abi(
266
- contract_abi, w3.codec, fn_identifier, fn_args, fn_kwargs
184
+ fn_args = fn_args or []
185
+ fn_kwargs = fn_kwargs or {}
186
+
187
+ if not fn_args and not fn_kwargs and "(" not in str(abi_element_identifier):
188
+ abi_element_identifier = get_abi_element_signature(abi_element_identifier)
189
+
190
+ if abi_element_identifier in [
191
+ "fallback()",
192
+ "receive()",
193
+ ]:
194
+ abi_element_identifier = get_name_from_abi_element_identifier(
195
+ abi_element_identifier
267
196
  )
268
197
 
269
- validate_payable(transaction, fn_abi)
198
+ if abi_callable is None:
199
+ abi_callable = cast(
200
+ ABICallable,
201
+ get_abi_element(
202
+ contract_abi,
203
+ abi_element_identifier,
204
+ *fn_args,
205
+ abi_codec=w3.codec,
206
+ **fn_kwargs,
207
+ ),
208
+ )
209
+
210
+ validate_payable(transaction, abi_callable)
270
211
 
271
212
  if transaction is None:
272
213
  prepared_transaction: TxParams = {}
@@ -274,16 +215,16 @@ def prepare_transaction(
274
215
  prepared_transaction = cast(TxParams, dict(**transaction))
275
216
 
276
217
  if "data" in prepared_transaction:
277
- raise ValueError("Transaction parameter may not contain a 'data' key")
218
+ raise Web3ValueError("Transaction parameter may not contain a 'data' key")
278
219
 
279
220
  if address:
280
221
  prepared_transaction.setdefault("to", address)
281
222
 
282
223
  prepared_transaction["data"] = encode_transaction_data(
283
224
  w3,
284
- fn_identifier,
225
+ abi_element_identifier,
285
226
  contract_abi,
286
- fn_abi,
227
+ abi_callable,
287
228
  fn_args,
288
229
  fn_kwargs,
289
230
  )
@@ -292,34 +233,37 @@ def prepare_transaction(
292
233
 
293
234
  def encode_transaction_data(
294
235
  w3: Union["AsyncWeb3", "Web3"],
295
- fn_identifier: Union[str, Type[FallbackFn], Type[ReceiveFn]],
236
+ abi_element_identifier: ABIElementIdentifier,
296
237
  contract_abi: Optional[ABI] = None,
297
- fn_abi: Optional[ABIFunction] = None,
238
+ abi_callable: Optional[ABICallable] = None,
298
239
  args: Optional[Sequence[Any]] = None,
299
240
  kwargs: Optional[Any] = None,
300
241
  ) -> HexStr:
301
- if fn_identifier is FallbackFn:
302
- fn_abi, fn_selector, fn_arguments = get_fallback_function_info(
303
- contract_abi, fn_abi
242
+ info_abi: ABIElement
243
+ abi_element_name = get_name_from_abi_element_identifier(abi_element_identifier)
244
+ if abi_element_name == "fallback":
245
+ info_abi, info_selector, info_arguments = get_fallback_function_info(
246
+ contract_abi, cast(ABIFallback, abi_callable)
304
247
  )
305
- elif fn_identifier is ReceiveFn:
306
- fn_abi, fn_selector, fn_arguments = get_receive_function_info(
307
- contract_abi, fn_abi
248
+ elif abi_element_name == "receive":
249
+ info_abi, info_selector, info_arguments = get_receive_function_info(
250
+ contract_abi, cast(ABIReceive, abi_callable)
308
251
  )
309
- elif is_text(fn_identifier):
310
- fn_abi, fn_selector, fn_arguments = get_function_info(
311
- # type ignored b/c fn_id here is always str b/c FallbackFn is handled above
312
- fn_identifier, # type: ignore
313
- w3.codec,
252
+ elif isinstance(abi_element_identifier, str):
253
+ fn_info = get_abi_element_info(
314
254
  contract_abi,
315
- fn_abi,
316
- args,
317
- kwargs,
255
+ abi_element_identifier,
256
+ *args,
257
+ abi_codec=w3.codec,
258
+ **kwargs,
318
259
  )
260
+ info_abi = fn_info["abi"]
261
+ info_selector = fn_info["selector"]
262
+ info_arguments = fn_info["arguments"]
319
263
  else:
320
- raise TypeError("Unsupported function identifier")
264
+ raise Web3TypeError("Unsupported function identifier")
321
265
 
322
- return add_0x_prefix(encode_abi(w3, fn_abi, fn_arguments, fn_selector))
266
+ return add_0x_prefix(encode_abi(w3, info_abi, info_arguments, info_selector))
323
267
 
324
268
 
325
269
  def decode_transaction_data(
@@ -327,91 +271,71 @@ def decode_transaction_data(
327
271
  data: HexStr,
328
272
  normalizers: Sequence[Callable[[TypeStr, Any], Tuple[TypeStr, Any]]] = None,
329
273
  ) -> Dict[str, Any]:
330
- # type ignored b/c expects data arg to be HexBytes
331
- data = HexBytes(data) # type: ignore
274
+ data_bytes = HexBytes(data)
332
275
  types = get_abi_input_types(fn_abi)
333
276
  abi_codec = ABICodec(default_registry)
334
- decoded = abi_codec.decode(types, HexBytes(data[4:]))
277
+ decoded = abi_codec.decode(types, data_bytes[4:])
335
278
  if normalizers:
336
279
  decoded = map_abi_data(normalizers, types, decoded)
337
280
  return named_tree(fn_abi["inputs"], decoded)
338
281
 
339
282
 
340
- def get_fallback_function_info(
341
- contract_abi: Optional[ABI] = None, fn_abi: Optional[ABIFunction] = None
342
- ) -> Tuple[ABIFunction, HexStr, Tuple[Any, ...]]:
343
- if fn_abi is None:
344
- fn_abi = get_fallback_func_abi(contract_abi)
283
+ def get_constructor_function_info(
284
+ contract_abi: Optional[ABI] = None, constructor_abi: Optional[ABIConstructor] = None
285
+ ) -> Tuple[ABIConstructor, HexStr, Tuple[Any, ...]]:
286
+ if constructor_abi is None:
287
+ constructor_abi = cast(
288
+ ABIConstructor, get_abi_element(contract_abi, "constructor")
289
+ )
345
290
  fn_selector = encode_hex(b"")
346
291
  fn_arguments: Tuple[Any, ...] = tuple()
347
- return fn_abi, fn_selector, fn_arguments
292
+ return constructor_abi, fn_selector, fn_arguments
348
293
 
349
294
 
350
- def get_receive_function_info(
351
- contract_abi: Optional[ABI] = None, fn_abi: Optional[ABIFunction] = None
352
- ) -> Tuple[ABIFunction, HexStr, Tuple[Any, ...]]:
353
- if fn_abi is None:
354
- fn_abi = get_receive_func_abi(contract_abi)
295
+ def get_fallback_function_info(
296
+ contract_abi: Optional[ABI] = None, fallback_abi: Optional[ABIFallback] = None
297
+ ) -> Tuple[ABIFallback, HexStr, Tuple[Any, ...]]:
298
+ if fallback_abi is None:
299
+ fallback_abi = cast(ABIFallback, get_abi_element(contract_abi, "fallback"))
355
300
  fn_selector = encode_hex(b"")
356
301
  fn_arguments: Tuple[Any, ...] = tuple()
357
- return fn_abi, fn_selector, fn_arguments
302
+ return fallback_abi, fn_selector, fn_arguments
358
303
 
359
304
 
360
- def get_function_info(
361
- fn_name: str,
362
- abi_codec: ABICodec,
363
- contract_abi: Optional[ABI] = None,
364
- fn_abi: Optional[ABIFunction] = None,
365
- args: Optional[Sequence[Any]] = None,
366
- kwargs: Optional[Any] = None,
367
- ) -> Tuple[ABIFunction, HexStr, Tuple[Any, ...]]:
368
- if args is None:
369
- args = tuple()
370
- if kwargs is None:
371
- kwargs = {}
372
-
373
- if fn_abi is None:
374
- fn_abi = find_matching_fn_abi(contract_abi, abi_codec, fn_name, args, kwargs)
375
-
376
- # typed dict cannot be used w/ a normal Dict
377
- # https://github.com/python/mypy/issues/4976
378
- fn_selector = encode_hex(function_abi_to_4byte_selector(fn_abi)) # type: ignore
379
-
380
- fn_arguments = merge_args_and_kwargs(fn_abi, args, kwargs)
381
-
382
- _, aligned_fn_arguments = get_aligned_abi_inputs(fn_abi, fn_arguments)
383
-
384
- return fn_abi, fn_selector, aligned_fn_arguments
305
+ def get_receive_function_info(
306
+ contract_abi: Optional[ABI] = None, receive_abi: Optional[ABIReceive] = None
307
+ ) -> Tuple[ABIReceive, HexStr, Tuple[Any, ...]]:
308
+ if receive_abi is None:
309
+ receive_abi = cast(ABIReceive, get_abi_element(contract_abi, "receive"))
310
+ fn_selector = encode_hex(b"")
311
+ fn_arguments: Tuple[Any, ...] = tuple()
312
+ return receive_abi, fn_selector, fn_arguments
385
313
 
386
314
 
387
- def validate_payable(transaction: TxParams, abi: ABIFunction) -> None:
388
- """Raise Web3ValidationError if non-zero ether
315
+ def validate_payable(transaction: TxParams, abi_callable: ABICallable) -> None:
316
+ """
317
+ Raise Web3ValidationError if non-zero ether
389
318
  is sent to a non-payable function.
390
319
  """
391
- if "value" in transaction:
392
- if to_integer_if_hex(transaction["value"]) != 0:
393
- if (
394
- "payable" in abi
395
- and not abi["payable"]
396
- or "stateMutability" in abi
397
- and abi["stateMutability"] == "nonpayable"
398
- ):
399
- raise Web3ValidationError(
400
- "Sending non-zero ether to a contract function "
401
- "with payable=False. Please ensure that "
402
- "transaction's value is 0."
403
- )
404
-
405
-
406
- def _get_argument_readable_type(arg: Any) -> str:
407
- if is_checksum_address(arg) or is_binary_address(arg):
408
- return "address"
409
-
410
- return arg.__class__.__name__
320
+ if (
321
+ "value" in transaction
322
+ and to_integer_if_hex(transaction["value"]) != 0
323
+ and (
324
+ "payable" in abi_callable
325
+ and not abi_callable["payable"]
326
+ or "stateMutability" in abi_callable
327
+ and abi_callable["stateMutability"] == "nonpayable"
328
+ )
329
+ ):
330
+ raise Web3ValidationError(
331
+ "Sending non-zero ether to a contract function "
332
+ "with payable=False. Please ensure that "
333
+ "transaction's value is 0."
334
+ )
411
335
 
412
336
 
413
337
  def parse_block_identifier(
414
- w3: "Web3", block_identifier: BlockIdentifier
338
+ w3: "Web3", block_identifier: Optional[BlockIdentifier]
415
339
  ) -> BlockIdentifier:
416
340
  if block_identifier is None:
417
341
  return w3.eth.default_block
@@ -424,7 +348,7 @@ def parse_block_identifier(
424
348
  ):
425
349
  return w3.eth.get_block(block_identifier)["number"]
426
350
  else:
427
- raise BlockNumberOutofRange
351
+ raise BlockNumberOutOfRange
428
352
 
429
353
 
430
354
  def parse_block_identifier_int(w3: "Web3", block_identifier_int: int) -> BlockNumber:
@@ -434,7 +358,7 @@ def parse_block_identifier_int(w3: "Web3", block_identifier_int: int) -> BlockNu
434
358
  last_block = w3.eth.get_block("latest")["number"]
435
359
  block_num = last_block + block_identifier_int + 1
436
360
  if block_num < 0:
437
- raise BlockNumberOutofRange
361
+ raise BlockNumberOutOfRange
438
362
  return BlockNumber(block_num)
439
363
 
440
364
 
@@ -453,7 +377,7 @@ async def async_parse_block_identifier(
453
377
  requested_block = await async_w3.eth.get_block(block_identifier)
454
378
  return requested_block["number"]
455
379
  else:
456
- raise BlockNumberOutofRange
380
+ raise BlockNumberOutOfRange
457
381
 
458
382
 
459
383
  async def async_parse_block_identifier_int(
@@ -466,5 +390,33 @@ async def async_parse_block_identifier_int(
466
390
  last_block_num = last_block["number"]
467
391
  block_num = last_block_num + block_identifier_int + 1
468
392
  if block_num < 0:
469
- raise BlockNumberOutofRange
393
+ raise BlockNumberOutOfRange
470
394
  return BlockNumber(block_num)
395
+
396
+
397
+ def copy_contract_function(
398
+ contract_function: TContractFn, *args: Any, **kwargs: Any
399
+ ) -> TContractFn:
400
+ """
401
+ Copy a contract function instance.
402
+ """
403
+ clone = copy.copy(contract_function)
404
+ clone.args = args or tuple()
405
+ clone.kwargs = kwargs or dict()
406
+
407
+ clone._set_function_info()
408
+ return clone
409
+
410
+
411
+ def copy_contract_event(
412
+ contract_event: TContractEvent, *args: Any, **kwargs: Any
413
+ ) -> TContractEvent:
414
+ """
415
+ Copy a contract function instance.
416
+ """
417
+ clone = copy.copy(contract_event)
418
+ clone.args = args or tuple()
419
+ clone.kwargs = kwargs or dict()
420
+
421
+ clone._set_event_info()
422
+ return clone
web3/_utils/datatypes.py CHANGED
@@ -14,10 +14,14 @@ from eth_utils.toolz import (
14
14
  concat,
15
15
  )
16
16
 
17
+ from web3.exceptions import (
18
+ Web3AttributeError,
19
+ )
20
+
17
21
 
18
22
  def verify_attr(class_name: str, key: str, namespace: Collection[str]) -> None:
19
23
  if key not in namespace:
20
- raise AttributeError(
24
+ raise Web3AttributeError(
21
25
  f"Property {key} not found on {class_name} class. "
22
26
  f"`{class_name}.factory` only accepts keyword arguments which are "
23
27
  f"present on the {class_name} class"
web3/_utils/decorators.py CHANGED
@@ -8,6 +8,10 @@ from typing import (
8
8
  )
9
9
  import warnings
10
10
 
11
+ from web3.exceptions import (
12
+ Web3ValueError,
13
+ )
14
+
11
15
  TFunc = TypeVar("TFunc", bound=Callable[..., Any])
12
16
 
13
17
 
@@ -24,7 +28,7 @@ def reject_recursive_repeats(to_wrap: Callable[..., Any]) -> Callable[..., Any]:
24
28
  thread_id = threading.get_ident()
25
29
  thread_local_args = (thread_id,) + arg_instances
26
30
  if thread_local_args in to_wrap.__already_called: # type: ignore
27
- raise ValueError(f"Recursively called {to_wrap} with {args!r}")
31
+ raise Web3ValueError(f"Recursively called {to_wrap} with {args!r}")
28
32
  to_wrap.__already_called[thread_local_args] = True # type: ignore
29
33
  try:
30
34
  wrapped_val = to_wrap(*args)
@@ -50,6 +54,7 @@ def deprecated_for(replace_message: str) -> Callable[..., Any]:
50
54
  warnings.warn(
51
55
  f"{to_wrap.__name__} is deprecated in favor of {replace_message}",
52
56
  category=DeprecationWarning,
57
+ stacklevel=2,
53
58
  )
54
59
  return to_wrap(*args, **kwargs)
55
60
 
web3/_utils/empty.py CHANGED
@@ -1,4 +1,4 @@
1
- from web3._utils.compat import (
1
+ from typing import (
2
2
  Literal,
3
3
  )
4
4