web3 7.5.0__py3-none-any.whl → 7.6.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/contract/contract.py CHANGED
@@ -1,4 +1,3 @@
1
- import copy
2
1
  from typing import (
3
2
  TYPE_CHECKING,
4
3
  Any,
@@ -14,12 +13,13 @@ from typing import (
14
13
 
15
14
  from eth_typing import (
16
15
  ABI,
17
- ABIEvent,
18
16
  ChecksumAddress,
19
17
  )
20
18
  from eth_utils import (
19
+ abi_to_signature,
21
20
  combomethod,
22
21
  get_abi_input_names,
22
+ get_abi_input_types,
23
23
  get_all_function_abis,
24
24
  )
25
25
  from eth_utils.toolz import (
@@ -31,6 +31,9 @@ from hexbytes import (
31
31
 
32
32
  from web3._utils.abi import (
33
33
  fallback_func_abi_exists,
34
+ filter_by_types,
35
+ get_abi_element_signature,
36
+ get_name_from_abi_element_identifier,
34
37
  receive_func_abi_exists,
35
38
  )
36
39
  from web3._utils.abi_element_identifiers import (
@@ -41,6 +44,8 @@ from web3._utils.compat import (
41
44
  Self,
42
45
  )
43
46
  from web3._utils.contracts import (
47
+ copy_contract_event,
48
+ copy_contract_function,
44
49
  parse_block_identifier,
45
50
  )
46
51
  from web3._utils.datatypes import (
@@ -83,7 +88,9 @@ from web3.contract.utils import (
83
88
  transact_with_contract_function,
84
89
  )
85
90
  from web3.exceptions import (
91
+ ABIEventNotFound,
86
92
  ABIFunctionNotFound,
93
+ NoABIEventsFound,
87
94
  NoABIFound,
88
95
  NoABIFunctionsFound,
89
96
  Web3AttributeError,
@@ -98,6 +105,8 @@ from web3.types import (
98
105
  TxParams,
99
106
  )
100
107
  from web3.utils.abi import (
108
+ _get_any_abi_signature_with_name,
109
+ filter_abi_by_type,
101
110
  get_abi_element,
102
111
  )
103
112
 
@@ -110,16 +119,27 @@ class ContractEvent(BaseContractEvent):
110
119
  # mypy types
111
120
  w3: "Web3"
112
121
 
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
- )
122
+ def __call__(self, *args: Any, **kwargs: Any) -> "ContractEvent":
123
+ event_abi = get_abi_element(
124
+ filter_abi_by_type("event", self.contract_abi),
125
+ self.name,
126
+ *args,
127
+ abi_codec=self.w3.codec,
128
+ **kwargs,
129
+ )
130
+ argument_types = get_abi_input_types(event_abi)
131
+ event_signature = str(
132
+ get_abi_element_signature(self.abi_element_identifier, argument_types)
133
+ )
134
+ contract_event = ContractEvent.factory(
135
+ event_signature,
136
+ w3=self.w3,
137
+ contract_abi=self.contract_abi,
138
+ address=self.address,
139
+ abi_element_identifier=event_signature,
140
+ )
121
141
 
122
- return clone
142
+ return copy_contract_event(contract_event, *args, **kwargs)
123
143
 
124
144
  @combomethod
125
145
  def get_logs(
@@ -186,7 +206,6 @@ class ContractEvent(BaseContractEvent):
186
206
  :yield: Tuple of :class:`AttributeDict` instances
187
207
  """
188
208
  event_abi = self._get_event_abi()
189
-
190
209
  # validate ``argument_filters`` if present
191
210
  if argument_filters is not None:
192
211
  event_arg_names = get_abi_input_names(event_abi)
@@ -228,7 +247,8 @@ class ContractEvent(BaseContractEvent):
228
247
  """
229
248
  Create filter object that tracks logs emitted by this contract event.
230
249
  """
231
- filter_builder = EventFilterBuilder(self._get_event_abi(), self.w3.codec)
250
+ abi = self._get_event_abi()
251
+ filter_builder = EventFilterBuilder(abi, self.w3.codec)
232
252
  self._set_up_filter_builder(
233
253
  argument_filters,
234
254
  from_block,
@@ -238,28 +258,25 @@ class ContractEvent(BaseContractEvent):
238
258
  filter_builder,
239
259
  )
240
260
  log_filter = filter_builder.deploy(self.w3)
241
- log_filter.log_entry_formatter = get_event_data(
242
- self.w3.codec, self._get_event_abi()
243
- )
261
+ log_filter.log_entry_formatter = get_event_data(self.w3.codec, abi)
244
262
  log_filter.builder = filter_builder
245
263
 
246
264
  return log_filter
247
265
 
248
266
  @combomethod
249
267
  def build_filter(self) -> EventFilterBuilder:
268
+ abi = self._get_event_abi()
250
269
  builder = EventFilterBuilder(
251
- self._get_event_abi(),
270
+ abi,
252
271
  self.w3.codec,
253
- formatter=get_event_data(self.w3.codec, self._get_event_abi()),
272
+ formatter=get_event_data(self.w3.codec, abi),
254
273
  )
255
274
  builder.address = self.address
256
275
  return builder
257
276
 
258
277
  @classmethod
259
278
  def factory(cls, class_name: str, **kwargs: Any) -> Self:
260
- return PropertyCheckingFactory(class_name, (cls,), kwargs)(
261
- abi=kwargs.get("abi")
262
- )
279
+ return PropertyCheckingFactory(class_name, (cls,), kwargs)()
263
280
 
264
281
 
265
282
  class ContractEvents(BaseContractEvents):
@@ -268,28 +285,81 @@ class ContractEvents(BaseContractEvents):
268
285
  ) -> None:
269
286
  super().__init__(abi, w3, ContractEvent, address)
270
287
 
288
+ def __getattr__(self, event_name: str) -> "ContractEvent":
289
+ if super().__getattribute__("abi") is None:
290
+ raise NoABIFound(
291
+ "There is no ABI found for this contract.",
292
+ )
293
+ if "_events" not in self.__dict__ or len(self._events) == 0:
294
+ raise NoABIEventsFound(
295
+ "The abi for this contract contains no event definitions. ",
296
+ "Are you sure you provided the correct contract abi?",
297
+ )
298
+ elif get_name_from_abi_element_identifier(event_name) not in [
299
+ get_name_from_abi_element_identifier(event["name"])
300
+ for event in self._events
301
+ ]:
302
+ raise ABIEventNotFound(
303
+ f"The event '{event_name}' was not found in this contract's abi. ",
304
+ "Are you sure you provided the correct contract abi?",
305
+ )
306
+ else:
307
+ event_abi = get_abi_element(self._events, event_name)
308
+ argument_types = get_abi_input_types(event_abi)
309
+ event_signature = str(get_abi_element_signature(event_name, argument_types))
310
+ return super().__getattribute__(event_signature)
311
+
312
+ def __getitem__(self, event_name: str) -> "ContractEvent":
313
+ return getattr(self, event_name)
314
+
315
+ def __iter__(self) -> Iterable["ContractEvent"]:
316
+ for event in self._events:
317
+ yield self[event["name"]]
318
+
271
319
 
272
320
  class ContractFunction(BaseContractFunction):
273
321
  # mypy types
274
322
  w3: "Web3"
275
323
 
276
324
  def __call__(self, *args: Any, **kwargs: Any) -> "ContractFunction":
277
- clone = copy.copy(self)
278
- if args is None:
279
- clone.args = tuple()
280
- else:
281
- clone.args = args
325
+ element_name = self.abi_element_identifier
326
+ if element_name in ["fallback", "receive"] or len(args) + len(kwargs):
327
+ # Use only the name if a fallback, receive function
328
+ # or when args/kwargs are present to find the proper element
329
+ element_name = self.fn_name
330
+
331
+ function_abi = get_abi_element(
332
+ filter_by_types(
333
+ ["function", "constructor", "fallback", "receive"],
334
+ self.contract_abi,
335
+ ),
336
+ element_name,
337
+ *args,
338
+ abi_codec=self.w3.codec,
339
+ **kwargs,
340
+ )
282
341
 
283
- if kwargs is None:
284
- clone.kwargs = {}
285
- else:
286
- clone.kwargs = kwargs
287
- clone._set_function_info()
288
- return clone
342
+ argument_types = None
343
+ if function_abi["type"] not in ["fallback", "receive"]:
344
+ argument_types = get_abi_input_types(function_abi)
345
+
346
+ function_signature = str(
347
+ get_abi_element_signature(self.abi_element_identifier, argument_types)
348
+ )
349
+ contract_function = ContractFunction.factory(
350
+ function_signature,
351
+ w3=self.w3,
352
+ contract_abi=self.contract_abi,
353
+ address=self.address,
354
+ abi_element_identifier=function_signature,
355
+ decode_tuples=self.decode_tuples,
356
+ )
357
+
358
+ return copy_contract_function(contract_function, *args, **kwargs)
289
359
 
290
360
  @classmethod
291
361
  def factory(cls, class_name: str, **kwargs: Any) -> Self:
292
- return PropertyCheckingFactory(class_name, (cls,), kwargs)(kwargs.get("abi"))
362
+ return PropertyCheckingFactory(class_name, (cls,), kwargs)()
293
363
 
294
364
  def call(
295
365
  self,
@@ -329,11 +399,13 @@ class ContractFunction(BaseContractFunction):
329
399
 
330
400
  block_id = parse_block_identifier(self.w3, block_identifier)
331
401
 
402
+ abi_element_identifier = abi_to_signature(self.abi)
403
+
332
404
  return call_contract_function(
333
405
  self.w3,
334
406
  self.address,
335
407
  self._return_data_normalizers,
336
- self.abi_element_identifier,
408
+ abi_element_identifier,
337
409
  call_transaction,
338
410
  block_id,
339
411
  self.contract_abi,
@@ -347,11 +419,12 @@ class ContractFunction(BaseContractFunction):
347
419
 
348
420
  def transact(self, transaction: Optional[TxParams] = None) -> HexBytes:
349
421
  setup_transaction = self._transact(transaction)
422
+ abi_element_identifier = abi_to_signature(self.abi)
350
423
 
351
424
  return transact_with_contract_function(
352
425
  self.address,
353
426
  self.w3,
354
- self.abi_element_identifier,
427
+ abi_element_identifier,
355
428
  setup_transaction,
356
429
  self.contract_abi,
357
430
  self.abi,
@@ -366,10 +439,11 @@ class ContractFunction(BaseContractFunction):
366
439
  state_override: Optional[StateOverride] = None,
367
440
  ) -> int:
368
441
  setup_transaction = self._estimate_gas(transaction)
442
+ abi_element_identifier = abi_to_signature(self.abi)
369
443
  return estimate_gas_for_function(
370
444
  self.address,
371
445
  self.w3,
372
- self.abi_element_identifier,
446
+ abi_element_identifier,
373
447
  setup_transaction,
374
448
  self.contract_abi,
375
449
  self.abi,
@@ -381,11 +455,12 @@ class ContractFunction(BaseContractFunction):
381
455
 
382
456
  def build_transaction(self, transaction: Optional[TxParams] = None) -> TxParams:
383
457
  built_transaction = self._build_transaction(transaction)
458
+ abi_element_identifier = abi_to_signature(self.abi)
384
459
 
385
460
  return build_transaction_for_function(
386
461
  self.address,
387
462
  self.w3,
388
- self.abi_element_identifier,
463
+ abi_element_identifier,
389
464
  built_transaction,
390
465
  self.contract_abi,
391
466
  self.abi,
@@ -436,23 +511,45 @@ class ContractFunctions(BaseContractFunctions):
436
511
  ) -> None:
437
512
  super().__init__(abi, w3, ContractFunction, address, decode_tuples)
438
513
 
514
+ def __iter__(self) -> Iterable["ContractFunction"]:
515
+ if not hasattr(self, "_functions") or not self._functions:
516
+ return
517
+
518
+ for func in self._functions:
519
+ yield self[abi_to_signature(func)]
520
+
439
521
  def __getattr__(self, function_name: str) -> "ContractFunction":
440
- if self.abi is None:
522
+ if super().__getattribute__("abi") is None:
441
523
  raise NoABIFound(
442
524
  "There is no ABI found for this contract.",
443
525
  )
444
- if "_functions" not in self.__dict__:
526
+ elif "_functions" not in self.__dict__ or len(self._functions) == 0:
445
527
  raise NoABIFunctionsFound(
446
528
  "The abi for this contract contains no function definitions. ",
447
529
  "Are you sure you provided the correct contract abi?",
448
530
  )
449
- elif function_name not in self.__dict__["_functions"]:
531
+ elif get_name_from_abi_element_identifier(function_name) not in [
532
+ get_name_from_abi_element_identifier(function["name"])
533
+ for function in self._functions
534
+ ]:
450
535
  raise ABIFunctionNotFound(
451
- f"The function '{function_name}' was not found in this contract's abi.",
452
- " Are you sure you provided the correct contract abi?",
536
+ f"The function '{function_name}' was not found in this contract's "
537
+ "abi. Are you sure you provided the correct contract abi?",
538
+ )
539
+
540
+ function_identifier = function_name
541
+
542
+ if "(" not in function_name:
543
+ function_identifier = _get_any_abi_signature_with_name(
544
+ function_name, self._functions
453
545
  )
454
- else:
455
- return super().__getattribute__(function_name)
546
+
547
+ return super().__getattribute__(
548
+ function_identifier,
549
+ )
550
+
551
+ def __getitem__(self, function_name: str) -> "ContractFunction":
552
+ return getattr(self, function_name)
456
553
 
457
554
 
458
555
  class Contract(BaseContract):
@@ -526,6 +623,16 @@ class Contract(BaseContract):
526
623
  normalizers=normalizers,
527
624
  ),
528
625
  )
626
+
627
+ if contract.abi:
628
+ for abi in contract.abi:
629
+ abi_name = abi.get("name")
630
+ if abi_name in ["abi", "address"]:
631
+ raise Web3AttributeError(
632
+ f"Contract contains a reserved word `{abi_name}` "
633
+ f"and could not be instantiated."
634
+ )
635
+
529
636
  contract.functions = ContractFunctions(
530
637
  contract.abi, contract.w3, decode_tuples=contract.decode_tuples
531
638
  )
@@ -627,12 +734,12 @@ class ContractCaller(BaseContractCaller):
627
734
  self._functions = get_all_function_abis(self.abi)
628
735
 
629
736
  for func in self._functions:
737
+ abi_signature = abi_to_signature(func)
630
738
  fn = ContractFunction.factory(
631
- func["name"],
739
+ abi_signature,
632
740
  w3=w3,
633
741
  contract_abi=self.abi,
634
742
  address=self.address,
635
- abi_element_identifier=func["name"],
636
743
  decode_tuples=decode_tuples,
637
744
  )
638
745
 
@@ -644,7 +751,7 @@ class ContractCaller(BaseContractCaller):
644
751
  ccip_read_enabled=ccip_read_enabled,
645
752
  )
646
753
 
647
- setattr(self, func["name"], caller_method)
754
+ setattr(self, abi_signature, caller_method)
648
755
 
649
756
  def __call__(
650
757
  self,
web3/contract/utils.py CHANGED
@@ -23,6 +23,7 @@ from eth_typing import (
23
23
  TypeStr,
24
24
  )
25
25
  from eth_utils.abi import (
26
+ abi_to_signature,
26
27
  filter_abi_by_type,
27
28
  get_abi_output_types,
28
29
  )
@@ -345,11 +346,11 @@ def find_functions_by_identifier(
345
346
  fns_abi = filter_abi_by_type("function", contract_abi)
346
347
  return [
347
348
  function_type.factory(
348
- fn_abi["name"],
349
+ abi_to_signature(fn_abi),
349
350
  w3=w3,
350
351
  contract_abi=contract_abi,
351
352
  address=address,
352
- abi_element_identifier=fn_abi["name"],
353
+ abi_element_identifier=abi_to_signature(fn_abi),
353
354
  abi=fn_abi,
354
355
  )
355
356
  for fn_abi in fns_abi
web3/eth/async_eth.py CHANGED
@@ -127,6 +127,17 @@ class AsyncEth(BaseEth):
127
127
  async def accounts(self) -> Tuple[ChecksumAddress]:
128
128
  return await self._accounts()
129
129
 
130
+ # eth_blobBaseFee
131
+
132
+ _eth_blobBaseFee: Method[Callable[[], Awaitable[Wei]]] = Method(
133
+ RPC.eth_blobBaseFee,
134
+ is_property=True,
135
+ )
136
+
137
+ @property
138
+ async def blob_base_fee(self) -> Wei:
139
+ return await self._eth_blobBaseFee()
140
+
130
141
  # eth_blockNumber
131
142
 
132
143
  get_block_number: Method[Callable[[], Awaitable[BlockNumber]]] = Method(
web3/eth/eth.py CHANGED
@@ -119,6 +119,17 @@ class Eth(BaseEth):
119
119
  def accounts(self) -> Tuple[ChecksumAddress]:
120
120
  return self._accounts()
121
121
 
122
+ # eth_blobBaseFee
123
+
124
+ _eth_blobBaseFee: Method[Callable[[], Wei]] = Method(
125
+ RPC.eth_blobBaseFee,
126
+ is_property=True,
127
+ )
128
+
129
+ @property
130
+ def blob_base_fee(self) -> Wei:
131
+ return self._eth_blobBaseFee()
132
+
122
133
  # eth_blockNumber
123
134
 
124
135
  get_block_number: Method[Callable[[], BlockNumber]] = Method(
@@ -246,6 +246,7 @@ API_ENDPOINTS = {
246
246
  "chainId": static_return(131277322940537), # from fixture generation file
247
247
  "feeHistory": call_eth_tester("get_fee_history"),
248
248
  "maxPriorityFeePerGas": static_return(10**9),
249
+ "blobBaseFee": static_return(10**9),
249
250
  "gasPrice": static_return(10**9), # must be >= base fee post-London
250
251
  "accounts": call_eth_tester("get_accounts"),
251
252
  "blockNumber": compose(