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/_utils/abi.py +59 -1
- web3/_utils/contract_sources/contract_data/event_contracts.py +49 -4
- web3/_utils/contracts.py +48 -7
- web3/_utils/method_formatters.py +1 -0
- web3/_utils/module_testing/eth_module.py +11 -0
- web3/_utils/rpc_abi.py +1 -0
- web3/_utils/validation.py +3 -0
- web3/contract/async_contract.py +159 -52
- web3/contract/base_contract.py +138 -102
- web3/contract/contract.py +154 -47
- web3/contract/utils.py +3 -2
- web3/eth/async_eth.py +11 -0
- web3/eth/eth.py +11 -0
- web3/providers/eth_tester/defaults.py +1 -0
- web3/utils/abi.py +308 -76
- {web3-7.5.0.dist-info → web3-7.6.0.dist-info}/METADATA +2 -2
- {web3-7.5.0.dist-info → web3-7.6.0.dist-info}/RECORD +20 -20
- {web3-7.5.0.dist-info → web3-7.6.0.dist-info}/LICENSE +0 -0
- {web3-7.5.0.dist-info → web3-7.6.0.dist-info}/WHEEL +0 -0
- {web3-7.5.0.dist-info → web3-7.6.0.dist-info}/top_level.txt +0 -0
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
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
270
|
+
abi,
|
|
252
271
|
self.w3.codec,
|
|
253
|
-
formatter=get_event_data(self.w3.codec,
|
|
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
|
-
|
|
278
|
-
if args
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
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
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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)(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
522
|
+
if super().__getattribute__("abi") is None:
|
|
441
523
|
raise NoABIFound(
|
|
442
524
|
"There is no ABI found for this contract.",
|
|
443
525
|
)
|
|
444
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
455
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
|
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
|
|
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(
|