dkg 0.1.0b6__py3-none-any.whl → 1.1.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 (44) hide show
  1. dkg/asset.py +106 -28
  2. dkg/constants.py +18 -10
  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/exceptions.py +1 -1
  11. dkg/main.py +6 -3
  12. dkg/method.py +55 -39
  13. dkg/module.py +1 -0
  14. dkg/network.py +20 -10
  15. dkg/paranet.py +476 -0
  16. dkg/providers/blockchain.py +57 -26
  17. dkg/types/__init__.py +1 -0
  18. dkg/types/general.py +44 -0
  19. dkg/utils/blockchain_request.py +149 -4
  20. dkg/utils/node_request.py +77 -80
  21. {dkg-0.1.0b6.dist-info → dkg-1.1.0.dist-info}/METADATA +3 -141
  22. dkg-1.1.0.dist-info/NOTICE +9 -0
  23. dkg-1.1.0.dist-info/RECORD +52 -0
  24. {dkg-0.1.0b6.dist-info → dkg-1.1.0.dist-info}/WHEEL +1 -1
  25. dkg/data/interfaces/Assertion.json +0 -157
  26. dkg/data/interfaces/CommitManagerV1.json +0 -549
  27. dkg/data/interfaces/CommitManagerV1U1.json +0 -735
  28. dkg/data/interfaces/HashingProxy.json +0 -253
  29. dkg/data/interfaces/IdentityStorage.json +0 -342
  30. dkg/data/interfaces/ParametersStorage.json +0 -487
  31. dkg/data/interfaces/Profile.json +0 -318
  32. dkg/data/interfaces/ProfileStorage.json +0 -596
  33. dkg/data/interfaces/ProofManagerV1.json +0 -540
  34. dkg/data/interfaces/ProofManagerV1U1.json +0 -561
  35. dkg/data/interfaces/ScoringProxy.json +0 -268
  36. dkg/data/interfaces/ServiceAgreementStorageV1U1.json +0 -1097
  37. dkg/data/interfaces/ServiceAgreementV1.json +0 -745
  38. dkg/data/interfaces/ShardingTable.json +0 -294
  39. dkg/data/interfaces/ShardingTableStorage.json +0 -317
  40. dkg/data/interfaces/Staking.json +0 -482
  41. dkg/data/interfaces/StakingStorage.json +0 -407
  42. dkg/data/interfaces/WhitelistStorage.json +0 -124
  43. dkg-0.1.0b6.dist-info/RECORD +0 -64
  44. {dkg-0.1.0b6.dist-info → dkg-1.1.0.dist-info}/LICENSE +0 -0
dkg/paranet.py ADDED
@@ -0,0 +1,476 @@
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.types import TxReceipt
23
+
24
+ from dkg.dataclasses import BaseIncentivesPoolParams, ParanetIncentivizationType
25
+ from dkg.manager import DefaultRequestManager
26
+ from dkg.method import Method
27
+ from dkg.module import Module
28
+ from dkg.types import Address, UAL, HexStr
29
+ from dkg.utils.blockchain_request import BlockchainRequest
30
+ from dkg.utils.ual import parse_ual
31
+
32
+
33
+ class Paranet(Module):
34
+ @dataclass
35
+ class NeuroWebIncentivesPoolParams(BaseIncentivesPoolParams):
36
+ neuro_emission_multiplier: float
37
+ operator_percentage: float
38
+ voters_percentage: float
39
+
40
+ def to_contract_args(self) -> dict:
41
+ return {
42
+ "tracToNeuroEmissionMultiplier": int(
43
+ self.neuro_emission_multiplier * (10**12)
44
+ ),
45
+ "paranetOperatorRewardPercentage": int(self.operator_percentage * 100),
46
+ "paranetIncentivizationProposalVotersRewardPercentage": int(
47
+ self.voters_percentage * 100
48
+ ),
49
+ }
50
+
51
+ def __init__(self, manager: DefaultRequestManager):
52
+ self.manager = manager
53
+ self.incentives_pools_deployment_functions = {
54
+ ParanetIncentivizationType.NEUROWEB: self._deploy_neuro_incentives_pool,
55
+ }
56
+
57
+ _register_paranet = Method(BlockchainRequest.register_paranet)
58
+
59
+ def create(
60
+ self, ual: UAL, name: str, description: str
61
+ ) -> dict[str, str | HexStr | TxReceipt]:
62
+ parsed_ual = parse_ual(ual)
63
+ knowledge_asset_storage, knowledge_asset_token_id = (
64
+ parsed_ual["contract_address"],
65
+ parsed_ual["token_id"],
66
+ )
67
+
68
+ receipt: TxReceipt = self._register_paranet(
69
+ knowledge_asset_storage,
70
+ knowledge_asset_token_id,
71
+ name,
72
+ description,
73
+ )
74
+
75
+ return {
76
+ "paranetUAL": ual,
77
+ "paranetId": Web3.to_hex(
78
+ Web3.solidity_keccak(
79
+ ["address", "uint256"],
80
+ [knowledge_asset_storage, knowledge_asset_token_id],
81
+ )
82
+ ),
83
+ "operation": json.loads(Web3.to_json(receipt)),
84
+ }
85
+
86
+ _deploy_neuro_incentives_pool = Method(
87
+ BlockchainRequest.deploy_neuro_incentives_pool
88
+ )
89
+
90
+ def deploy_incentives_contract(
91
+ self,
92
+ ual: UAL,
93
+ incentives_pool_parameters: NeuroWebIncentivesPoolParams,
94
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
95
+ ) -> dict[str, str | HexStr | TxReceipt]:
96
+ deploy_incentives_pool_fn = self.incentives_pools_deployment_functions.get(
97
+ incentives_type,
98
+ None,
99
+ )
100
+
101
+ if deploy_incentives_pool_fn is None:
102
+ raise ValueError(
103
+ f"{incentives_type} Incentive Type isn't supported. Supported "
104
+ f"Incentive Types: {self.incentives_pools_deployment_functions.keys()}"
105
+ )
106
+
107
+ parsed_ual = parse_ual(ual)
108
+ knowledge_asset_storage, knowledge_asset_token_id = (
109
+ parsed_ual["contract_address"],
110
+ parsed_ual["token_id"],
111
+ )
112
+
113
+ receipt: TxReceipt = deploy_incentives_pool_fn(
114
+ knowledge_asset_storage,
115
+ knowledge_asset_token_id,
116
+ **incentives_pool_parameters.to_contract_args(),
117
+ )
118
+
119
+ events = self.manager.blockchain_provider.decode_logs_event(
120
+ receipt,
121
+ "ParanetIncentivesPoolFactory",
122
+ "ParanetIncetivesPoolDeployed",
123
+ )
124
+
125
+ return {
126
+ "paranetUAL": ual,
127
+ "paranetId": Web3.to_hex(
128
+ Web3.solidity_keccak(
129
+ ["address", "uint256"],
130
+ [knowledge_asset_storage, knowledge_asset_token_id],
131
+ )
132
+ ),
133
+ "incentivesPoolAddress": events[0].args["incentivesPool"]["addr"],
134
+ "operation": json.loads(Web3.to_json(receipt)),
135
+ }
136
+
137
+ _get_incentives_pool_address = Method(BlockchainRequest.get_incentives_pool_address)
138
+
139
+ def get_incentives_pool_address(
140
+ self,
141
+ ual: UAL,
142
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
143
+ ) -> Address:
144
+ parsed_ual = parse_ual(ual)
145
+ knowledge_asset_storage, knowledge_asset_token_id = (
146
+ parsed_ual["contract_address"],
147
+ parsed_ual["token_id"],
148
+ )
149
+ paranet_id = Web3.solidity_keccak(
150
+ ["address", "uint256"], [knowledge_asset_storage, knowledge_asset_token_id]
151
+ )
152
+
153
+ return self._get_incentives_pool_address(paranet_id, incentives_type)
154
+
155
+ _register_paranet_service = Method(BlockchainRequest.register_paranet_service)
156
+
157
+ def create_service(
158
+ self, ual: UAL, name: str, description: str, addresses: list[Address]
159
+ ) -> dict[str, str | HexStr | TxReceipt]:
160
+ parsed_ual = parse_ual(ual)
161
+ knowledge_asset_storage, knowledge_asset_token_id = (
162
+ parsed_ual["contract_address"],
163
+ parsed_ual["token_id"],
164
+ )
165
+
166
+ receipt: TxReceipt = self._register_paranet_service(
167
+ knowledge_asset_storage,
168
+ knowledge_asset_token_id,
169
+ name,
170
+ description,
171
+ addresses,
172
+ )
173
+
174
+ return {
175
+ "paranetServiceUAL": ual,
176
+ "paranetServiceId": Web3.to_hex(
177
+ Web3.solidity_keccak(
178
+ ["address", "uint256"],
179
+ [knowledge_asset_storage, knowledge_asset_token_id],
180
+ )
181
+ ),
182
+ "operation": json.loads(Web3.to_json(receipt)),
183
+ }
184
+
185
+ _add_paranet_services = Method(BlockchainRequest.add_paranet_services)
186
+
187
+ def add_services(
188
+ self, ual: UAL, services_uals: list[UAL]
189
+ ) -> dict[str, str | HexStr | TxReceipt]:
190
+ parsed_paranet_ual = parse_ual(ual)
191
+ paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = (
192
+ parsed_paranet_ual["contract_address"],
193
+ parsed_paranet_ual["token_id"],
194
+ )
195
+
196
+ parsed_service_uals = []
197
+ for service_ual in services_uals:
198
+ parsed_service_ual = parse_ual(service_ual)
199
+ (service_knowledge_asset_storage, service_knowledge_asset_token_id) = (
200
+ parsed_service_ual["contract_address"],
201
+ parsed_service_ual["token_id"],
202
+ )
203
+
204
+ parsed_service_uals.append(
205
+ {
206
+ "knowledgeAssetStorageContract": service_knowledge_asset_storage,
207
+ "tokenId": service_knowledge_asset_token_id,
208
+ }
209
+ )
210
+
211
+ receipt: TxReceipt = self._add_paranet_services(
212
+ paranet_knowledge_asset_storage,
213
+ paranet_knowledge_asset_token_id,
214
+ parsed_service_uals,
215
+ )
216
+
217
+ return {
218
+ "paranetUAL": ual,
219
+ "paranetId": Web3.to_hex(
220
+ Web3.solidity_keccak(
221
+ ["address", "uint256"],
222
+ [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id],
223
+ )
224
+ ),
225
+ "operation": json.loads(Web3.to_json(receipt)),
226
+ }
227
+
228
+ _is_knowledge_miner_registered = Method(
229
+ BlockchainRequest.is_knowledge_miner_registered
230
+ )
231
+
232
+ def is_knowledge_miner(self, ual: UAL, address: Address | None = None) -> bool:
233
+ parsed_ual = parse_ual(ual)
234
+ knowledge_asset_storage, knowledge_asset_token_id = (
235
+ parsed_ual["contract_address"],
236
+ parsed_ual["token_id"],
237
+ )
238
+
239
+ paranet_id = Web3.solidity_keccak(
240
+ ["address", "uint256"], [knowledge_asset_storage, knowledge_asset_token_id]
241
+ )
242
+
243
+ return self._is_knowledge_miner_registered(
244
+ paranet_id, address or self.manager.blockchain_provider.account.address
245
+ )
246
+
247
+ _owner_of = Method(BlockchainRequest.owner_of)
248
+
249
+ def is_operator(self, ual: UAL, address: Address | None = None) -> bool:
250
+ knowledge_asset_token_id = parse_ual(ual)["token_id"]
251
+
252
+ return self._owner_of(knowledge_asset_token_id) == (
253
+ address or self.manager.blockchain_provider.account.address
254
+ )
255
+
256
+ _is_proposal_voter = Method(BlockchainRequest.is_proposal_voter)
257
+
258
+ def is_voter(
259
+ self,
260
+ ual: UAL,
261
+ address: Address | None = None,
262
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
263
+ ) -> bool:
264
+ return self._is_proposal_voter(
265
+ contract=self._get_incentives_pool_contract(ual, incentives_type),
266
+ addr=address or self.manager.blockchain_provider.account.address,
267
+ )
268
+
269
+ _get_claimable_knowledge_miner_reward_amount = Method(
270
+ BlockchainRequest.get_claimable_knowledge_miner_reward_amount
271
+ )
272
+
273
+ def calculate_claimable_miner_reward_amount(
274
+ self,
275
+ ual: UAL,
276
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
277
+ ) -> int:
278
+ return self._get_claimable_knowledge_miner_reward_amount(
279
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
280
+ )
281
+
282
+ _get_claimable_all_knowledge_miners_reward_amount = Method(
283
+ BlockchainRequest.get_claimable_all_knowledge_miners_reward_amount
284
+ )
285
+
286
+ def calculate_all_claimable_miner_rewards_amount(
287
+ self,
288
+ ual: UAL,
289
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
290
+ ) -> int:
291
+ return self._get_claimable_all_knowledge_miners_reward_amount(
292
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
293
+ )
294
+
295
+ _claim_knowledge_miner_reward = Method(
296
+ BlockchainRequest.claim_knowledge_miner_reward
297
+ )
298
+
299
+ def claim_miner_reward(
300
+ self,
301
+ ual: UAL,
302
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
303
+ ) -> dict[str, str | HexStr | TxReceipt]:
304
+ receipt: TxReceipt = self._claim_knowledge_miner_reward(
305
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
306
+ )
307
+
308
+ parsed_ual = parse_ual(ual)
309
+ knowledge_asset_storage, knowledge_asset_token_id = (
310
+ parsed_ual["contract_address"],
311
+ parsed_ual["token_id"],
312
+ )
313
+
314
+ return {
315
+ "paranetUAL": ual,
316
+ "paranetId": Web3.to_hex(
317
+ Web3.solidity_keccak(
318
+ ["address", "uint256"],
319
+ [knowledge_asset_storage, knowledge_asset_token_id],
320
+ )
321
+ ),
322
+ "operation": json.loads(Web3.to_json(receipt)),
323
+ }
324
+
325
+ _get_claimable_paranet_operator_reward_amount = Method(
326
+ BlockchainRequest.get_claimable_paranet_operator_reward_amount
327
+ )
328
+
329
+ def calculate_claimable_operator_reward_amount(
330
+ self,
331
+ ual: UAL,
332
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
333
+ ) -> int:
334
+ return self._get_claimable_paranet_operator_reward_amount(
335
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
336
+ )
337
+
338
+ _claim_paranet_operator_reward = Method(
339
+ BlockchainRequest.claim_paranet_operator_reward
340
+ )
341
+
342
+ def claim_operator_reward(
343
+ self,
344
+ ual: UAL,
345
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
346
+ ) -> dict[str, str | HexStr | TxReceipt]:
347
+ receipt: TxReceipt = self._claim_paranet_operator_reward(
348
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
349
+ )
350
+
351
+ parsed_ual = parse_ual(ual)
352
+ knowledge_asset_storage, knowledge_asset_token_id = (
353
+ parsed_ual["contract_address"],
354
+ parsed_ual["token_id"],
355
+ )
356
+
357
+ return {
358
+ "paranetUAL": ual,
359
+ "paranetId": Web3.to_hex(
360
+ Web3.solidity_keccak(
361
+ ["address", "uint256"],
362
+ [knowledge_asset_storage, knowledge_asset_token_id],
363
+ )
364
+ ),
365
+ "operation": json.loads(Web3.to_json(receipt)),
366
+ }
367
+
368
+ _get_claimable_proposal_voter_reward_amount = Method(
369
+ BlockchainRequest.get_claimable_proposal_voter_reward_amount
370
+ )
371
+
372
+ def calculate_claimable_voter_reward_amount(
373
+ self,
374
+ ual: UAL,
375
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
376
+ ) -> int:
377
+ return self._get_claimable_proposal_voter_reward_amount(
378
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
379
+ )
380
+
381
+ _get_claimable_all_proposal_voters_reward_amount = Method(
382
+ BlockchainRequest.get_claimable_all_proposal_voters_reward_amount
383
+ )
384
+
385
+ def calculate_all_claimable_voters_reward_amount(
386
+ self,
387
+ ual: UAL,
388
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
389
+ ) -> int:
390
+ return self._get_claimable_all_proposal_voters_reward_amount(
391
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
392
+ )
393
+
394
+ _claim_incentivization_proposal_voter_reward = Method(
395
+ BlockchainRequest.claim_incentivization_proposal_voter_reward
396
+ )
397
+
398
+ def claim_voter_reward(
399
+ self,
400
+ ual: UAL,
401
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
402
+ ) -> dict[str, str | HexStr | TxReceipt]:
403
+ receipt: TxReceipt = self._claim_incentivization_proposal_voter_reward(
404
+ contract=self._get_incentives_pool_contract(ual, incentives_type)
405
+ )
406
+
407
+ parsed_ual = parse_ual(ual)
408
+ knowledge_asset_storage, knowledge_asset_token_id = (
409
+ parsed_ual["contract_address"],
410
+ parsed_ual["token_id"],
411
+ )
412
+
413
+ return {
414
+ "paranetUAL": ual,
415
+ "paranetId": Web3.to_hex(
416
+ Web3.solidity_keccak(
417
+ ["address", "uint256"],
418
+ [knowledge_asset_storage, knowledge_asset_token_id],
419
+ )
420
+ ),
421
+ "operation": json.loads(Web3.to_json(receipt)),
422
+ }
423
+
424
+ _get_updating_knowledge_asset_states = Method(
425
+ BlockchainRequest.get_updating_knowledge_asset_states
426
+ )
427
+ _process_updated_knowledge_asset_states_metadata = Method(
428
+ BlockchainRequest.process_updated_knowledge_asset_states_metadata
429
+ )
430
+
431
+ def update_claimable_rewards(self, ual: UAL) -> dict[str, str | HexStr | TxReceipt]:
432
+ parsed_ual = parse_ual(ual)
433
+ knowledge_asset_storage, knowledge_asset_token_id = (
434
+ parsed_ual["contract_address"],
435
+ parsed_ual["token_id"],
436
+ )
437
+
438
+ paranet_id = Web3.solidity_keccak(
439
+ ["address", "uint256"], [knowledge_asset_storage, knowledge_asset_token_id]
440
+ )
441
+
442
+ updating_states = self._get_updating_knowledge_asset_states(
443
+ self.manager.blockchain_provider.account.address,
444
+ paranet_id,
445
+ )
446
+ receipt: TxReceipt = self._process_updated_knowledge_asset_states_metadata(
447
+ knowledge_asset_storage,
448
+ knowledge_asset_token_id,
449
+ 0,
450
+ len(updating_states),
451
+ )
452
+
453
+ return {
454
+ "paranetUAL": ual,
455
+ "paranetId": paranet_id,
456
+ "operation": json.loads(Web3.to_json(receipt)),
457
+ }
458
+
459
+ def _get_incentives_pool_contract(
460
+ self,
461
+ ual: UAL,
462
+ incentives_type: ParanetIncentivizationType = ParanetIncentivizationType.NEUROWEB,
463
+ ) -> str | dict[str, str]:
464
+ incentives_pool_name = f"Paranet{str(incentives_type)}IncentivesPool"
465
+ is_incentives_pool_cached = (
466
+ incentives_pool_name in self.manager.blockchain_provider.contracts.keys()
467
+ )
468
+
469
+ return (
470
+ incentives_pool_name
471
+ if is_incentives_pool_cached
472
+ else {
473
+ "name": incentives_pool_name,
474
+ "address": self.get_incentives_pool_address(ual, incentives_type),
475
+ }
476
+ )
@@ -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)