dkg 0.1.0b6__py3-none-any.whl → 1.0.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 (43) hide show
  1. dkg/asset.py +106 -28
  2. dkg/constants.py +13 -9
  3. dkg/data/interfaces/ContentAsset.json +133 -3
  4. dkg/data/interfaces/Paranet.json +821 -0
  5. dkg/data/interfaces/{Identity.json → ParanetIncentivesPoolFactory.json} +67 -86
  6. dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json +919 -0
  7. dkg/data/interfaces/ParanetNeurowebIncentivesPool.json +1102 -0
  8. dkg/data/interfaces/{ServiceAgreementStorageV1.json → ParanetsRegistry.json} +331 -360
  9. dkg/dataclasses.py +28 -8
  10. dkg/main.py +6 -3
  11. dkg/method.py +55 -39
  12. dkg/module.py +1 -0
  13. dkg/network.py +20 -10
  14. dkg/paranet.py +477 -0
  15. dkg/providers/blockchain.py +57 -26
  16. dkg/types/__init__.py +1 -0
  17. dkg/types/general.py +44 -0
  18. dkg/utils/blockchain_request.py +149 -4
  19. dkg/utils/node_request.py +77 -80
  20. {dkg-0.1.0b6.dist-info → dkg-1.0.0.dist-info}/METADATA +3 -141
  21. dkg-1.0.0.dist-info/NOTICE +9 -0
  22. dkg-1.0.0.dist-info/RECORD +52 -0
  23. {dkg-0.1.0b6.dist-info → dkg-1.0.0.dist-info}/WHEEL +1 -1
  24. dkg/data/interfaces/Assertion.json +0 -157
  25. dkg/data/interfaces/CommitManagerV1.json +0 -549
  26. dkg/data/interfaces/CommitManagerV1U1.json +0 -735
  27. dkg/data/interfaces/HashingProxy.json +0 -253
  28. dkg/data/interfaces/IdentityStorage.json +0 -342
  29. dkg/data/interfaces/ParametersStorage.json +0 -487
  30. dkg/data/interfaces/Profile.json +0 -318
  31. dkg/data/interfaces/ProfileStorage.json +0 -596
  32. dkg/data/interfaces/ProofManagerV1.json +0 -540
  33. dkg/data/interfaces/ProofManagerV1U1.json +0 -561
  34. dkg/data/interfaces/ScoringProxy.json +0 -268
  35. dkg/data/interfaces/ServiceAgreementStorageV1U1.json +0 -1097
  36. dkg/data/interfaces/ServiceAgreementV1.json +0 -745
  37. dkg/data/interfaces/ShardingTable.json +0 -294
  38. dkg/data/interfaces/ShardingTableStorage.json +0 -317
  39. dkg/data/interfaces/Staking.json +0 -482
  40. dkg/data/interfaces/StakingStorage.json +0 -407
  41. dkg/data/interfaces/WhitelistStorage.json +0 -124
  42. dkg-0.1.0b6.dist-info/RECORD +0 -64
  43. {dkg-0.1.0b6.dist-info → dkg-1.0.0.dist-info}/LICENSE +0 -0
dkg/paranet.py ADDED
@@ -0,0 +1,477 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ import json
19
+
20
+ from dataclasses import dataclass
21
+ from web3 import Web3
22
+ from web3.contract import Contract
23
+ from web3.types import TxReceipt
24
+
25
+ from dkg.dataclasses import BaseIncentivesPoolParams, ParanetIncentivizationType
26
+ from dkg.manager import DefaultRequestManager
27
+ from dkg.method import Method
28
+ from dkg.module import Module
29
+ from dkg.types import Address, UAL, HexStr
30
+ from dkg.utils.blockchain_request import BlockchainRequest
31
+ from dkg.utils.ual import parse_ual
32
+
33
+
34
+ class Paranet(Module):
35
+ @dataclass
36
+ class NeuroWebIncentivesPoolParams(BaseIncentivesPoolParams):
37
+ neuro_emission_multiplier: float
38
+ operator_percentage: float
39
+ voters_percentage: float
40
+
41
+ def to_contract_args(self) -> dict:
42
+ return {
43
+ "tracToNeuroEmissionMultiplier": int(
44
+ self.neuro_emission_multiplier * (10**12)
45
+ ),
46
+ "paranetOperatorRewardPercentage": int(self.operator_percentage * 100),
47
+ "paranetIncentivizationProposalVotersRewardPercentage": int(
48
+ self.voters_percentage * 100
49
+ ),
50
+ }
51
+
52
+ def __init__(self, manager: DefaultRequestManager):
53
+ self.manager = manager
54
+ self.incentives_pools_deployment_functions = {
55
+ ParanetIncentivizationType.NEUROWEB: self._deploy_neuro_incentives_pool,
56
+ }
57
+
58
+ _register_paranet = Method(BlockchainRequest.register_paranet)
59
+
60
+ def create(
61
+ self, ual: UAL, name: str, description: str
62
+ ) -> dict[str, str | HexStr | TxReceipt]:
63
+ parsed_ual = parse_ual(ual)
64
+ knowledge_asset_storage, knowledge_asset_token_id = (
65
+ parsed_ual["contract_address"],
66
+ parsed_ual["token_id"],
67
+ )
68
+
69
+ receipt: TxReceipt = self._register_paranet(
70
+ knowledge_asset_storage,
71
+ knowledge_asset_token_id,
72
+ name,
73
+ description,
74
+ )
75
+
76
+ return {
77
+ "paranetUAL": ual,
78
+ "paranetId": Web3.to_hex(
79
+ Web3.solidity_keccak(
80
+ ["address", "uint256"],
81
+ [knowledge_asset_storage, knowledge_asset_token_id],
82
+ )
83
+ ),
84
+ "operation": json.loads(Web3.to_json(receipt)),
85
+ }
86
+
87
+ _deploy_neuro_incentives_pool = Method(
88
+ BlockchainRequest.deploy_neuro_incentives_pool
89
+ )
90
+
91
+ def deploy_incentives_contract(
92
+ self,
93
+ ual: UAL,
94
+ incentives_pool_parameters: NeuroWebIncentivesPoolParams,
95
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
96
+ ) -> dict[str, str | HexStr | TxReceipt]:
97
+ deploy_incentives_pool_fn = self.incentives_pools_deployment_functions.get(
98
+ incentives_type,
99
+ None,
100
+ )
101
+
102
+ if deploy_incentives_pool_fn is None:
103
+ raise ValueError(
104
+ f"{incentives_type} Incentive Type isn't supported. Supported "
105
+ f"Incentive Types: {self.incentives_pools_deployment_functions.keys()}"
106
+ )
107
+
108
+ parsed_ual = parse_ual(ual)
109
+ knowledge_asset_storage, knowledge_asset_token_id = (
110
+ parsed_ual["contract_address"],
111
+ parsed_ual["token_id"],
112
+ )
113
+
114
+ receipt: TxReceipt = deploy_incentives_pool_fn(
115
+ knowledge_asset_storage,
116
+ knowledge_asset_token_id,
117
+ **incentives_pool_parameters.to_contract_args(),
118
+ )
119
+
120
+ events = self.manager.blockchain_provider.decode_logs_event(
121
+ receipt,
122
+ "ParanetIncentivesPoolFactory",
123
+ "ParanetIncetivesPoolDeployed",
124
+ )
125
+
126
+ return {
127
+ "paranetUAL": ual,
128
+ "paranetId": Web3.to_hex(
129
+ Web3.solidity_keccak(
130
+ ["address", "uint256"],
131
+ [knowledge_asset_storage, knowledge_asset_token_id],
132
+ )
133
+ ),
134
+ "incentivesPoolAddress": events[0].args["incentivesPool"]["addr"],
135
+ "operation": json.loads(Web3.to_json(receipt)),
136
+ }
137
+
138
+ _get_incentives_pool_address = Method(BlockchainRequest.get_incentives_pool_address)
139
+
140
+ def get_incentives_pool_address(
141
+ self,
142
+ ual: UAL,
143
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
144
+ ) -> Address:
145
+ parsed_ual = parse_ual(ual)
146
+ knowledge_asset_storage, knowledge_asset_token_id = (
147
+ parsed_ual["contract_address"],
148
+ parsed_ual["token_id"],
149
+ )
150
+ paranet_id = Web3.solidity_keccak(
151
+ ["address", "uint256"], [knowledge_asset_storage, knowledge_asset_token_id]
152
+ )
153
+
154
+ return self._get_incentives_pool_address(paranet_id, incentives_type)
155
+
156
+ _register_paranet_service = Method(BlockchainRequest.register_paranet_service)
157
+
158
+ def create_service(
159
+ self, ual: UAL, name: str, description: str, addresses: list[Address]
160
+ ) -> dict[str, str | HexStr | TxReceipt]:
161
+ parsed_ual = parse_ual(ual)
162
+ knowledge_asset_storage, knowledge_asset_token_id = (
163
+ parsed_ual["contract_address"],
164
+ parsed_ual["token_id"],
165
+ )
166
+
167
+ receipt: TxReceipt = self._register_paranet_service(
168
+ knowledge_asset_storage,
169
+ knowledge_asset_token_id,
170
+ name,
171
+ description,
172
+ addresses,
173
+ )
174
+
175
+ return {
176
+ "paranetServiceUAL": ual,
177
+ "paranetServiceId": Web3.to_hex(
178
+ Web3.solidity_keccak(
179
+ ["address", "uint256"],
180
+ [knowledge_asset_storage, knowledge_asset_token_id],
181
+ )
182
+ ),
183
+ "operation": json.loads(Web3.to_json(receipt)),
184
+ }
185
+
186
+ _add_paranet_services = Method(BlockchainRequest.add_paranet_services)
187
+
188
+ def add_services(
189
+ self, ual: UAL, services_uals: list[UAL]
190
+ ) -> dict[str, str | HexStr | TxReceipt]:
191
+ parsed_paranet_ual = parse_ual(ual)
192
+ paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = (
193
+ parsed_paranet_ual["contract_address"],
194
+ parsed_paranet_ual["token_id"],
195
+ )
196
+
197
+ parsed_service_uals = []
198
+ for service_ual in services_uals:
199
+ parsed_service_ual = parse_ual(service_ual)
200
+ (service_knowledge_asset_storage, service_knowledge_asset_token_id) = (
201
+ parsed_service_ual["contract_address"],
202
+ parsed_service_ual["token_id"],
203
+ )
204
+
205
+ parsed_service_uals.append(
206
+ {
207
+ "knowledgeAssetStorageContract": service_knowledge_asset_storage,
208
+ "tokenId": service_knowledge_asset_token_id,
209
+ }
210
+ )
211
+
212
+ receipt: TxReceipt = self._add_paranet_services(
213
+ paranet_knowledge_asset_storage,
214
+ paranet_knowledge_asset_token_id,
215
+ parsed_service_uals,
216
+ )
217
+
218
+ return {
219
+ "paranetUAL": ual,
220
+ "paranetId": Web3.to_hex(
221
+ Web3.solidity_keccak(
222
+ ["address", "uint256"],
223
+ [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id],
224
+ )
225
+ ),
226
+ "operation": json.loads(Web3.to_json(receipt)),
227
+ }
228
+
229
+ _is_knowledge_miner_registered = Method(
230
+ BlockchainRequest.is_knowledge_miner_registered
231
+ )
232
+
233
+ def is_knowledge_miner(self, ual: UAL, address: Address | None = None) -> bool:
234
+ parsed_ual = parse_ual(ual)
235
+ knowledge_asset_storage, knowledge_asset_token_id = (
236
+ parsed_ual["contract_address"],
237
+ parsed_ual["token_id"],
238
+ )
239
+
240
+ paranet_id = Web3.solidity_keccak(
241
+ ["address", "uint256"], [knowledge_asset_storage, knowledge_asset_token_id]
242
+ )
243
+
244
+ return self._is_knowledge_miner_registered(
245
+ paranet_id, address or self.manager.blockchain_provider.account.address
246
+ )
247
+
248
+ _owner_of = Method(BlockchainRequest.owner_of)
249
+
250
+ def is_operator(self, ual: UAL, address: Address | None = None) -> bool:
251
+ knowledge_asset_token_id = parse_ual(ual)["token_id"]
252
+
253
+ return self._owner_of(knowledge_asset_token_id) == (
254
+ address or self.manager.blockchain_provider.account.address
255
+ )
256
+
257
+ _is_proposal_voter = Method(BlockchainRequest.is_proposal_voter)
258
+
259
+ def is_voter(
260
+ self,
261
+ ual: UAL,
262
+ address: Address | None = None,
263
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
264
+ ) -> bool:
265
+ return self._is_proposal_voter(
266
+ contract=self._get_incentives_pool_contract(ual, incentives_type),
267
+ addr=address or self.manager.blockchain_provider.account.address,
268
+ )
269
+
270
+ _get_claimable_knowledge_miner_reward_amount = Method(
271
+ BlockchainRequest.get_claimable_knowledge_miner_reward_amount
272
+ )
273
+
274
+ def calculate_claimable_miner_reward_amount(
275
+ self,
276
+ ual: UAL,
277
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
278
+ ) -> int:
279
+ return self._get_claimable_knowledge_miner_reward_amount(
280
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
281
+ )
282
+
283
+ _get_claimable_all_knowledge_miners_reward_amount = Method(
284
+ BlockchainRequest.get_claimable_all_knowledge_miners_reward_amount
285
+ )
286
+
287
+ def calculate_all_claimable_miner_rewards_amount(
288
+ self,
289
+ ual: UAL,
290
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
291
+ ) -> int:
292
+ return self._get_claimable_all_knowledge_miners_reward_amount(
293
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
294
+ )
295
+
296
+ _claim_knowledge_miner_reward = Method(
297
+ BlockchainRequest.claim_knowledge_miner_reward
298
+ )
299
+
300
+ def claim_miner_reward(
301
+ self,
302
+ ual: UAL,
303
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
304
+ ) -> dict[str, str | HexStr | TxReceipt]:
305
+ receipt: TxReceipt = self._claim_knowledge_miner_reward(
306
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
307
+ )
308
+
309
+ parsed_ual = parse_ual(ual)
310
+ knowledge_asset_storage, knowledge_asset_token_id = (
311
+ parsed_ual["contract_address"],
312
+ parsed_ual["token_id"],
313
+ )
314
+
315
+ return {
316
+ "paranetUAL": ual,
317
+ "paranetId": Web3.to_hex(
318
+ Web3.solidity_keccak(
319
+ ["address", "uint256"],
320
+ [knowledge_asset_storage, knowledge_asset_token_id],
321
+ )
322
+ ),
323
+ "operation": json.loads(Web3.to_json(receipt)),
324
+ }
325
+
326
+ _get_claimable_paranet_operator_reward_amount = Method(
327
+ BlockchainRequest.get_claimable_paranet_operator_reward_amount
328
+ )
329
+
330
+ def calculate_claimable_operator_reward_amount(
331
+ self,
332
+ ual: UAL,
333
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
334
+ ) -> int:
335
+ return self._get_claimable_paranet_operator_reward_amount(
336
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
337
+ )
338
+
339
+ _claim_paranet_operator_reward = Method(
340
+ BlockchainRequest.claim_paranet_operator_reward
341
+ )
342
+
343
+ def claim_operator_reward(
344
+ self,
345
+ ual: UAL,
346
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
347
+ ) -> dict[str, str | HexStr | TxReceipt]:
348
+ receipt: TxReceipt = self._claim_paranet_operator_reward(
349
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
350
+ )
351
+
352
+ parsed_ual = parse_ual(ual)
353
+ knowledge_asset_storage, knowledge_asset_token_id = (
354
+ parsed_ual["contract_address"],
355
+ parsed_ual["token_id"],
356
+ )
357
+
358
+ return {
359
+ "paranetUAL": ual,
360
+ "paranetId": Web3.to_hex(
361
+ Web3.solidity_keccak(
362
+ ["address", "uint256"],
363
+ [knowledge_asset_storage, knowledge_asset_token_id],
364
+ )
365
+ ),
366
+ "operation": json.loads(Web3.to_json(receipt)),
367
+ }
368
+
369
+ _get_claimable_proposal_voter_reward_amount = Method(
370
+ BlockchainRequest.get_claimable_proposal_voter_reward_amount
371
+ )
372
+
373
+ def calculate_claimable_voter_reward_amount(
374
+ self,
375
+ ual: UAL,
376
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
377
+ ) -> int:
378
+ return self._get_claimable_proposal_voter_reward_amount(
379
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
380
+ )
381
+
382
+ _get_claimable_all_proposal_voters_reward_amount = Method(
383
+ BlockchainRequest.get_claimable_all_proposal_voters_reward_amount
384
+ )
385
+
386
+ def calculate_all_claimable_voters_reward_amount(
387
+ self,
388
+ ual: UAL,
389
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
390
+ ) -> int:
391
+ return self._get_claimable_all_proposal_voters_reward_amount(
392
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
393
+ )
394
+
395
+ _claim_incentivization_proposal_voter_reward = Method(
396
+ BlockchainRequest.claim_incentivization_proposal_voter_reward
397
+ )
398
+
399
+ def claim_voter_reward(
400
+ self,
401
+ ual: UAL,
402
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
403
+ ) -> dict[str, str | HexStr | TxReceipt]:
404
+ receipt: TxReceipt = self._claim_incentivization_proposal_voter_reward(
405
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
406
+ )
407
+
408
+ parsed_ual = parse_ual(ual)
409
+ knowledge_asset_storage, knowledge_asset_token_id = (
410
+ parsed_ual["contract_address"],
411
+ parsed_ual["token_id"],
412
+ )
413
+
414
+ return {
415
+ "paranetUAL": ual,
416
+ "paranetId": Web3.to_hex(
417
+ Web3.solidity_keccak(
418
+ ["address", "uint256"],
419
+ [knowledge_asset_storage, knowledge_asset_token_id],
420
+ )
421
+ ),
422
+ "operation": json.loads(Web3.to_json(receipt)),
423
+ }
424
+
425
+ _get_updating_knowledge_asset_states = Method(
426
+ BlockchainRequest.get_updating_knowledge_asset_states
427
+ )
428
+ _process_updated_knowledge_asset_states_metadata = Method(
429
+ BlockchainRequest.process_updated_knowledge_asset_states_metadata
430
+ )
431
+
432
+ def update_claimable_rewards(self, ual: UAL) -> dict[str, str | HexStr | TxReceipt]:
433
+ parsed_ual = parse_ual(ual)
434
+ knowledge_asset_storage, knowledge_asset_token_id = (
435
+ parsed_ual["contract_address"],
436
+ parsed_ual["token_id"],
437
+ )
438
+
439
+ paranet_id = Web3.solidity_keccak(
440
+ ["address", "uint256"], [knowledge_asset_storage, knowledge_asset_token_id]
441
+ )
442
+
443
+ updating_states = self._get_updating_knowledge_asset_states(
444
+ self.manager.blockchain_provider.account.address,
445
+ paranet_id,
446
+ )
447
+ receipt: TxReceipt = self._process_updated_knowledge_asset_states_metadata(
448
+ knowledge_asset_storage,
449
+ knowledge_asset_token_id,
450
+ 0,
451
+ len(updating_states),
452
+ )
453
+
454
+ return {
455
+ "paranetUAL": ual,
456
+ "paranetId": paranet_id,
457
+ "operation": json.loads(Web3.to_json(receipt)),
458
+ }
459
+
460
+ def _get_incentives_pool_contract(
461
+ self,
462
+ ual: UAL,
463
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
464
+ ) -> str | dict[str, str]:
465
+ incentives_pool_name = f"Paranet{str(incentives_type)}IncentivesPool"
466
+ is_incentives_pool_cached = (
467
+ incentives_pool_name in self.manager.blockchain_provider.contracts.keys()
468
+ )
469
+
470
+ return (
471
+ incentives_pool_name
472
+ if is_incentives_pool_cached
473
+ else {
474
+ "name": incentives_pool_name,
475
+ "address": self.get_incentives_pool_address(ual, incentives_type),
476
+ }
477
+ )
@@ -24,8 +24,12 @@ from typing import Any, Type
24
24
 
25
25
  import requests
26
26
  from dkg.constants import BLOCKCHAINS, DEFAULT_GAS_PRICE_GWEI
27
- from dkg.exceptions import (AccountMissing, EnvironmentNotSupported,
28
- NetworkNotSupported, RPCURINotDefined)
27
+ from dkg.exceptions import (
28
+ AccountMissing,
29
+ EnvironmentNotSupported,
30
+ NetworkNotSupported,
31
+ RPCURINotDefined,
32
+ )
29
33
  from dkg.types import URI, Address, DataHexStr, Environment, Wei
30
34
  from eth_account.signers.local import LocalAccount
31
35
  from web3 import Web3
@@ -96,13 +100,14 @@ class BlockchainProvider:
96
100
  "Hub": self.w3.eth.contract(
97
101
  address=hub_address,
98
102
  abi=self.abi["Hub"],
103
+ decode_tuples=True,
99
104
  )
100
105
  }
101
106
  self._init_contracts()
102
107
 
103
108
  if (
104
- private_key is not None or
105
- (private_key_env := os.environ.get("PRIVATE_KEY", None)) is not None
109
+ private_key is not None
110
+ or (private_key_env := os.environ.get("PRIVATE_KEY", None)) is not None
106
111
  ):
107
112
  self.set_account(private_key or private_key_env)
108
113
 
@@ -125,33 +130,48 @@ class BlockchainProvider:
125
130
  except Exception as err:
126
131
  if (
127
132
  contract_name
133
+ and isinstance(contract_name, str)
128
134
  and any(msg in str(err) for msg in ["revert", "VM Exception"])
129
135
  and not self._check_contract_status(contract_name)
130
136
  ):
131
- self._update_contract_instance(contract_name)
132
- return func(self, *args, **kwargs)
133
- raise
137
+ is_updated = self._update_contract_instance(contract_name)
138
+ if is_updated:
139
+ return func(self, *args, **kwargs)
140
+ raise err
134
141
 
135
142
  return wrapper
136
143
 
137
144
  @handle_updated_contract
138
145
  def call_function(
139
146
  self,
140
- contract: str,
147
+ contract: str | dict[str, str],
141
148
  function: str,
142
149
  args: dict[str, Any] = {},
143
150
  state_changing: bool = False,
144
151
  gas_price: Wei | None = None,
145
152
  gas_limit: Wei | None = None,
146
153
  ) -> TxReceipt | Any:
147
- contract_instance = self.contracts[contract]
154
+ if isinstance(contract, str):
155
+ contract_name = contract
156
+ contract_instance = self.contracts[contract_name]
157
+ else:
158
+ contract_name = contract["name"]
159
+ contract_instance = self.w3.eth.contract(
160
+ address=contract["address"],
161
+ abi=self.abi[contract_name],
162
+ decode_tuples=True,
163
+ )
164
+ self.contracts[contract_name] = contract_instance
165
+
148
166
  contract_function: ContractFunction = getattr(
149
167
  contract_instance.functions, function
150
168
  )
151
169
 
152
170
  if not state_changing:
153
171
  result = contract_function(**args).call()
154
- if function in (output_named_tuples := self.output_named_tuples[contract]):
172
+ if function in (
173
+ output_named_tuples := self.output_named_tuples[contract_name]
174
+ ):
155
175
  result = output_named_tuples[function](*result)
156
176
  return result
157
177
  else:
@@ -190,11 +210,13 @@ class BlockchainProvider:
190
210
  self.w3.eth.default_account = self.account.address
191
211
 
192
212
  def _get_network_gas_price(self) -> Wei | None:
213
+ if self.environment == "development":
214
+ return None
215
+
193
216
  blockchain_name, _ = self.blockchain_id.split(":")
194
217
 
195
218
  default_gas_price = self.w3.to_wei(
196
- DEFAULT_GAS_PRICE_GWEI[blockchain_name],
197
- "gwei"
219
+ DEFAULT_GAS_PRICE_GWEI[blockchain_name], "gwei"
198
220
  )
199
221
 
200
222
  def fetch_gas_price(oracle_url: str) -> Wei | None:
@@ -204,9 +226,9 @@ class BlockchainProvider:
204
226
  data: dict = response.json()
205
227
 
206
228
  if "result" in data:
207
- return int(data['result'], 16)
229
+ return int(data["result"], 16)
208
230
  elif "average" in data:
209
- return self.w3.to_wei(data['average'], 'gwei')
231
+ return self.w3.to_wei(data["average"], "gwei")
210
232
  else:
211
233
  return None
212
234
  except Exception:
@@ -221,7 +243,7 @@ class BlockchainProvider:
221
243
  gas_price = fetch_gas_price(oracle_url)
222
244
  if gas_price is not None:
223
245
  return gas_price
224
-
246
+
225
247
  return default_gas_price
226
248
 
227
249
  def _init_contracts(self):
@@ -231,17 +253,26 @@ class BlockchainProvider:
231
253
 
232
254
  self._update_contract_instance(contract)
233
255
 
234
- def _update_contract_instance(self, contract: str):
235
- self.contracts[contract] = self.w3.eth.contract(
236
- address=(
237
- self.contracts["Hub"]
238
- .functions.getContractAddress(contract).call()
239
- if not contract.endswith("AssetStorage")
240
- else self.contracts["Hub"]
241
- .functions.getAssetStorageAddress(contract).call()
242
- ),
243
- abi=self.abi[contract],
244
- )
256
+ def _update_contract_instance(self, contract: str) -> bool:
257
+ if (
258
+ self.contracts["Hub"].functions.isContract(contractName=contract).call()
259
+ or self.contracts["Hub"]
260
+ .functions.isAssetStorage(assetStorageName=contract)
261
+ .call()
262
+ ):
263
+ self.contracts[contract] = self.w3.eth.contract(
264
+ address=(
265
+ self.contracts["Hub"].functions.getContractAddress(contract).call()
266
+ if not contract.endswith("AssetStorage")
267
+ else self.contracts["Hub"]
268
+ .functions.getAssetStorageAddress(contract)
269
+ .call()
270
+ ),
271
+ abi=self.abi[contract],
272
+ decode_tuples=True,
273
+ )
274
+ return True
275
+ return False
245
276
 
246
277
  def _check_contract_status(self, contract: str) -> bool:
247
278
  try:
dkg/types/__init__.py CHANGED
@@ -1,3 +1,4 @@
1
+ from .general import AutoStrEnum, AutoStrEnumCapitalize, AutoStrEnumUpperCase # NOQA: F401
1
2
  from .blockchain import (ABI, ABIElement, ABIError, ABIEvent, # NOQA: F401
2
3
  ABIFunction, ABIParameter, AgreementData, Environment)
3
4
  from .dkg_node import UAL # NOQA: F401
dkg/types/general.py ADDED
@@ -0,0 +1,44 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ from enum import Enum
19
+
20
+ class AutoStrEnum(str, Enum):
21
+ @staticmethod
22
+ def _generate_next_value_(name: str, start: int, count: int, last_values: list) -> str:
23
+ return name.lower()
24
+
25
+ def __str__(self):
26
+ return str(self.value)
27
+
28
+
29
+ class AutoStrEnumCapitalize(str, Enum):
30
+ @staticmethod
31
+ def _generate_next_value_(name: str, start: int, count: int, last_values: list) -> str:
32
+ return name.capitalize()
33
+
34
+ def __str__(self):
35
+ return str(self.value)
36
+
37
+
38
+ class AutoStrEnumUpperCase(str, Enum):
39
+ @staticmethod
40
+ def _generate_next_value_(name: str, start: int, count: int, last_values: list) -> str:
41
+ return name
42
+
43
+ def __str__(self):
44
+ return str(self.value)