dkg 0.1.0b1__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 +3 -0
- dkg/asset.py +781 -0
- dkg/constants.py +39 -0
- dkg/data/interfaces/Assertion.json +131 -0
- dkg/data/interfaces/AssertionStorage.json +229 -0
- dkg/data/interfaces/CommitManagerV1.json +534 -0
- dkg/data/interfaces/CommitManagerV1U1.json +720 -0
- dkg/data/interfaces/ContentAsset.json +671 -0
- dkg/data/interfaces/ContentAssetStorage.json +706 -0
- dkg/data/interfaces/HashingProxy.json +227 -0
- dkg/data/interfaces/Hub.json +356 -0
- dkg/data/interfaces/Identity.json +193 -0
- dkg/data/interfaces/IdentityStorage.json +342 -0
- dkg/data/interfaces/ParametersStorage.json +468 -0
- dkg/data/interfaces/Profile.json +292 -0
- dkg/data/interfaces/ProfileStorage.json +596 -0
- dkg/data/interfaces/ProofManagerV1.json +525 -0
- dkg/data/interfaces/ProofManagerV1U1.json +546 -0
- dkg/data/interfaces/ScoringProxy.json +242 -0
- dkg/data/interfaces/ServiceAgreementStorageProxy.json +1299 -0
- dkg/data/interfaces/ServiceAgreementStorageV1.json +901 -0
- dkg/data/interfaces/ServiceAgreementStorageV1U1.json +1097 -0
- dkg/data/interfaces/ServiceAgreementV1.json +741 -0
- dkg/data/interfaces/ShardingTable.json +268 -0
- dkg/data/interfaces/ShardingTableStorage.json +317 -0
- dkg/data/interfaces/Staking.json +456 -0
- dkg/data/interfaces/StakingStorage.json +407 -0
- dkg/data/interfaces/Token.json +544 -0
- dkg/data/interfaces/UnfinalizedStateStorage.json +171 -0
- dkg/data/interfaces/WhitelistStorage.json +124 -0
- dkg/dataclasses.py +45 -0
- dkg/exceptions.py +161 -0
- dkg/graph.py +63 -0
- dkg/main.py +74 -0
- dkg/manager.py +64 -0
- dkg/method.py +131 -0
- dkg/module.py +63 -0
- dkg/node.py +54 -0
- dkg/providers/__init__.py +2 -0
- dkg/providers/blockchain.py +181 -0
- dkg/providers/node_http.py +62 -0
- dkg/types/__init__.py +8 -0
- dkg/types/blockchain.py +58 -0
- dkg/types/dkg_node.py +20 -0
- dkg/types/encoding.py +22 -0
- dkg/types/evm.py +25 -0
- dkg/types/generics.py +21 -0
- dkg/types/network.py +20 -0
- dkg/types/rdf.py +21 -0
- dkg/utils/__init__.py +0 -0
- dkg/utils/blockchain_request.py +159 -0
- dkg/utils/decorators.py +46 -0
- dkg/utils/merkle.py +173 -0
- dkg/utils/metadata.py +50 -0
- dkg/utils/node_request.py +197 -0
- dkg/utils/rdf.py +51 -0
- dkg/utils/string_transformations.py +22 -0
- dkg/utils/ual.py +41 -0
- dkg-0.1.0b1.dist-info/LICENSE +202 -0
- dkg-0.1.0b1.dist-info/METADATA +453 -0
- dkg-0.1.0b1.dist-info/RECORD +62 -0
- dkg-0.1.0b1.dist-info/WHEEL +4 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
[
|
2
|
+
{
|
3
|
+
"inputs": [
|
4
|
+
{
|
5
|
+
"internalType": "address",
|
6
|
+
"name": "hubAddress",
|
7
|
+
"type": "address"
|
8
|
+
}
|
9
|
+
],
|
10
|
+
"stateMutability": "nonpayable",
|
11
|
+
"type": "constructor"
|
12
|
+
},
|
13
|
+
{
|
14
|
+
"inputs": [
|
15
|
+
{
|
16
|
+
"internalType": "address",
|
17
|
+
"name": "addr",
|
18
|
+
"type": "address"
|
19
|
+
}
|
20
|
+
],
|
21
|
+
"name": "blacklistAddress",
|
22
|
+
"outputs": [],
|
23
|
+
"stateMutability": "nonpayable",
|
24
|
+
"type": "function"
|
25
|
+
},
|
26
|
+
{
|
27
|
+
"inputs": [],
|
28
|
+
"name": "disableWhitelist",
|
29
|
+
"outputs": [],
|
30
|
+
"stateMutability": "nonpayable",
|
31
|
+
"type": "function"
|
32
|
+
},
|
33
|
+
{
|
34
|
+
"inputs": [],
|
35
|
+
"name": "enableWhitelist",
|
36
|
+
"outputs": [],
|
37
|
+
"stateMutability": "nonpayable",
|
38
|
+
"type": "function"
|
39
|
+
},
|
40
|
+
{
|
41
|
+
"inputs": [],
|
42
|
+
"name": "hub",
|
43
|
+
"outputs": [
|
44
|
+
{
|
45
|
+
"internalType": "contract Hub",
|
46
|
+
"name": "",
|
47
|
+
"type": "address"
|
48
|
+
}
|
49
|
+
],
|
50
|
+
"stateMutability": "view",
|
51
|
+
"type": "function"
|
52
|
+
},
|
53
|
+
{
|
54
|
+
"inputs": [],
|
55
|
+
"name": "name",
|
56
|
+
"outputs": [
|
57
|
+
{
|
58
|
+
"internalType": "string",
|
59
|
+
"name": "",
|
60
|
+
"type": "string"
|
61
|
+
}
|
62
|
+
],
|
63
|
+
"stateMutability": "pure",
|
64
|
+
"type": "function"
|
65
|
+
},
|
66
|
+
{
|
67
|
+
"inputs": [],
|
68
|
+
"name": "version",
|
69
|
+
"outputs": [
|
70
|
+
{
|
71
|
+
"internalType": "string",
|
72
|
+
"name": "",
|
73
|
+
"type": "string"
|
74
|
+
}
|
75
|
+
],
|
76
|
+
"stateMutability": "pure",
|
77
|
+
"type": "function"
|
78
|
+
},
|
79
|
+
{
|
80
|
+
"inputs": [
|
81
|
+
{
|
82
|
+
"internalType": "address",
|
83
|
+
"name": "addr",
|
84
|
+
"type": "address"
|
85
|
+
}
|
86
|
+
],
|
87
|
+
"name": "whitelistAddress",
|
88
|
+
"outputs": [],
|
89
|
+
"stateMutability": "nonpayable",
|
90
|
+
"type": "function"
|
91
|
+
},
|
92
|
+
{
|
93
|
+
"inputs": [
|
94
|
+
{
|
95
|
+
"internalType": "address",
|
96
|
+
"name": "",
|
97
|
+
"type": "address"
|
98
|
+
}
|
99
|
+
],
|
100
|
+
"name": "whitelisted",
|
101
|
+
"outputs": [
|
102
|
+
{
|
103
|
+
"internalType": "bool",
|
104
|
+
"name": "",
|
105
|
+
"type": "bool"
|
106
|
+
}
|
107
|
+
],
|
108
|
+
"stateMutability": "view",
|
109
|
+
"type": "function"
|
110
|
+
},
|
111
|
+
{
|
112
|
+
"inputs": [],
|
113
|
+
"name": "whitelistingEnabled",
|
114
|
+
"outputs": [
|
115
|
+
{
|
116
|
+
"internalType": "bool",
|
117
|
+
"name": "",
|
118
|
+
"type": "bool"
|
119
|
+
}
|
120
|
+
],
|
121
|
+
"stateMutability": "view",
|
122
|
+
"type": "function"
|
123
|
+
}
|
124
|
+
]
|
dkg/dataclasses.py
ADDED
@@ -0,0 +1,45 @@
|
|
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
|
+
import pandas as pd
|
21
|
+
|
22
|
+
|
23
|
+
class BlockchainResponseDict(dict):
|
24
|
+
pass
|
25
|
+
|
26
|
+
|
27
|
+
class HTTPRequestMethod(Enum):
|
28
|
+
GET = 1
|
29
|
+
POST = 2
|
30
|
+
|
31
|
+
|
32
|
+
class NodeResponseDict(dict):
|
33
|
+
def to_dataframe(self) -> pd.DataFrame:
|
34
|
+
return pd.DataFrame(self)
|
35
|
+
|
36
|
+
|
37
|
+
class KnowledgeAssetEnumStates(Enum):
|
38
|
+
LATEST = "LATEST"
|
39
|
+
LATEST_FINALIZED = "LATEST_FINALIZED"
|
40
|
+
|
41
|
+
|
42
|
+
class KnowledgeAssetContentVisibility(Enum):
|
43
|
+
ALL = "ALL"
|
44
|
+
PUBLIC = "PUBLIC"
|
45
|
+
PRIVATE = "PRIVATE"
|
dkg/exceptions.py
ADDED
@@ -0,0 +1,161 @@
|
|
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
|
+
class DKGException(Exception):
|
19
|
+
"""
|
20
|
+
Exception mixin inherited by all exceptions of dkg.py
|
21
|
+
This allows::
|
22
|
+
try:
|
23
|
+
some_call()
|
24
|
+
except DKGException:
|
25
|
+
# deal with dkg exception
|
26
|
+
except:
|
27
|
+
# deal with other exceptions
|
28
|
+
"""
|
29
|
+
|
30
|
+
|
31
|
+
class NetworkNotSupported(DKGException):
|
32
|
+
"""
|
33
|
+
Raised when blockchain provider is initialized for unsupported network.
|
34
|
+
"""
|
35
|
+
|
36
|
+
pass
|
37
|
+
|
38
|
+
|
39
|
+
class InvalidStateOption(DKGException):
|
40
|
+
"""
|
41
|
+
Raised when invalid state option given to the get operation.
|
42
|
+
"""
|
43
|
+
|
44
|
+
pass
|
45
|
+
|
46
|
+
|
47
|
+
class MissingKnowledgeAssetState(DKGException):
|
48
|
+
"""
|
49
|
+
Raised when search for the Knowledge Asset state on the network has failed.
|
50
|
+
"""
|
51
|
+
|
52
|
+
pass
|
53
|
+
|
54
|
+
|
55
|
+
class ValidationError(DKGException):
|
56
|
+
"""
|
57
|
+
Raised when something does not pass a validation check.
|
58
|
+
"""
|
59
|
+
|
60
|
+
pass
|
61
|
+
|
62
|
+
|
63
|
+
class InvalidRequest(DKGException):
|
64
|
+
"""
|
65
|
+
Raised by a manager to signal that blockchain/node request method
|
66
|
+
doesn't exist.
|
67
|
+
"""
|
68
|
+
|
69
|
+
pass
|
70
|
+
|
71
|
+
|
72
|
+
class HTTPRequestMethodNotSupported(DKGException):
|
73
|
+
"""
|
74
|
+
Raised if used HTTP method isn't supported
|
75
|
+
"""
|
76
|
+
|
77
|
+
pass
|
78
|
+
|
79
|
+
|
80
|
+
class NodeRequestError(DKGException):
|
81
|
+
"""
|
82
|
+
Raised by Node HTTP Provider if error occured during request.
|
83
|
+
"""
|
84
|
+
|
85
|
+
pass
|
86
|
+
|
87
|
+
|
88
|
+
class OperationNotFinished(DKGException):
|
89
|
+
"""
|
90
|
+
Raised when requested operation result isn't ready.
|
91
|
+
"""
|
92
|
+
|
93
|
+
pass
|
94
|
+
|
95
|
+
|
96
|
+
class OperationFailed(DKGException):
|
97
|
+
"""
|
98
|
+
Raised when requested operation status is failed.
|
99
|
+
"""
|
100
|
+
|
101
|
+
pass
|
102
|
+
|
103
|
+
|
104
|
+
class AccountMissing(DKGException):
|
105
|
+
"""
|
106
|
+
Raised when trying to perform state-changing blockchain transaction without account
|
107
|
+
specified.
|
108
|
+
"""
|
109
|
+
|
110
|
+
pass
|
111
|
+
|
112
|
+
|
113
|
+
class InvalidDataset(DKGException):
|
114
|
+
"""
|
115
|
+
Raised when dataset URDNA2015 normalization doesn't result in any quads.
|
116
|
+
"""
|
117
|
+
|
118
|
+
pass
|
119
|
+
|
120
|
+
|
121
|
+
class DatasetInputFormatNotSupported(DKGException):
|
122
|
+
"""
|
123
|
+
Raised when trying to normalize RDF dataset with not supported input format.
|
124
|
+
"""
|
125
|
+
|
126
|
+
pass
|
127
|
+
|
128
|
+
|
129
|
+
class DatasetOutputFormatNotSupported(DKGException):
|
130
|
+
"""
|
131
|
+
Raised when trying to convert RDF dataset to not supported output format.
|
132
|
+
"""
|
133
|
+
|
134
|
+
pass
|
135
|
+
|
136
|
+
|
137
|
+
class InvalidKnowledgeAsset(DKGException):
|
138
|
+
"""
|
139
|
+
Raised when root of the Merkle Tree built from N-Quads isn't the same as the
|
140
|
+
assertionId.
|
141
|
+
"""
|
142
|
+
|
143
|
+
pass
|
144
|
+
|
145
|
+
|
146
|
+
class InvalidTokenAmount(DKGException):
|
147
|
+
"""
|
148
|
+
Raised when token amount for operation isn't specified and suggested amount is less
|
149
|
+
or equal to what is already present in the contract.
|
150
|
+
"""
|
151
|
+
|
152
|
+
pass
|
153
|
+
|
154
|
+
|
155
|
+
class LeafNotInTree(DKGException):
|
156
|
+
"""
|
157
|
+
Raised when proof/verification requested for the leaf that is not the part of the
|
158
|
+
Merkle Tree.
|
159
|
+
"""
|
160
|
+
|
161
|
+
pass
|
dkg/graph.py
ADDED
@@ -0,0 +1,63 @@
|
|
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 rdflib.plugins.sparql.parser import parseQuery
|
19
|
+
|
20
|
+
from dkg.dataclasses import NodeResponseDict
|
21
|
+
from dkg.exceptions import OperationNotFinished
|
22
|
+
from dkg.manager import DefaultRequestManager
|
23
|
+
from dkg.method import Method
|
24
|
+
from dkg.module import Module
|
25
|
+
from dkg.types import NQuads
|
26
|
+
from dkg.utils.decorators import retry
|
27
|
+
from dkg.utils.node_request import NodeRequest, validate_operation_status
|
28
|
+
|
29
|
+
|
30
|
+
class Graph(Module):
|
31
|
+
def __init__(self, manager: DefaultRequestManager):
|
32
|
+
self.manager = manager
|
33
|
+
|
34
|
+
_query = Method(NodeRequest.query)
|
35
|
+
_get_operation_result = Method(NodeRequest.get_operation_result)
|
36
|
+
|
37
|
+
def query(
|
38
|
+
self,
|
39
|
+
query: str,
|
40
|
+
repository: str,
|
41
|
+
) -> NQuads:
|
42
|
+
parsed_query = parseQuery(query)
|
43
|
+
query_type = parsed_query[1].name.replace("Query", "").upper()
|
44
|
+
|
45
|
+
operation_id: NodeResponseDict = self._query(query, query_type, repository)[
|
46
|
+
"operationId"
|
47
|
+
]
|
48
|
+
operation_result = self.get_operation_result(operation_id, "query")
|
49
|
+
|
50
|
+
return operation_result["data"]
|
51
|
+
|
52
|
+
@retry(catch=OperationNotFinished, max_retries=5, base_delay=1, backoff=2)
|
53
|
+
def get_operation_result(
|
54
|
+
self, operation_id: str, operation: str
|
55
|
+
) -> NodeResponseDict:
|
56
|
+
operation_result = self._get_operation_result(
|
57
|
+
operation_id=operation_id,
|
58
|
+
operation=operation,
|
59
|
+
)
|
60
|
+
|
61
|
+
validate_operation_status(operation_result)
|
62
|
+
|
63
|
+
return operation_result
|
dkg/main.py
ADDED
@@ -0,0 +1,74 @@
|
|
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 functools import wraps
|
19
|
+
|
20
|
+
from dkg.asset import ContentAsset
|
21
|
+
from dkg.graph import Graph
|
22
|
+
from dkg.manager import DefaultRequestManager
|
23
|
+
from dkg.module import Module
|
24
|
+
from dkg.node import Node
|
25
|
+
from dkg.providers import BlockchainProvider, NodeHTTPProvider
|
26
|
+
from dkg.types import UAL, Address, ChecksumAddress
|
27
|
+
from dkg.utils.ual import format_ual, parse_ual
|
28
|
+
|
29
|
+
|
30
|
+
class DKG(Module):
|
31
|
+
asset: ContentAsset
|
32
|
+
node: Node
|
33
|
+
graph: Graph
|
34
|
+
|
35
|
+
@staticmethod
|
36
|
+
@wraps(format_ual)
|
37
|
+
def format_ual(
|
38
|
+
blockchain: str, contract_address: Address | ChecksumAddress, token_id: int
|
39
|
+
) -> UAL:
|
40
|
+
return format_ual(blockchain, contract_address, token_id)
|
41
|
+
|
42
|
+
@staticmethod
|
43
|
+
@wraps(parse_ual)
|
44
|
+
def parse_ual(ual: UAL) -> dict[str, str | Address | int]:
|
45
|
+
return parse_ual(ual)
|
46
|
+
|
47
|
+
def __init__(
|
48
|
+
self,
|
49
|
+
node_provider: NodeHTTPProvider,
|
50
|
+
blockchain_provider: BlockchainProvider,
|
51
|
+
):
|
52
|
+
self.manager = DefaultRequestManager(node_provider, blockchain_provider)
|
53
|
+
modules = {
|
54
|
+
"asset": ContentAsset(self.manager),
|
55
|
+
"node": Node(self.manager),
|
56
|
+
"graph": Graph(self.manager),
|
57
|
+
}
|
58
|
+
self._attach_modules(modules)
|
59
|
+
|
60
|
+
@property
|
61
|
+
def node_provider(self) -> NodeHTTPProvider:
|
62
|
+
return self.manager.node_provider
|
63
|
+
|
64
|
+
@node_provider.setter
|
65
|
+
def node_provider(self, node_provider: NodeHTTPProvider) -> None:
|
66
|
+
self.manager.node_provider = node_provider
|
67
|
+
|
68
|
+
@property
|
69
|
+
def blockchain_provider(self) -> BlockchainProvider:
|
70
|
+
return self.manager.blockchain_provider
|
71
|
+
|
72
|
+
@blockchain_provider.setter
|
73
|
+
def blockchain_provider(self, blockchain_provider: BlockchainProvider) -> None:
|
74
|
+
self.manager.blockchain_provider = blockchain_provider
|
dkg/manager.py
ADDED
@@ -0,0 +1,64 @@
|
|
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 typing import Any, Type
|
19
|
+
|
20
|
+
from dkg.dataclasses import BlockchainResponseDict, NodeResponseDict
|
21
|
+
from dkg.exceptions import InvalidRequest
|
22
|
+
from dkg.providers import BlockchainProvider, NodeHTTPProvider
|
23
|
+
from dkg.utils.blockchain_request import ContractInteraction, JSONRPCRequest
|
24
|
+
from dkg.utils.node_request import NodeCall
|
25
|
+
|
26
|
+
|
27
|
+
class DefaultRequestManager:
|
28
|
+
def __init__(
|
29
|
+
self, node_provider: NodeHTTPProvider, blockchain_provider: BlockchainProvider
|
30
|
+
):
|
31
|
+
self._node_provider = node_provider
|
32
|
+
self._blockchain_provider = blockchain_provider
|
33
|
+
|
34
|
+
@property
|
35
|
+
def node_provider(self) -> NodeHTTPProvider:
|
36
|
+
return self._node_provider
|
37
|
+
|
38
|
+
@node_provider.setter
|
39
|
+
def node_provider(self, node_provider: NodeHTTPProvider) -> None:
|
40
|
+
self._node_provider = node_provider
|
41
|
+
|
42
|
+
@property
|
43
|
+
def blockchain_provider(self) -> BlockchainProvider:
|
44
|
+
return self._blockchain_provider
|
45
|
+
|
46
|
+
@blockchain_provider.setter
|
47
|
+
def blockchain_provider(self, blockchain_provider: BlockchainProvider) -> None:
|
48
|
+
self._blockchain_provider = blockchain_provider
|
49
|
+
|
50
|
+
def blocking_request(
|
51
|
+
self,
|
52
|
+
request_type: Type[JSONRPCRequest | ContractInteraction | NodeCall],
|
53
|
+
request_params: dict[str, Any],
|
54
|
+
) -> BlockchainResponseDict | NodeResponseDict:
|
55
|
+
if issubclass(request_type, JSONRPCRequest):
|
56
|
+
return self.blockchain_provider.make_json_rpc_request(**request_params)
|
57
|
+
elif issubclass(request_type, ContractInteraction):
|
58
|
+
return self.blockchain_provider.call_function(**request_params)
|
59
|
+
elif issubclass(request_type, NodeCall):
|
60
|
+
return self.node_provider.make_request(**request_params)
|
61
|
+
else:
|
62
|
+
raise InvalidRequest(
|
63
|
+
"Invalid Request. Manager can only process Blockchain/Node requests."
|
64
|
+
)
|
dkg/method.py
ADDED
@@ -0,0 +1,131 @@
|
|
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 itertools
|
19
|
+
import re
|
20
|
+
from typing import TYPE_CHECKING, Any, Generic, Type
|
21
|
+
|
22
|
+
from dkg.exceptions import ValidationError
|
23
|
+
from dkg.types import TFunc
|
24
|
+
from dkg.utils.blockchain_request import (ContractInteraction,
|
25
|
+
ContractTransaction, JSONRPCRequest)
|
26
|
+
from dkg.utils.node_request import NodeCall
|
27
|
+
from dkg.utils.string_transformations import snake_to_camel
|
28
|
+
|
29
|
+
if TYPE_CHECKING:
|
30
|
+
from dkg.module import Module
|
31
|
+
|
32
|
+
|
33
|
+
class Method(Generic[TFunc]):
|
34
|
+
def __init__(self, action: JSONRPCRequest | ContractInteraction | NodeCall):
|
35
|
+
self.action = action
|
36
|
+
|
37
|
+
def __get__(
|
38
|
+
self, obj: "Module | None" = None, _: Type["Module"] | None = None
|
39
|
+
) -> TFunc:
|
40
|
+
if obj is None:
|
41
|
+
raise TypeError(
|
42
|
+
"Direct calls to methods are not supported. "
|
43
|
+
"Methods must be called from a module instance, "
|
44
|
+
"usually attached to a dkg instance."
|
45
|
+
)
|
46
|
+
return obj.retrieve_caller_fn(self)
|
47
|
+
|
48
|
+
def process_args(self, *args: Any, **kwargs: Any):
|
49
|
+
match self.action:
|
50
|
+
case JSONRPCRequest():
|
51
|
+
return {"args": self._validate_and_map(self.action.args, args, kwargs)}
|
52
|
+
case ContractInteraction():
|
53
|
+
return {
|
54
|
+
"args": self._validate_and_map(self.action.args, args, kwargs),
|
55
|
+
"state_changing": isinstance(self.action, ContractTransaction),
|
56
|
+
}
|
57
|
+
case NodeCall():
|
58
|
+
path_placeholders = re.findall(r"\{([^{}]+)?\}", self.action.path)
|
59
|
+
|
60
|
+
args_in_path = 0
|
61
|
+
path_args = []
|
62
|
+
path_kwargs = {}
|
63
|
+
if len(path_placeholders) > 0:
|
64
|
+
for placeholder in path_placeholders:
|
65
|
+
if (placeholder != "") and (placeholder in kwargs.keys()):
|
66
|
+
path_kwargs[placeholder] = kwargs.pop(placeholder)
|
67
|
+
else:
|
68
|
+
if len(args) <= args_in_path:
|
69
|
+
raise ValidationError(
|
70
|
+
"Number of given arguments can't be smaller than "
|
71
|
+
"number of path placeholders"
|
72
|
+
)
|
73
|
+
|
74
|
+
if placeholder == "":
|
75
|
+
path_args.append(args[args_in_path])
|
76
|
+
else:
|
77
|
+
path_kwargs[placeholder] = args[args_in_path]
|
78
|
+
|
79
|
+
args_in_path += 1
|
80
|
+
|
81
|
+
return {
|
82
|
+
"path": self.action.path.format(*path_args, **path_kwargs),
|
83
|
+
"params": self._validate_and_map(
|
84
|
+
self.action.params, args[args_in_path:], kwargs
|
85
|
+
)
|
86
|
+
if self.action.params
|
87
|
+
else {},
|
88
|
+
"data": self._validate_and_map(
|
89
|
+
self.action.data, args[args_in_path:], kwargs
|
90
|
+
)
|
91
|
+
if self.action.data
|
92
|
+
else {},
|
93
|
+
}
|
94
|
+
|
95
|
+
case _:
|
96
|
+
return {}
|
97
|
+
|
98
|
+
def _validate_and_map(
|
99
|
+
self,
|
100
|
+
required_args: dict[str, Type] | Type,
|
101
|
+
args: list[Any],
|
102
|
+
kwargs: dict[str, Any],
|
103
|
+
) -> dict[str, Any]:
|
104
|
+
if not isinstance(required_args, dict):
|
105
|
+
if (len(args) + len(kwargs)) != 1:
|
106
|
+
raise ValidationError("Exactly one argument must be provided.")
|
107
|
+
|
108
|
+
if len(args) == 1:
|
109
|
+
return args[0]
|
110
|
+
else:
|
111
|
+
return list(kwargs.values())[0]
|
112
|
+
|
113
|
+
if len(args) > len(required_args):
|
114
|
+
raise ValidationError(
|
115
|
+
"Number of positional arguments can't be bigger than "
|
116
|
+
"number of required arguments"
|
117
|
+
)
|
118
|
+
|
119
|
+
args_mapped = dict(zip(itertools.islice(required_args.keys(), len(args)), args))
|
120
|
+
camel_kwargs = {snake_to_camel(key): value for key, value in kwargs.items()}
|
121
|
+
|
122
|
+
processed_args = {}
|
123
|
+
processed_args.update(args_mapped)
|
124
|
+
processed_args.update(camel_kwargs)
|
125
|
+
|
126
|
+
if any(missing_params := (arg not in processed_args for arg in required_args)):
|
127
|
+
raise ValidationError(
|
128
|
+
f"Missing required arg(s): {', '.join(missing_params)}"
|
129
|
+
)
|
130
|
+
|
131
|
+
return processed_args
|