dkg 8.0.0a2__py3-none-any.whl → 8.0.1__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.
- dkg/__init__.py +1 -1
- dkg/assertion.py +2 -2
- dkg/clients/__init__.py +4 -0
- dkg/clients/async_dkg.py +109 -0
- dkg/{main.py → clients/dkg.py} +42 -21
- dkg/constants.py +117 -6
- dkg/data/interfaces/AskStorage.json +366 -0
- dkg/data/interfaces/Chronos.json +202 -0
- dkg/data/interfaces/Hub.json +294 -2
- dkg/data/interfaces/IdentityStorage.json +58 -0
- dkg/data/interfaces/{ContentAsset.json → KnowledgeCollection.json} +256 -343
- dkg/data/interfaces/KnowledgeCollectionStorage.json +2312 -0
- dkg/data/interfaces/Paranet.json +30 -214
- dkg/data/interfaces/ParanetIncentivesPoolFactory.json +18 -2
- dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json +20 -4
- dkg/data/interfaces/{ParanetNeurowebIncentivesPool.json → ParanetNeuroIncentivesPool.json} +7 -7
- dkg/data/interfaces/ParanetsRegistry.json +102 -32
- dkg/data/interfaces/Token.json +146 -17
- dkg/managers/__init__.py +0 -0
- dkg/managers/async_manager.py +69 -0
- dkg/{manager.py → managers/manager.py} +5 -3
- dkg/method.py +5 -2
- dkg/modules/__init__.py +0 -0
- dkg/modules/asset/__init__.py +0 -0
- dkg/modules/asset/asset.py +739 -0
- dkg/modules/asset/async_asset.py +751 -0
- dkg/modules/async_module.py +66 -0
- dkg/modules/graph/__init__.py +0 -0
- dkg/modules/graph/async_graph.py +118 -0
- dkg/modules/graph/graph.py +94 -0
- dkg/{module.py → modules/module.py} +1 -1
- dkg/modules/network/__init__.py +0 -0
- dkg/{network.py → modules/network/network.py} +4 -4
- dkg/modules/node/__init__.py +0 -0
- dkg/modules/node/async_node.py +39 -0
- dkg/{node.py → modules/node/node.py} +2 -2
- dkg/modules/paranet/__init__.py +0 -0
- dkg/{paranet.py → modules/paranet/paranet.py} +2 -2
- dkg/providers/__init__.py +9 -2
- dkg/providers/blockchain/__init__.py +4 -0
- dkg/providers/blockchain/async_blockchain.py +245 -0
- dkg/providers/blockchain/base_blockchain.py +102 -0
- dkg/providers/{blockchain.py → blockchain/blockchain.py} +15 -96
- dkg/providers/node/__init__.py +4 -0
- dkg/providers/node/async_node_http.py +72 -0
- dkg/providers/node/base_node_http.py +25 -0
- dkg/providers/{node_http.py → node/node_http.py} +12 -10
- dkg/services/__init__.py +0 -0
- dkg/services/blockchain_services/__init__.py +0 -0
- dkg/services/blockchain_services/async_blockchain_service.py +180 -0
- dkg/services/blockchain_services/blockchain_service.py +174 -0
- dkg/services/input_service.py +183 -0
- dkg/services/node_services/__init__.py +0 -0
- dkg/services/node_services/async_node_service.py +184 -0
- dkg/services/node_services/node_service.py +167 -0
- dkg/types/__init__.py +11 -11
- dkg/utils/blockchain_request.py +68 -42
- dkg/utils/knowledge_asset_tools.py +5 -0
- dkg/utils/knowledge_collection_tools.py +248 -0
- dkg/utils/node_request.py +60 -13
- dkg/utils/rdf.py +9 -3
- {dkg-8.0.0a2.dist-info → dkg-8.0.1.dist-info}/METADATA +28 -19
- dkg-8.0.1.dist-info/RECORD +82 -0
- {dkg-8.0.0a2.dist-info → dkg-8.0.1.dist-info}/WHEEL +1 -1
- dkg/asset.py +0 -912
- dkg/data/interfaces/AssertionStorage.json +0 -229
- dkg/data/interfaces/ContentAssetStorage.json +0 -706
- dkg/data/interfaces/ServiceAgreementStorageProxy.json +0 -1314
- dkg/graph.py +0 -63
- dkg-8.0.0a2.dist-info/RECORD +0 -52
- {dkg-8.0.0a2.dist-info → dkg-8.0.1.dist-info}/LICENSE +0 -0
- {dkg-8.0.0a2.dist-info → dkg-8.0.1.dist-info}/NOTICE +0 -0
@@ -0,0 +1,174 @@
|
|
1
|
+
from dkg.modules.module import Module
|
2
|
+
from dkg.managers.manager import DefaultRequestManager
|
3
|
+
from dkg.utils.blockchain_request import BlockchainRequest
|
4
|
+
from dkg.method import Method
|
5
|
+
from dkg.constants import ZERO_ADDRESS
|
6
|
+
from web3 import Web3
|
7
|
+
from typing import Optional
|
8
|
+
from dkg.types import Address, UAL
|
9
|
+
from dkg.utils.blockchain_request import KnowledgeCollectionResult, AllowanceResult
|
10
|
+
from dkg.utils.ual import parse_ual
|
11
|
+
|
12
|
+
|
13
|
+
class BlockchainService(Module):
|
14
|
+
def __init__(self, manager: DefaultRequestManager):
|
15
|
+
self.manager = manager
|
16
|
+
|
17
|
+
_owner = Method(BlockchainRequest.owner_of)
|
18
|
+
_get_contract_address = Method(BlockchainRequest.get_contract_address)
|
19
|
+
_get_current_allowance = Method(BlockchainRequest.allowance)
|
20
|
+
_increase_allowance = Method(BlockchainRequest.increase_allowance)
|
21
|
+
_decrease_allowance = Method(BlockchainRequest.decrease_allowance)
|
22
|
+
_create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection)
|
23
|
+
_mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset)
|
24
|
+
_get_asset_storage_address = Method(BlockchainRequest.get_asset_storage_address)
|
25
|
+
_key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet)
|
26
|
+
_time_until_next_epoch = Method(BlockchainRequest.time_until_next_epoch)
|
27
|
+
_epoch_length = Method(BlockchainRequest.epoch_length)
|
28
|
+
_get_stake_weighted_average_ask = Method(
|
29
|
+
BlockchainRequest.get_stake_weighted_average_ask
|
30
|
+
)
|
31
|
+
_get_block = Method(BlockchainRequest.get_block)
|
32
|
+
|
33
|
+
def decrease_knowledge_collection_allowance(
|
34
|
+
self,
|
35
|
+
allowance_gap: int,
|
36
|
+
):
|
37
|
+
knowledge_collection_address = self._get_contract_address("KnowledgeCollection")
|
38
|
+
self._decrease_allowance(knowledge_collection_address, allowance_gap)
|
39
|
+
|
40
|
+
def increase_knowledge_collection_allowance(
|
41
|
+
self,
|
42
|
+
sender: str,
|
43
|
+
token_amount: str,
|
44
|
+
) -> AllowanceResult:
|
45
|
+
"""
|
46
|
+
Increases the allowance for knowledge collection if necessary.
|
47
|
+
|
48
|
+
Args:
|
49
|
+
sender: The address of the sender
|
50
|
+
token_amount: The amount of tokens to check/increase allowance for
|
51
|
+
|
52
|
+
Returns:
|
53
|
+
AllowanceResult containing whether allowance was increased and the gap
|
54
|
+
"""
|
55
|
+
knowledge_collection_address = self._get_contract_address("KnowledgeCollection")
|
56
|
+
|
57
|
+
allowance = self._get_current_allowance(sender, knowledge_collection_address)
|
58
|
+
allowance_gap = int(token_amount) - int(allowance)
|
59
|
+
|
60
|
+
if allowance_gap > 0:
|
61
|
+
self._increase_allowance(knowledge_collection_address, allowance_gap)
|
62
|
+
|
63
|
+
return AllowanceResult(
|
64
|
+
allowance_increased=True, allowance_gap=allowance_gap
|
65
|
+
)
|
66
|
+
|
67
|
+
return AllowanceResult(allowance_increased=False, allowance_gap=allowance_gap)
|
68
|
+
|
69
|
+
def create_knowledge_collection(
|
70
|
+
self,
|
71
|
+
request: dict,
|
72
|
+
paranet_ka_contract: Optional[Address] = None,
|
73
|
+
paranet_token_id: Optional[int] = None,
|
74
|
+
) -> KnowledgeCollectionResult:
|
75
|
+
"""
|
76
|
+
Creates a knowledge collection on the blockchain.
|
77
|
+
|
78
|
+
Args:
|
79
|
+
request: dict containing all collection parameters
|
80
|
+
paranet_ka_contract: Optional paranet contract address
|
81
|
+
paranet_token_id: Optional paranet token ID
|
82
|
+
blockchain: Blockchain configuration
|
83
|
+
|
84
|
+
Returns:
|
85
|
+
KnowledgeCollectionResult containing collection ID and transaction receipt
|
86
|
+
|
87
|
+
Raises:
|
88
|
+
BlockchainError: If the collection creation fails
|
89
|
+
"""
|
90
|
+
sender = self.manager.blockchain_provider.account.address
|
91
|
+
allowance_increased = False
|
92
|
+
allowance_gap = 0
|
93
|
+
|
94
|
+
try:
|
95
|
+
# Handle allowance
|
96
|
+
if request.get("paymaster") and request.get("paymaster") != ZERO_ADDRESS:
|
97
|
+
pass
|
98
|
+
else:
|
99
|
+
allowance_result = self.increase_knowledge_collection_allowance(
|
100
|
+
sender=sender,
|
101
|
+
token_amount=request.get("tokenAmount"),
|
102
|
+
)
|
103
|
+
allowance_increased = allowance_result.allowance_increased
|
104
|
+
allowance_gap = allowance_result.allowance_gap
|
105
|
+
|
106
|
+
if not paranet_ka_contract and not paranet_token_id:
|
107
|
+
receipt = self._create_knowledge_collection(
|
108
|
+
request.get("publishOperationId"),
|
109
|
+
Web3.to_bytes(hexstr=request.get("merkleRoot")),
|
110
|
+
request.get("knowledgeAssetsAmount"),
|
111
|
+
request.get("byteSize"),
|
112
|
+
request.get("epochs"),
|
113
|
+
request.get("tokenAmount"),
|
114
|
+
request.get("isImmutable"),
|
115
|
+
request.get("paymaster"),
|
116
|
+
request.get("publisherNodeIdentityId"),
|
117
|
+
Web3.to_bytes(hexstr=request.get("publisherNodeR")),
|
118
|
+
Web3.to_bytes(hexstr=request.get("publisherNodeVS")),
|
119
|
+
request.get("identityIds"),
|
120
|
+
[Web3.to_bytes(hexstr=x) for x in request.get("r")],
|
121
|
+
[Web3.to_bytes(hexstr=x) for x in request.get("vs")],
|
122
|
+
)
|
123
|
+
else:
|
124
|
+
receipt = self._mint_knowledge_asset(
|
125
|
+
paranet_ka_contract,
|
126
|
+
paranet_token_id,
|
127
|
+
list(request.values()),
|
128
|
+
)
|
129
|
+
|
130
|
+
event_data = self.manager.blockchain_provider.decode_logs_event(
|
131
|
+
receipt=receipt,
|
132
|
+
contract_name="KnowledgeCollectionStorage",
|
133
|
+
event_name="KnowledgeCollectionCreated",
|
134
|
+
)
|
135
|
+
collection_id = (
|
136
|
+
int(getattr(event_data[0].get("args", {}), "id", None))
|
137
|
+
if event_data
|
138
|
+
else None
|
139
|
+
)
|
140
|
+
|
141
|
+
return KnowledgeCollectionResult(
|
142
|
+
knowledge_collection_id=collection_id, receipt=receipt
|
143
|
+
)
|
144
|
+
|
145
|
+
except Exception as e:
|
146
|
+
if allowance_increased:
|
147
|
+
self.decrease_knowledge_collection_allowance(allowance_gap)
|
148
|
+
raise e
|
149
|
+
|
150
|
+
# TODO: change self._owner to v8 compatible function
|
151
|
+
def get_owner(self, ual: UAL) -> Address:
|
152
|
+
token_id = parse_ual(ual)["token_id"]
|
153
|
+
|
154
|
+
return self._owner(token_id)
|
155
|
+
|
156
|
+
def get_asset_storage_address(self, asset_storage_name: str) -> Address:
|
157
|
+
return self._get_asset_storage_address(asset_storage_name)
|
158
|
+
|
159
|
+
def key_is_operational_wallet(
|
160
|
+
self, identity_id: int, key: Address, purpose: int
|
161
|
+
) -> bool:
|
162
|
+
return self._key_is_operational_wallet(identity_id, key, purpose)
|
163
|
+
|
164
|
+
def time_until_next_epoch(self) -> int:
|
165
|
+
return self._time_until_next_epoch()
|
166
|
+
|
167
|
+
def epoch_length(self) -> int:
|
168
|
+
return self._epoch_length()
|
169
|
+
|
170
|
+
def get_stake_weighted_average_ask(self) -> int:
|
171
|
+
return self._get_stake_weighted_average_ask()
|
172
|
+
|
173
|
+
def get_block(self, block_identifier: str | int):
|
174
|
+
return self._get_block(block_identifier)
|
@@ -0,0 +1,183 @@
|
|
1
|
+
from dkg.constants import (
|
2
|
+
DefaultParameters,
|
3
|
+
ZERO_ADDRESS,
|
4
|
+
DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS,
|
5
|
+
)
|
6
|
+
|
7
|
+
|
8
|
+
class InputService:
|
9
|
+
def __init__(self, manager, config):
|
10
|
+
self.manager = manager
|
11
|
+
self.config = config
|
12
|
+
|
13
|
+
def get_asset_get_arguments(self, options):
|
14
|
+
return {
|
15
|
+
"max_number_of_retries": self.get_max_number_of_retries(options),
|
16
|
+
"frequency": self.get_frequency(options),
|
17
|
+
"state": self.get_state(options),
|
18
|
+
"include_metadata": self.get_include_metadata(options),
|
19
|
+
"content_type": self.get_content_type(options),
|
20
|
+
"validate": self.get_validate(options),
|
21
|
+
"output_format": self.get_output_format(options),
|
22
|
+
"hash_function_id": self.get_hash_function_id(options),
|
23
|
+
"paranet_ual": self.get_paranet_ual(options),
|
24
|
+
"subject_ual": self.get_subject_ual(options),
|
25
|
+
}
|
26
|
+
|
27
|
+
def get_asset_create_arguments(self, options):
|
28
|
+
return {
|
29
|
+
"max_number_of_retries": self.get_max_number_of_retries(options),
|
30
|
+
"frequency": self.get_frequency(options),
|
31
|
+
"epochs_num": self.get_epochs_num(options),
|
32
|
+
"hash_function_id": self.get_hash_function_id(options),
|
33
|
+
"score_function_id": self.get_score_function_id(options),
|
34
|
+
"immutable": self.get_immutable(options),
|
35
|
+
"token_amount": self.get_token_amount(options),
|
36
|
+
"payer": self.get_payer(options),
|
37
|
+
"minimum_number_of_finalization_confirmations": self.get_minimum_number_of_finalization_confirmations(
|
38
|
+
options
|
39
|
+
),
|
40
|
+
"minimum_number_of_node_replications": self.get_minimum_number_of_node_replications(
|
41
|
+
options
|
42
|
+
),
|
43
|
+
}
|
44
|
+
|
45
|
+
def get_query_arguments(self, options):
|
46
|
+
return {
|
47
|
+
"max_number_of_retries": self.get_max_number_of_retries(options),
|
48
|
+
"frequency": self.get_frequency(options),
|
49
|
+
"paranet_ual": self.get_paranet_ual(options),
|
50
|
+
"repository": self.get_repository(options),
|
51
|
+
}
|
52
|
+
|
53
|
+
def get_publish_finality_arguments(self, options):
|
54
|
+
return {
|
55
|
+
"max_number_of_retries": self.get_max_number_of_retries(options),
|
56
|
+
"frequency": self.get_frequency(options),
|
57
|
+
"minimum_number_of_finalization_confirmations": self.get_minimum_number_of_finalization_confirmations(
|
58
|
+
options
|
59
|
+
),
|
60
|
+
}
|
61
|
+
|
62
|
+
def get_max_number_of_retries(self, options):
|
63
|
+
return (
|
64
|
+
options.get("max_number_of_retries")
|
65
|
+
or self.config.get("max_number_of_retries")
|
66
|
+
or DefaultParameters.MAX_NUMBER_OF_RETRIES.value
|
67
|
+
)
|
68
|
+
|
69
|
+
def get_frequency(self, options):
|
70
|
+
return (
|
71
|
+
options.get("frequency")
|
72
|
+
or self.config.get("frequency")
|
73
|
+
or DefaultParameters.FREQUENCY.value
|
74
|
+
)
|
75
|
+
|
76
|
+
def get_state(self, options):
|
77
|
+
return (
|
78
|
+
options.get("state")
|
79
|
+
or self.config.get("state")
|
80
|
+
or DefaultParameters.STATE.value
|
81
|
+
)
|
82
|
+
|
83
|
+
def get_include_metadata(self, options):
|
84
|
+
return (
|
85
|
+
options.get("include_metadata")
|
86
|
+
or self.config.get("include_metadata")
|
87
|
+
or DefaultParameters.INCLUDE_METADATA.value
|
88
|
+
)
|
89
|
+
|
90
|
+
def get_content_type(self, options):
|
91
|
+
return (
|
92
|
+
options.get("content_type")
|
93
|
+
or self.config.get("content_type")
|
94
|
+
or DefaultParameters.CONTENT_TYPE.value
|
95
|
+
)
|
96
|
+
|
97
|
+
def get_validate(self, options):
|
98
|
+
return (
|
99
|
+
options.get("validate")
|
100
|
+
or self.config.get("validate")
|
101
|
+
or DefaultParameters.VALIDATE.value
|
102
|
+
)
|
103
|
+
|
104
|
+
def get_output_format(self, options):
|
105
|
+
return (
|
106
|
+
options.get("output_format")
|
107
|
+
or self.config.get("output_format")
|
108
|
+
or DefaultParameters.OUTPUT_FORMAT.value
|
109
|
+
)
|
110
|
+
|
111
|
+
def get_hash_function_id(self, options):
|
112
|
+
return (
|
113
|
+
options.get("hash_function_id")
|
114
|
+
or self.config.get("hash_function_id")
|
115
|
+
or DefaultParameters.HASH_FUNCTION_ID.value
|
116
|
+
)
|
117
|
+
|
118
|
+
def get_paranet_ual(self, options):
|
119
|
+
return (
|
120
|
+
options.get("paranet_ual")
|
121
|
+
or self.config.get("paranet_ual")
|
122
|
+
or DefaultParameters.PARANET_UAL.value
|
123
|
+
)
|
124
|
+
|
125
|
+
def get_subject_ual(self, options):
|
126
|
+
return (
|
127
|
+
options.get("subject_ual")
|
128
|
+
or self.config.get("subject_ual")
|
129
|
+
or DefaultParameters.GET_SUBJECT_UAL.value
|
130
|
+
)
|
131
|
+
|
132
|
+
def get_epochs_num(self, options):
|
133
|
+
return options.get("epochs_num") or self.config.get("epochs_num") or None
|
134
|
+
|
135
|
+
def get_immutable(self, options):
|
136
|
+
return (
|
137
|
+
options.get("immutable")
|
138
|
+
or self.config.get("immutable")
|
139
|
+
or DefaultParameters.IMMUTABLE.value
|
140
|
+
)
|
141
|
+
|
142
|
+
def get_token_amount(self, options):
|
143
|
+
return options.get("token_amount") or self.config.get("token_amount") or None
|
144
|
+
|
145
|
+
def get_payer(self, options):
|
146
|
+
return options.get("payer") or self.config.get("payer") or ZERO_ADDRESS
|
147
|
+
|
148
|
+
def get_minimum_number_of_finalization_confirmations(self, options):
|
149
|
+
return (
|
150
|
+
options.get("minimum_number_of_finalization_confirmations")
|
151
|
+
or self.config.get("minimum_number_of_finalization_confirmations")
|
152
|
+
or DefaultParameters.MIN_NUMBER_OF_FINALIZATION_CONFIRMATION.value
|
153
|
+
or None
|
154
|
+
)
|
155
|
+
|
156
|
+
def get_minimum_number_of_node_replications(self, options):
|
157
|
+
return (
|
158
|
+
options.get("minimum_number_of_node_replications")
|
159
|
+
or self.config.get("minimum_number_of_node_replications")
|
160
|
+
or None
|
161
|
+
)
|
162
|
+
|
163
|
+
def get_score_function_id(self, options):
|
164
|
+
environment = (
|
165
|
+
options.get("environment")
|
166
|
+
or self.config.get("environment")
|
167
|
+
or self.manager.blockchain_provider.environment
|
168
|
+
or DefaultParameters.ENVIRONMENT.value
|
169
|
+
)
|
170
|
+
blockchain_name = (
|
171
|
+
options.get("blockchain")
|
172
|
+
or self.config.get("blockchain")
|
173
|
+
or self.manager.blockchain_provider.blockchain_id
|
174
|
+
)
|
175
|
+
|
176
|
+
return DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[environment][blockchain_name]
|
177
|
+
|
178
|
+
def get_repository(self, options):
|
179
|
+
return (
|
180
|
+
options.get("repository")
|
181
|
+
or self.config.get("repository")
|
182
|
+
or DefaultParameters.REPOSITORY.value
|
183
|
+
)
|
File without changes
|
@@ -0,0 +1,184 @@
|
|
1
|
+
from dkg.managers.async_manager import AsyncRequestManager
|
2
|
+
from dkg.method import Method
|
3
|
+
from dkg.constants import OperationStatuses, ErrorType, Status
|
4
|
+
from dkg.utils.node_request import NodeRequest
|
5
|
+
from dkg.modules.async_module import AsyncModule
|
6
|
+
from typing import Dict, Any
|
7
|
+
from dkg.types import UAL
|
8
|
+
from dkg.dataclasses import NodeResponseDict
|
9
|
+
import asyncio
|
10
|
+
|
11
|
+
|
12
|
+
class AsyncNodeService(AsyncModule):
|
13
|
+
def __init__(self, manager: AsyncRequestManager):
|
14
|
+
self.manager = manager
|
15
|
+
|
16
|
+
_info = Method(NodeRequest.info)
|
17
|
+
_get_operation_result = Method(NodeRequest.get_operation_result)
|
18
|
+
_finality_status = Method(NodeRequest.finality_status)
|
19
|
+
_ask = Method(NodeRequest.ask)
|
20
|
+
_get_bid_suggestion = Method(NodeRequest.bid_suggestion)
|
21
|
+
_publish = Method(NodeRequest.publish)
|
22
|
+
_get = Method(NodeRequest.get)
|
23
|
+
_query = Method(NodeRequest.query)
|
24
|
+
|
25
|
+
async def info(self) -> NodeResponseDict:
|
26
|
+
return await self._info()
|
27
|
+
|
28
|
+
async def get_operation_result(
|
29
|
+
self,
|
30
|
+
operation_id: str,
|
31
|
+
operation: str,
|
32
|
+
max_retries: int,
|
33
|
+
frequency: int,
|
34
|
+
) -> Dict[str, Any]:
|
35
|
+
response = {"status": OperationStatuses.PENDING.value}
|
36
|
+
|
37
|
+
retries = 0
|
38
|
+
|
39
|
+
while True:
|
40
|
+
if retries > max_retries:
|
41
|
+
response["data"] = {
|
42
|
+
"errorType": ErrorType.DKG_CLIENT_ERROR.value,
|
43
|
+
"errorMessage": "Unable to get results. Max number of retries reached.",
|
44
|
+
}
|
45
|
+
break
|
46
|
+
|
47
|
+
if retries > 0:
|
48
|
+
await asyncio.sleep(frequency)
|
49
|
+
|
50
|
+
retries += 1
|
51
|
+
|
52
|
+
try:
|
53
|
+
result = await self._get_operation_result(
|
54
|
+
operation=operation,
|
55
|
+
operation_id=operation_id,
|
56
|
+
)
|
57
|
+
response = {"data": result}
|
58
|
+
except Exception:
|
59
|
+
response = {"data": {"status": Status.NETWORK_ERROR.value}}
|
60
|
+
|
61
|
+
# Check completion conditions
|
62
|
+
if (
|
63
|
+
response["data"].get("status") == OperationStatuses.COMPLETED.value
|
64
|
+
or response["data"].get("status") == OperationStatuses.FAILED.value
|
65
|
+
):
|
66
|
+
break
|
67
|
+
|
68
|
+
return response["data"]
|
69
|
+
|
70
|
+
async def finality_status(
|
71
|
+
self,
|
72
|
+
ual: UAL,
|
73
|
+
required_confirmations: int,
|
74
|
+
max_number_of_retries: int,
|
75
|
+
frequency: int,
|
76
|
+
):
|
77
|
+
retries = 0
|
78
|
+
finality = 0
|
79
|
+
|
80
|
+
while finality < required_confirmations and retries <= max_number_of_retries:
|
81
|
+
if retries > max_number_of_retries:
|
82
|
+
raise Exception(
|
83
|
+
f"Unable to achieve required confirmations. "
|
84
|
+
f"Max number of retries ({max_number_of_retries}) reached."
|
85
|
+
)
|
86
|
+
|
87
|
+
# Sleep between attempts (except for first try)
|
88
|
+
if retries > 0:
|
89
|
+
await asyncio.sleep(frequency)
|
90
|
+
|
91
|
+
retries += 1
|
92
|
+
|
93
|
+
try:
|
94
|
+
response = await self._finality_status(ual)
|
95
|
+
finality = response.get("finality", 0)
|
96
|
+
except Exception:
|
97
|
+
finality = 0
|
98
|
+
|
99
|
+
return finality
|
100
|
+
|
101
|
+
async def ask(
|
102
|
+
self,
|
103
|
+
ual: UAL,
|
104
|
+
required_confirmations: int,
|
105
|
+
max_number_of_retries: int,
|
106
|
+
frequency: int,
|
107
|
+
):
|
108
|
+
finality_id = 0
|
109
|
+
retries = 0
|
110
|
+
|
111
|
+
while finality_id < required_confirmations and retries < max_number_of_retries:
|
112
|
+
if retries > max_number_of_retries:
|
113
|
+
raise Exception(
|
114
|
+
f"Unable to achieve required confirmations. "
|
115
|
+
f"Max number of retries ({max_number_of_retries}) reached."
|
116
|
+
)
|
117
|
+
|
118
|
+
if retries > 0:
|
119
|
+
await asyncio.sleep(frequency)
|
120
|
+
|
121
|
+
retries += 1
|
122
|
+
|
123
|
+
try:
|
124
|
+
try:
|
125
|
+
response = await self._ask(
|
126
|
+
ual=ual, minimumNumberOfNodeReplications=required_confirmations
|
127
|
+
)
|
128
|
+
except Exception as e:
|
129
|
+
response = None
|
130
|
+
print(f"failed: {e}")
|
131
|
+
|
132
|
+
if response is not None:
|
133
|
+
operation_id = response.json().get("operationId", 0)
|
134
|
+
if operation_id >= required_confirmations:
|
135
|
+
finality_id = operation_id
|
136
|
+
|
137
|
+
except Exception as e:
|
138
|
+
finality_id = 0
|
139
|
+
print(f"Retry {retries + 1}/{max_number_of_retries} failed: {e}")
|
140
|
+
|
141
|
+
return finality_id
|
142
|
+
|
143
|
+
async def publish(
|
144
|
+
self,
|
145
|
+
dataset_root,
|
146
|
+
dataset,
|
147
|
+
blockchain_id,
|
148
|
+
hash_function_id,
|
149
|
+
minimum_number_of_node_replications,
|
150
|
+
):
|
151
|
+
return await self._publish(
|
152
|
+
dataset_root,
|
153
|
+
dataset,
|
154
|
+
blockchain_id,
|
155
|
+
hash_function_id,
|
156
|
+
minimum_number_of_node_replications,
|
157
|
+
)
|
158
|
+
|
159
|
+
async def get(
|
160
|
+
self,
|
161
|
+
ual_with_state,
|
162
|
+
content_type,
|
163
|
+
include_metadata,
|
164
|
+
hash_function_id,
|
165
|
+
paranet_ual,
|
166
|
+
subject_ual,
|
167
|
+
):
|
168
|
+
return await self._get(
|
169
|
+
ual_with_state,
|
170
|
+
content_type,
|
171
|
+
include_metadata,
|
172
|
+
hash_function_id,
|
173
|
+
paranet_ual,
|
174
|
+
subject_ual,
|
175
|
+
)
|
176
|
+
|
177
|
+
async def query(
|
178
|
+
self,
|
179
|
+
query,
|
180
|
+
query_type,
|
181
|
+
repository,
|
182
|
+
paranet_ual,
|
183
|
+
):
|
184
|
+
return await self._query(query, query_type, repository, paranet_ual)
|