dkg.js 6.0.0 → 6.0.2
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.
- package/.eslintrc.js +2 -0
- package/README.md +1 -3
- package/constants.js +74 -9
- package/dist/dkg.min.js +1 -1
- package/dist/dkg.min.js.LICENSE.txt +93 -1111
- package/{demo.js → examples/demo-private.js} +24 -51
- package/{demo.html → examples/demo.html} +2 -4
- package/examples/demo.js +184 -0
- package/{socket-front-demo.html → examples/socket-front-demo.html} +1 -1
- package/{sockets-demo.js → examples/sockets-demo.js} +2 -2
- package/managers/asset-operations-manager.js +832 -150
- package/managers/graph-operations-manager.js +55 -6
- package/managers/node-operations-manager.js +16 -2
- package/package.json +11 -13
- package/services/base-service-manager.js +3 -0
- package/services/blockchain-service/blockchain-service-base.js +262 -91
- package/services/blockchain-service/implementations/browser-blockchain-service.js +5 -21
- package/services/blockchain-service/implementations/node-blockchain-service.js +6 -21
- package/services/input-service.js +167 -0
- package/services/node-api-service/implementations/http-service.js +93 -74
- package/services/utilities.js +62 -24
- package/services/validation-service.js +289 -52
- package/webpack.config.js +8 -2
|
@@ -1,54 +1,97 @@
|
|
|
1
1
|
const { assertionMetadata, formatAssertion, calculateRoot } = require('assertion-tools');
|
|
2
|
-
const
|
|
2
|
+
const { ethers } = require('ethers');
|
|
3
3
|
const {
|
|
4
4
|
isEmptyObject,
|
|
5
5
|
deriveUAL,
|
|
6
6
|
getOperationStatusObject,
|
|
7
7
|
resolveUAL,
|
|
8
|
+
toNQuads,
|
|
9
|
+
toJSONLD,
|
|
10
|
+
sleepForMilliseconds,
|
|
11
|
+
deriveRepository,
|
|
8
12
|
} = require('../services/utilities.js');
|
|
9
13
|
const {
|
|
14
|
+
CONTENT_TYPES,
|
|
10
15
|
OPERATIONS,
|
|
11
|
-
DEFAULT_HASH_FUNCTION_ID,
|
|
12
16
|
OPERATIONS_STEP_STATUS,
|
|
13
17
|
GET_OUTPUT_FORMATS,
|
|
14
18
|
OPERATION_STATUSES,
|
|
15
19
|
DEFAULT_GET_LOCAL_STORE_RESULT_FREQUENCY,
|
|
16
20
|
PRIVATE_ASSERTION_PREDICATE,
|
|
21
|
+
QUERY_TYPES,
|
|
22
|
+
DEFAULT_PARAMETERS,
|
|
17
23
|
} = require('../constants.js');
|
|
18
24
|
const emptyHooks = require('../util/empty-hooks');
|
|
25
|
+
const { STORE_TYPES, ASSET_STATES } = require('../constants');
|
|
19
26
|
|
|
20
27
|
class AssetOperationsManager {
|
|
21
28
|
constructor(config, services) {
|
|
22
29
|
this.nodeApiService = services.nodeApiService;
|
|
23
30
|
this.validationService = services.validationService;
|
|
24
31
|
this.blockchainService = services.blockchainService;
|
|
32
|
+
this.inputService = services.inputService;
|
|
25
33
|
}
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Creates a new asset.
|
|
37
|
+
* @async
|
|
38
|
+
* @param {Object} content - The content of the asset to be created, contains public, private or both keys.
|
|
39
|
+
* @param {Object} [options={}] - Additional options for asset creation.
|
|
40
|
+
* @param {Object} [stepHooks=emptyHooks] - Hooks to execute during asset creation.
|
|
41
|
+
* @returns {Object} Object containing UAL, publicAssertionId and operation status.
|
|
42
|
+
*/
|
|
43
|
+
async create(content, options = {}, stepHooks = emptyHooks) {
|
|
44
|
+
this.validationService.validateObjectType(content);
|
|
45
|
+
let jsonContent = {};
|
|
32
46
|
|
|
33
47
|
// for backwards compatibility
|
|
34
|
-
if (!
|
|
35
|
-
|
|
48
|
+
if (!content.public && !content.private) {
|
|
49
|
+
jsonContent.public = content;
|
|
36
50
|
} else {
|
|
37
|
-
|
|
51
|
+
jsonContent = content;
|
|
38
52
|
}
|
|
39
53
|
|
|
40
|
-
|
|
54
|
+
const {
|
|
55
|
+
blockchain,
|
|
56
|
+
endpoint,
|
|
57
|
+
port,
|
|
58
|
+
maxNumberOfRetries,
|
|
59
|
+
frequency,
|
|
60
|
+
epochsNum,
|
|
61
|
+
hashFunctionId,
|
|
62
|
+
scoreFunctionId,
|
|
63
|
+
immutable,
|
|
64
|
+
tokenAmount,
|
|
65
|
+
authToken,
|
|
66
|
+
} = this.inputService.getAssetCreateArguments(options);
|
|
67
|
+
|
|
68
|
+
this.validationService.validateAssetCreate(
|
|
69
|
+
jsonContent,
|
|
70
|
+
blockchain,
|
|
71
|
+
endpoint,
|
|
72
|
+
port,
|
|
73
|
+
maxNumberOfRetries,
|
|
74
|
+
frequency,
|
|
75
|
+
epochsNum,
|
|
76
|
+
hashFunctionId,
|
|
77
|
+
scoreFunctionId,
|
|
78
|
+
immutable,
|
|
79
|
+
tokenAmount,
|
|
80
|
+
authToken,
|
|
81
|
+
);
|
|
41
82
|
|
|
42
83
|
let privateAssertion;
|
|
43
84
|
let privateAssertionId;
|
|
44
|
-
if (
|
|
45
|
-
privateAssertion = await formatAssertion(
|
|
85
|
+
if (jsonContent.private && !isEmptyObject(jsonContent.private)) {
|
|
86
|
+
privateAssertion = await formatAssertion(jsonContent.private);
|
|
46
87
|
privateAssertionId = calculateRoot(privateAssertion);
|
|
47
88
|
}
|
|
48
89
|
const publicGraph = {
|
|
49
90
|
'@graph': [
|
|
50
|
-
|
|
51
|
-
|
|
91
|
+
jsonContent.public && !isEmptyObject(jsonContent.public)
|
|
92
|
+
? jsonContent.public
|
|
93
|
+
: null,
|
|
94
|
+
jsonContent.private && !isEmptyObject(jsonContent.private)
|
|
52
95
|
? {
|
|
53
96
|
[PRIVATE_ASSERTION_PREDICATE]: privateAssertionId,
|
|
54
97
|
}
|
|
@@ -58,88 +101,112 @@ class AssetOperationsManager {
|
|
|
58
101
|
const publicAssertion = await formatAssertion(publicGraph);
|
|
59
102
|
const publicAssertionId = calculateRoot(publicAssertion);
|
|
60
103
|
|
|
61
|
-
const blockchain = this.blockchainService.getBlockchain(options);
|
|
62
104
|
const contentAssetStorageAddress = await this.blockchainService.getContractAddress(
|
|
63
|
-
blockchain.name,
|
|
64
105
|
'ContentAssetStorage',
|
|
65
|
-
blockchain
|
|
106
|
+
blockchain,
|
|
66
107
|
);
|
|
108
|
+
|
|
67
109
|
const tokenAmountInWei =
|
|
68
|
-
|
|
110
|
+
tokenAmount ??
|
|
69
111
|
(await this.nodeApiService.getBidSuggestion(
|
|
112
|
+
endpoint,
|
|
113
|
+
port,
|
|
114
|
+
authToken,
|
|
70
115
|
blockchain.name.startsWith('otp') ? 'otp' : blockchain.name,
|
|
71
|
-
|
|
116
|
+
epochsNum,
|
|
72
117
|
assertionMetadata.getAssertionSizeInBytes(publicAssertion),
|
|
73
118
|
contentAssetStorageAddress,
|
|
74
119
|
publicAssertionId,
|
|
75
|
-
|
|
76
|
-
options,
|
|
120
|
+
hashFunctionId,
|
|
77
121
|
));
|
|
122
|
+
|
|
78
123
|
const tokenId = await this.blockchainService.createAsset(
|
|
79
124
|
{
|
|
80
125
|
publicAssertionId,
|
|
81
126
|
assertionSize: assertionMetadata.getAssertionSizeInBytes(publicAssertion),
|
|
82
127
|
triplesNumber: assertionMetadata.getAssertionTriplesNumber(publicAssertion),
|
|
83
128
|
chunksNumber: assertionMetadata.getAssertionChunksNumber(publicAssertion),
|
|
84
|
-
epochsNum
|
|
129
|
+
epochsNum,
|
|
85
130
|
tokenAmount: tokenAmountInWei,
|
|
86
|
-
scoreFunctionId:
|
|
87
|
-
immutable_:
|
|
131
|
+
scoreFunctionId: scoreFunctionId ?? 1,
|
|
132
|
+
immutable_: immutable,
|
|
88
133
|
},
|
|
89
|
-
|
|
134
|
+
blockchain,
|
|
90
135
|
stepHooks,
|
|
91
136
|
);
|
|
92
137
|
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
138
|
+
const resolvedUAL = {
|
|
139
|
+
blockchain: blockchain.name.startsWith('otp') ? 'otp' : blockchain.name,
|
|
140
|
+
contract: contentAssetStorageAddress,
|
|
141
|
+
tokenId,
|
|
142
|
+
};
|
|
143
|
+
const assertions = [
|
|
144
|
+
{
|
|
145
|
+
...resolvedUAL,
|
|
146
|
+
assertionId: publicAssertionId,
|
|
147
|
+
assertion: publicAssertion,
|
|
148
|
+
storeType: STORE_TYPES.TRIPLE,
|
|
149
|
+
},
|
|
150
|
+
];
|
|
97
151
|
if (privateAssertion?.length) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
tokenId,
|
|
104
|
-
assertionId: publicAssertionId,
|
|
105
|
-
assertion: publicAssertion,
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
blockchain: blockchain.name,
|
|
109
|
-
contract: contentAssetStorageAddress,
|
|
110
|
-
tokenId,
|
|
111
|
-
assertionId: privateAssertionId,
|
|
112
|
-
assertion: privateAssertion,
|
|
113
|
-
},
|
|
114
|
-
],
|
|
115
|
-
options,
|
|
116
|
-
);
|
|
117
|
-
operationResult = await this.nodeApiService.getOperationResult(operationId, {
|
|
118
|
-
...options,
|
|
119
|
-
operation: OPERATIONS.LOCAL_STORE,
|
|
120
|
-
frequency: DEFAULT_GET_LOCAL_STORE_RESULT_FREQUENCY,
|
|
152
|
+
assertions.push({
|
|
153
|
+
...resolvedUAL,
|
|
154
|
+
assertionId: privateAssertionId,
|
|
155
|
+
assertion: privateAssertion,
|
|
156
|
+
storeType: STORE_TYPES.TRIPLE,
|
|
121
157
|
});
|
|
158
|
+
}
|
|
159
|
+
let operationId = await this.nodeApiService.localStore(
|
|
160
|
+
endpoint,
|
|
161
|
+
port,
|
|
162
|
+
authToken,
|
|
163
|
+
assertions,
|
|
164
|
+
);
|
|
165
|
+
let operationResult = await this.nodeApiService.getOperationResult(
|
|
166
|
+
endpoint,
|
|
167
|
+
port,
|
|
168
|
+
authToken,
|
|
169
|
+
OPERATIONS.LOCAL_STORE,
|
|
170
|
+
maxNumberOfRetries,
|
|
171
|
+
DEFAULT_GET_LOCAL_STORE_RESULT_FREQUENCY,
|
|
172
|
+
operationId,
|
|
173
|
+
);
|
|
122
174
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
175
|
+
const UAL = deriveUAL(
|
|
176
|
+
blockchain.name.startsWith('otp') ? 'otp' : blockchain.name,
|
|
177
|
+
contentAssetStorageAddress,
|
|
178
|
+
tokenId,
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
if (operationResult.status === OPERATION_STATUSES.FAILED) {
|
|
182
|
+
return {
|
|
183
|
+
UAL,
|
|
184
|
+
assertionId: publicAssertionId,
|
|
185
|
+
operation: getOperationStatusObject(operationResult, operationId),
|
|
186
|
+
};
|
|
130
187
|
}
|
|
131
188
|
|
|
132
189
|
operationId = await this.nodeApiService.publish(
|
|
190
|
+
endpoint,
|
|
191
|
+
port,
|
|
192
|
+
authToken,
|
|
133
193
|
publicAssertionId,
|
|
134
194
|
publicAssertion,
|
|
135
|
-
|
|
136
|
-
|
|
195
|
+
blockchain.name.startsWith('otp') ? 'otp' : blockchain.name,
|
|
196
|
+
contentAssetStorageAddress,
|
|
197
|
+
tokenId,
|
|
198
|
+
hashFunctionId,
|
|
137
199
|
);
|
|
138
200
|
|
|
139
|
-
operationResult = await this.nodeApiService.getOperationResult(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
201
|
+
operationResult = await this.nodeApiService.getOperationResult(
|
|
202
|
+
endpoint,
|
|
203
|
+
port,
|
|
204
|
+
authToken,
|
|
205
|
+
OPERATIONS.PUBLISH,
|
|
206
|
+
maxNumberOfRetries,
|
|
207
|
+
frequency,
|
|
208
|
+
operationId,
|
|
209
|
+
);
|
|
143
210
|
|
|
144
211
|
stepHooks.afterHook({
|
|
145
212
|
status: OPERATIONS_STEP_STATUS.CREATE_ASSET_COMPLETED,
|
|
@@ -156,104 +223,473 @@ class AssetOperationsManager {
|
|
|
156
223
|
};
|
|
157
224
|
}
|
|
158
225
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
226
|
+
/**
|
|
227
|
+
* Retrieves a public or private assertion for a given UAL.
|
|
228
|
+
* @async
|
|
229
|
+
* @param {string} UAL - The Universal Asset Locator
|
|
230
|
+
* @param {Object} [options={}] - Optional parameters for the asset get operation.
|
|
231
|
+
* @param {string} [options.state] - The state of the asset, "latest" or "finalized".
|
|
232
|
+
* @param {string} [options.contentType] - The type of content to retrieve, either "public", "private" or "all".
|
|
233
|
+
* @param {boolean} [options.validate] - Whether to validate the retrieved assertion.
|
|
234
|
+
* @param {string} [options.outputFormat] - The format of the retrieved assertion output, either "n-quads" or "json-ld".
|
|
235
|
+
* @returns {Object} - The result of the asset get operation.
|
|
236
|
+
*/
|
|
237
|
+
async get(UAL, options = {}) {
|
|
238
|
+
const {
|
|
239
|
+
blockchain,
|
|
240
|
+
endpoint,
|
|
241
|
+
port,
|
|
242
|
+
maxNumberOfRetries,
|
|
243
|
+
frequency,
|
|
244
|
+
state,
|
|
245
|
+
contentType,
|
|
246
|
+
validate,
|
|
247
|
+
outputFormat,
|
|
248
|
+
authToken,
|
|
249
|
+
hashFunctionId,
|
|
250
|
+
} = this.inputService.getAssetGetArguments(options);
|
|
251
|
+
|
|
252
|
+
this.validationService.validateAssetGet(
|
|
253
|
+
UAL,
|
|
254
|
+
blockchain,
|
|
255
|
+
endpoint,
|
|
256
|
+
port,
|
|
257
|
+
maxNumberOfRetries,
|
|
258
|
+
frequency,
|
|
259
|
+
state,
|
|
260
|
+
contentType,
|
|
261
|
+
hashFunctionId,
|
|
262
|
+
validate,
|
|
263
|
+
outputFormat,
|
|
264
|
+
authToken,
|
|
265
|
+
);
|
|
266
|
+
|
|
162
267
|
const { tokenId } = resolveUAL(UAL);
|
|
268
|
+
let hasPendingUpdate = false;
|
|
269
|
+
if (state === ASSET_STATES.LATEST) {
|
|
270
|
+
hasPendingUpdate = await this.blockchainService.hasPendingUpdate(tokenId, blockchain);
|
|
271
|
+
}
|
|
163
272
|
|
|
164
|
-
const
|
|
273
|
+
const publicAssertionId = hasPendingUpdate
|
|
274
|
+
? await this.blockchainService.getUnfinalizedState(tokenId, blockchain)
|
|
275
|
+
: await this.blockchainService.getLatestAssertionId(tokenId, blockchain);
|
|
165
276
|
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
277
|
+
const getPublicOperationId = await this.nodeApiService.get(
|
|
278
|
+
endpoint,
|
|
279
|
+
port,
|
|
280
|
+
authToken,
|
|
281
|
+
UAL,
|
|
282
|
+
state,
|
|
283
|
+
hashFunctionId,
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
const getPublicOperationResult = await this.nodeApiService.getOperationResult(
|
|
287
|
+
endpoint,
|
|
288
|
+
port,
|
|
289
|
+
authToken,
|
|
290
|
+
OPERATIONS.GET,
|
|
291
|
+
maxNumberOfRetries,
|
|
292
|
+
frequency,
|
|
293
|
+
getPublicOperationId,
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
if(!getPublicOperationResult.data.assertion) {
|
|
297
|
+
return {
|
|
298
|
+
errorType: 'DKG_CLIENT_ERROR',
|
|
299
|
+
errorMessage: "Unable to find assertion on the network!",
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const publicAssertion = getPublicOperationResult.data.assertion;
|
|
304
|
+
|
|
305
|
+
if (validate === true && calculateRoot(publicAssertion) !== publicAssertionId) {
|
|
306
|
+
getPublicOperationResult.data = {
|
|
307
|
+
errorType: 'DKG_CLIENT_ERROR',
|
|
308
|
+
errorMessage: "Calculated root hashes don't match!",
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
let result = { operation: {} };
|
|
313
|
+
if (contentType !== CONTENT_TYPES.PRIVATE) {
|
|
314
|
+
let formattedPublicAssertion = publicAssertion;
|
|
173
315
|
try {
|
|
174
|
-
if (
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (options.outputFormat !== GET_OUTPUT_FORMATS.N_QUADS) {
|
|
179
|
-
assertion = await jsonld.fromRDF(assertion.join('\n'), {
|
|
180
|
-
algorithm: 'URDNA2015',
|
|
181
|
-
format: 'application/n-quads',
|
|
182
|
-
});
|
|
316
|
+
if (outputFormat !== GET_OUTPUT_FORMATS.N_QUADS) {
|
|
317
|
+
formattedPublicAssertion = await toJSONLD(publicAssertion.join('\n'));
|
|
318
|
+
} else {
|
|
319
|
+
formattedPublicAssertion = publicAssertion.join('\n');
|
|
183
320
|
}
|
|
184
321
|
} catch (error) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
322
|
+
getPublicOperationResult.data = {
|
|
323
|
+
errorType: 'DKG_CLIENT_ERROR',
|
|
324
|
+
errorMessage: error.message,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (contentType === CONTENT_TYPES.PUBLIC) {
|
|
329
|
+
result = {
|
|
330
|
+
...result,
|
|
331
|
+
assertion: formattedPublicAssertion,
|
|
332
|
+
assertionId: publicAssertionId,
|
|
333
|
+
};
|
|
334
|
+
} else {
|
|
335
|
+
result.public = {
|
|
336
|
+
assertion: formattedPublicAssertion,
|
|
337
|
+
assertionId: publicAssertionId,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
result.operation.publicGet = getOperationStatusObject(
|
|
342
|
+
getPublicOperationResult,
|
|
343
|
+
getPublicOperationId,
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (contentType !== CONTENT_TYPES.PUBLIC) {
|
|
348
|
+
const privateAssertionLinkTriple = publicAssertion.filter((element) =>
|
|
349
|
+
element.includes(PRIVATE_ASSERTION_PREDICATE),
|
|
350
|
+
)[0];
|
|
351
|
+
|
|
352
|
+
let queryPrivateOperationId;
|
|
353
|
+
let queryPrivateOperationResult = {};
|
|
354
|
+
if (privateAssertionLinkTriple) {
|
|
355
|
+
const privateAssertionId = privateAssertionLinkTriple.match(/"(.*?)"/)[1];
|
|
356
|
+
let privateAssertion;
|
|
357
|
+
if (getPublicOperationResult?.data?.privateAssertion?.length)
|
|
358
|
+
privateAssertion = getPublicOperationResult.data.privateAssertion;
|
|
359
|
+
else {
|
|
360
|
+
const queryString = `
|
|
361
|
+
CONSTRUCT { ?s ?p ?o }
|
|
362
|
+
WHERE {
|
|
363
|
+
{
|
|
364
|
+
GRAPH <assertion:${privateAssertionId}>
|
|
365
|
+
{
|
|
366
|
+
?s ?p ?o .
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}`;
|
|
370
|
+
|
|
371
|
+
const repository = deriveRepository(
|
|
372
|
+
DEFAULT_PARAMETERS.GRAPH_LOCATION,
|
|
373
|
+
DEFAULT_PARAMETERS.GRAPH_STATE,
|
|
374
|
+
);
|
|
375
|
+
queryPrivateOperationId = await this.nodeApiService.query(
|
|
376
|
+
endpoint,
|
|
377
|
+
port,
|
|
378
|
+
authToken,
|
|
379
|
+
queryString,
|
|
380
|
+
QUERY_TYPES.CONSTRUCT,
|
|
381
|
+
repository
|
|
382
|
+
);
|
|
383
|
+
|
|
384
|
+
queryPrivateOperationResult = await this.nodeApiService.getOperationResult(
|
|
385
|
+
endpoint,
|
|
386
|
+
port,
|
|
387
|
+
authToken,
|
|
388
|
+
OPERATIONS.QUERY,
|
|
389
|
+
maxNumberOfRetries,
|
|
390
|
+
frequency,
|
|
391
|
+
queryPrivateOperationId,
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
const privateAssertionNQuads = queryPrivateOperationResult.data;
|
|
395
|
+
|
|
396
|
+
privateAssertion = await toNQuads(
|
|
397
|
+
privateAssertionNQuads,
|
|
398
|
+
'application/n-quads',
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
let formattedPrivateAssertion;
|
|
403
|
+
if (
|
|
404
|
+
privateAssertion.length &&
|
|
405
|
+
validate === true &&
|
|
406
|
+
calculateRoot(privateAssertion) !== privateAssertionId
|
|
407
|
+
) {
|
|
408
|
+
queryPrivateOperationResult.data = {
|
|
409
|
+
errorType: 'DKG_CLIENT_ERROR',
|
|
410
|
+
errorMessage: "Calculated root hashes don't match!",
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
if (outputFormat !== GET_OUTPUT_FORMATS.N_QUADS) {
|
|
416
|
+
formattedPrivateAssertion = await toJSONLD(privateAssertion.join('\n'));
|
|
417
|
+
} else {
|
|
418
|
+
formattedPrivateAssertion = privateAssertion.join('\n');
|
|
419
|
+
}
|
|
420
|
+
} catch (error) {
|
|
421
|
+
queryPrivateOperationResult.data = {
|
|
188
422
|
errorType: 'DKG_CLIENT_ERROR',
|
|
189
423
|
errorMessage: error.message,
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (contentType === CONTENT_TYPES.PRIVATE) {
|
|
428
|
+
result = {
|
|
429
|
+
...result,
|
|
430
|
+
assertion: formattedPrivateAssertion,
|
|
431
|
+
assertionId: privateAssertionId,
|
|
432
|
+
};
|
|
433
|
+
} else {
|
|
434
|
+
result.private = {
|
|
435
|
+
assertion: formattedPrivateAssertion,
|
|
436
|
+
assertionId: privateAssertionId,
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
if (queryPrivateOperationId) {
|
|
440
|
+
result.operation.queryPrivate = getOperationStatusObject(
|
|
441
|
+
queryPrivateOperationResult,
|
|
442
|
+
queryPrivateOperationId,
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return result;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Updates an existing asset.
|
|
453
|
+
* @async
|
|
454
|
+
* @param {string} UAL - The Universal Asset Locator
|
|
455
|
+
* @param {Object} content - The content of the asset to be updated.
|
|
456
|
+
* @param {Object} [options={}] - Additional options for asset update.
|
|
457
|
+
* @returns {Object} Object containing UAL, publicAssertionId and operation status.
|
|
458
|
+
*/
|
|
459
|
+
async update(UAL, content, options = {}) {
|
|
460
|
+
this.validationService.validateObjectType(content);
|
|
461
|
+
const jsonContent = content;
|
|
462
|
+
|
|
463
|
+
const {
|
|
464
|
+
blockchain,
|
|
465
|
+
endpoint,
|
|
466
|
+
port,
|
|
467
|
+
maxNumberOfRetries,
|
|
468
|
+
frequency,
|
|
469
|
+
hashFunctionId,
|
|
470
|
+
scoreFunctionId,
|
|
471
|
+
tokenAmount,
|
|
472
|
+
authToken,
|
|
473
|
+
} = this.inputService.getAssetUpdateArguments(options);
|
|
474
|
+
|
|
475
|
+
this.validationService.validateAssetUpdate(
|
|
476
|
+
jsonContent,
|
|
477
|
+
blockchain,
|
|
478
|
+
endpoint,
|
|
479
|
+
port,
|
|
480
|
+
maxNumberOfRetries,
|
|
481
|
+
frequency,
|
|
482
|
+
hashFunctionId,
|
|
483
|
+
scoreFunctionId,
|
|
484
|
+
tokenAmount,
|
|
485
|
+
authToken,
|
|
486
|
+
);
|
|
487
|
+
|
|
488
|
+
const { tokenId } = resolveUAL(UAL);
|
|
489
|
+
|
|
490
|
+
let privateAssertion;
|
|
491
|
+
let privateAssertionId;
|
|
492
|
+
if (jsonContent.private && !isEmptyObject(jsonContent.private)) {
|
|
493
|
+
privateAssertion = await formatAssertion(jsonContent.private);
|
|
494
|
+
privateAssertionId = calculateRoot(privateAssertion);
|
|
495
|
+
}
|
|
496
|
+
const publicGraph = {
|
|
497
|
+
'@graph': [
|
|
498
|
+
jsonContent.public && !isEmptyObject(jsonContent.public)
|
|
499
|
+
? jsonContent.public
|
|
500
|
+
: null,
|
|
501
|
+
jsonContent.private && !isEmptyObject(jsonContent.private)
|
|
502
|
+
? {
|
|
503
|
+
[PRIVATE_ASSERTION_PREDICATE]: privateAssertionId,
|
|
504
|
+
}
|
|
505
|
+
: null,
|
|
506
|
+
],
|
|
507
|
+
};
|
|
508
|
+
const publicAssertion = await formatAssertion(publicGraph);
|
|
509
|
+
const publicAssertionId = calculateRoot(publicAssertion);
|
|
510
|
+
|
|
511
|
+
const contentAssetStorageAddress = await this.blockchainService.getContractAddress(
|
|
512
|
+
'ContentAssetStorage',
|
|
513
|
+
blockchain,
|
|
514
|
+
);
|
|
515
|
+
|
|
516
|
+
let tokenAmountInWei;
|
|
517
|
+
|
|
518
|
+
if (tokenAmount != null) {
|
|
519
|
+
tokenAmountInWei = tokenAmount;
|
|
520
|
+
} else {
|
|
521
|
+
tokenAmountInWei = await this._getUpdateBidSuggestion(
|
|
522
|
+
UAL,
|
|
523
|
+
blockchain,
|
|
524
|
+
endpoint,
|
|
525
|
+
port,
|
|
526
|
+
authToken,
|
|
527
|
+
publicAssertionId,
|
|
528
|
+
assertionMetadata.getAssertionSizeInBytes(publicAssertion),
|
|
529
|
+
hashFunctionId,
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
await this.blockchainService.updateAsset(
|
|
534
|
+
tokenId,
|
|
535
|
+
publicAssertionId,
|
|
536
|
+
assertionMetadata.getAssertionSizeInBytes(publicAssertion),
|
|
537
|
+
assertionMetadata.getAssertionTriplesNumber(publicAssertion),
|
|
538
|
+
assertionMetadata.getAssertionChunksNumber(publicAssertion),
|
|
539
|
+
tokenAmountInWei,
|
|
540
|
+
blockchain,
|
|
541
|
+
);
|
|
542
|
+
|
|
543
|
+
const resolvedUAL = {
|
|
544
|
+
blockchain: blockchain.name.startsWith('otp') ? 'otp' : blockchain.name,
|
|
545
|
+
contract: contentAssetStorageAddress,
|
|
546
|
+
tokenId,
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
const assertions = [
|
|
550
|
+
{
|
|
551
|
+
...resolvedUAL,
|
|
552
|
+
assertionId: publicAssertionId,
|
|
553
|
+
assertion: publicAssertion,
|
|
554
|
+
storeType: STORE_TYPES.PENDING,
|
|
555
|
+
},
|
|
556
|
+
];
|
|
557
|
+
|
|
558
|
+
if (privateAssertion?.length) {
|
|
559
|
+
assertions.push({
|
|
560
|
+
...resolvedUAL,
|
|
561
|
+
assertionId: privateAssertionId,
|
|
562
|
+
assertion: privateAssertion,
|
|
563
|
+
storeType: STORE_TYPES.PENDING,
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
let operationId = await this.nodeApiService.localStore(
|
|
568
|
+
endpoint,
|
|
569
|
+
port,
|
|
570
|
+
authToken,
|
|
571
|
+
assertions,
|
|
572
|
+
);
|
|
573
|
+
|
|
574
|
+
let operationResult = await this.nodeApiService.getOperationResult(
|
|
575
|
+
endpoint,
|
|
576
|
+
port,
|
|
577
|
+
authToken,
|
|
578
|
+
OPERATIONS.LOCAL_STORE,
|
|
579
|
+
maxNumberOfRetries,
|
|
580
|
+
DEFAULT_GET_LOCAL_STORE_RESULT_FREQUENCY,
|
|
581
|
+
operationId,
|
|
582
|
+
);
|
|
583
|
+
|
|
584
|
+
if (operationResult.status === OPERATION_STATUSES.FAILED) {
|
|
585
|
+
return {
|
|
586
|
+
UAL,
|
|
587
|
+
assertionId: publicAssertionId,
|
|
588
|
+
operation: getOperationStatusObject(operationResult, operationId),
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
operationId = await this.nodeApiService.update(
|
|
593
|
+
endpoint,
|
|
594
|
+
port,
|
|
595
|
+
authToken,
|
|
596
|
+
publicAssertionId,
|
|
597
|
+
publicAssertion,
|
|
598
|
+
blockchain.name.startsWith('otp') ? 'otp' : blockchain.name,
|
|
599
|
+
contentAssetStorageAddress,
|
|
600
|
+
tokenId,
|
|
601
|
+
hashFunctionId,
|
|
602
|
+
);
|
|
603
|
+
operationResult = await this.nodeApiService.getOperationResult(
|
|
604
|
+
endpoint,
|
|
605
|
+
port,
|
|
606
|
+
authToken,
|
|
607
|
+
OPERATIONS.UPDATE,
|
|
608
|
+
maxNumberOfRetries,
|
|
609
|
+
frequency,
|
|
610
|
+
operationId,
|
|
611
|
+
);
|
|
612
|
+
return {
|
|
613
|
+
UAL,
|
|
614
|
+
operation: getOperationStatusObject(operationResult, operationId),
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
async waitFinalization(UAL, options = {}) {
|
|
619
|
+
const blockchain = this.inputService.getBlockchain(options);
|
|
620
|
+
const frequency = this.inputService.getFrequency(options);
|
|
621
|
+
const maxNumberOfRetries = this.inputService.getMaxNumberOfRetries(options);
|
|
622
|
+
|
|
623
|
+
this.validationService.validateWaitAssetUpdateFinalization(UAL, blockchain);
|
|
624
|
+
|
|
625
|
+
const { tokenId } = resolveUAL(UAL);
|
|
626
|
+
const response = {
|
|
627
|
+
status: OPERATION_STATUSES.PENDING,
|
|
628
|
+
};
|
|
629
|
+
let pendingUpdate = true;
|
|
630
|
+
let retries = 0;
|
|
631
|
+
do {
|
|
632
|
+
if (retries > maxNumberOfRetries) {
|
|
633
|
+
response.data = {
|
|
634
|
+
...response.data,
|
|
635
|
+
data: {
|
|
636
|
+
errorType: 'DKG_CLIENT_ERROR',
|
|
637
|
+
errorMessage: 'Unable to get results. Max number of retries reached.',
|
|
190
638
|
},
|
|
191
639
|
};
|
|
640
|
+
break;
|
|
192
641
|
}
|
|
642
|
+
retries += 1;
|
|
643
|
+
// eslint-disable-next-line no-await-in-loop
|
|
644
|
+
await sleepForMilliseconds(frequency * 1000);
|
|
645
|
+
// eslint-disable-next-line no-await-in-loop
|
|
646
|
+
pendingUpdate = await this.blockchainService.hasPendingUpdate(tokenId, blockchain);
|
|
647
|
+
} while (pendingUpdate);
|
|
648
|
+
if (pendingUpdate) {
|
|
649
|
+
response.status = OPERATION_STATUSES.PENDING;
|
|
650
|
+
} else {
|
|
651
|
+
response.status = OPERATION_STATUSES.COMPLETED;
|
|
193
652
|
}
|
|
194
653
|
|
|
195
654
|
return {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
655
|
+
UAL,
|
|
656
|
+
operation: getOperationStatusObject(
|
|
657
|
+
{ data: response.data, status: response.status },
|
|
658
|
+
null,
|
|
659
|
+
),
|
|
199
660
|
};
|
|
200
661
|
}
|
|
201
662
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
options
|
|
230
|
-
);
|
|
231
|
-
let operationId = await this.nodeApiService.publish(
|
|
232
|
-
assertionId,
|
|
233
|
-
assertion,
|
|
234
|
-
UAL,
|
|
235
|
-
options
|
|
236
|
-
);
|
|
237
|
-
let operationResult = await this.nodeApiService.getOperationResult(
|
|
238
|
-
operationId,
|
|
239
|
-
{ ...options, operation: OPERATIONS.PUBLISH }
|
|
240
|
-
);
|
|
241
|
-
return {
|
|
242
|
-
UAL,
|
|
243
|
-
assertionId,
|
|
244
|
-
operation: Utilities.getOperationStatusObject(
|
|
245
|
-
operationResult,
|
|
246
|
-
operationId
|
|
247
|
-
),
|
|
248
|
-
};
|
|
249
|
-
} */
|
|
250
|
-
|
|
251
|
-
async transfer(UAL, to, opts = {}) {
|
|
252
|
-
const options = JSON.parse(JSON.stringify(opts));
|
|
253
|
-
this.validationService.validateAssetTransferRequest(UAL, to, options);
|
|
663
|
+
async cancelUpdate(UAL, options = {}) {
|
|
664
|
+
const blockchain = this.inputService.getBlockchain(options);
|
|
665
|
+
|
|
666
|
+
this.validationService.validateAssetUpdateCancel(UAL, blockchain);
|
|
667
|
+
|
|
668
|
+
const { tokenId } = resolveUAL(UAL);
|
|
669
|
+
await this.blockchainService.cancelAssetUpdate(tokenId, blockchain);
|
|
670
|
+
|
|
671
|
+
return {
|
|
672
|
+
UAL,
|
|
673
|
+
operation: getOperationStatusObject({ status: 'COMPLETED' }, null),
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Transfer an asset to a new owner on a specified blockchain.
|
|
679
|
+
* @async
|
|
680
|
+
* @param {string} UAL - The Universal Asset Locator of the asset to be transferred.
|
|
681
|
+
* @param {string} newOwner - The address of the new owner.
|
|
682
|
+
* @param {Object} [options={}] - Additional options for asset transfer.
|
|
683
|
+
* @returns {Object} Object containing UAL, owner's address and operation status.
|
|
684
|
+
*/
|
|
685
|
+
async transfer(UAL, newOwner, options = {}) {
|
|
686
|
+
const blockchain = this.inputService.getBlockchain(options);
|
|
687
|
+
|
|
688
|
+
this.validationService.validateAssetTransfer(UAL, newOwner, blockchain);
|
|
689
|
+
|
|
254
690
|
const { tokenId } = resolveUAL(UAL);
|
|
255
|
-
await this.blockchainService.transferAsset(tokenId,
|
|
256
|
-
const owner = await this.blockchainService.getAssetOwner(tokenId,
|
|
691
|
+
await this.blockchainService.transferAsset(tokenId, newOwner, blockchain);
|
|
692
|
+
const owner = await this.blockchainService.getAssetOwner(tokenId, blockchain);
|
|
257
693
|
return {
|
|
258
694
|
UAL,
|
|
259
695
|
owner,
|
|
@@ -261,16 +697,262 @@ class AssetOperationsManager {
|
|
|
261
697
|
};
|
|
262
698
|
}
|
|
263
699
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
700
|
+
/**
|
|
701
|
+
* Retrieves the owner of a specified asset for a given blockchain.
|
|
702
|
+
* @async
|
|
703
|
+
* @param {string} UAL - The Universal Asset Locator of the asset.
|
|
704
|
+
* @param {Object} [options={}] - Optional parameters for blockchain service.
|
|
705
|
+
* @returns {Object} An object containing the UAL, owner and operation status.
|
|
706
|
+
*/
|
|
707
|
+
async getOwner(UAL, options = {}) {
|
|
708
|
+
const blockchain = this.inputService.getBlockchain(options);
|
|
709
|
+
|
|
710
|
+
this.validationService.validateAssetGetOwner(UAL, blockchain);
|
|
711
|
+
|
|
267
712
|
const { tokenId } = resolveUAL(UAL);
|
|
268
|
-
const owner = await this.blockchainService.getAssetOwner(tokenId,
|
|
713
|
+
const owner = await this.blockchainService.getAssetOwner(tokenId, blockchain);
|
|
269
714
|
return {
|
|
270
715
|
UAL,
|
|
271
716
|
owner,
|
|
272
717
|
operation: getOperationStatusObject({ data: {}, status: 'COMPLETED' }, null),
|
|
273
718
|
};
|
|
274
719
|
}
|
|
720
|
+
|
|
721
|
+
async burn(UAL, options = {}) {
|
|
722
|
+
const blockchain = this.inputService.getBlockchain(options);
|
|
723
|
+
|
|
724
|
+
this.validationService.validateAssetBurn(UAL, blockchain);
|
|
725
|
+
|
|
726
|
+
const { tokenId } = resolveUAL(UAL);
|
|
727
|
+
await this.blockchainService.burnAsset(tokenId, blockchain);
|
|
728
|
+
|
|
729
|
+
return {
|
|
730
|
+
UAL,
|
|
731
|
+
operation: getOperationStatusObject({ status: 'COMPLETED' }, null),
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
async extendStoringPeriod(UAL, epochsNumber, options = {}) {
|
|
736
|
+
const blockchain = this.inputService.getBlockchain(options);
|
|
737
|
+
const tokenAmount = this.inputService.getTokenAmount(options);
|
|
738
|
+
|
|
739
|
+
const { tokenId } = resolveUAL(UAL);
|
|
740
|
+
|
|
741
|
+
let tokenAmountInWei;
|
|
742
|
+
|
|
743
|
+
if (tokenAmount != null) {
|
|
744
|
+
tokenAmountInWei = tokenAmount;
|
|
745
|
+
} else {
|
|
746
|
+
const endpoint = this.inputService.getEndpoint(options);
|
|
747
|
+
const port = this.inputService.getPort(options);
|
|
748
|
+
const authToken = this.inputService.getAuthToken(options);
|
|
749
|
+
const hashFunctionId = this.inputService.getHashFunctionId(options);
|
|
750
|
+
|
|
751
|
+
const latestFinalizedState = await this.blockchainService.getLatestAssertionId(
|
|
752
|
+
tokenId,
|
|
753
|
+
blockchain,
|
|
754
|
+
);
|
|
755
|
+
|
|
756
|
+
const latestFinalizedStateSize = await this.blockchainService.getAssertionSize(
|
|
757
|
+
latestFinalizedState,
|
|
758
|
+
blockchain,
|
|
759
|
+
);
|
|
760
|
+
|
|
761
|
+
tokenAmountInWei = await this._getUpdateBidSuggestion(
|
|
762
|
+
UAL,
|
|
763
|
+
blockchain,
|
|
764
|
+
endpoint,
|
|
765
|
+
port,
|
|
766
|
+
authToken,
|
|
767
|
+
latestFinalizedState,
|
|
768
|
+
latestFinalizedStateSize,
|
|
769
|
+
hashFunctionId,
|
|
770
|
+
);
|
|
771
|
+
|
|
772
|
+
if (tokenAmountInWei < 0) {
|
|
773
|
+
tokenAmountInWei = 0;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
this.validationService.validateExtendAssetStoringPeriod(
|
|
778
|
+
UAL,
|
|
779
|
+
epochsNumber,
|
|
780
|
+
tokenAmountInWei,
|
|
781
|
+
blockchain,
|
|
782
|
+
);
|
|
783
|
+
|
|
784
|
+
await this.blockchainService.extendAssetStoringPeriod(
|
|
785
|
+
tokenId,
|
|
786
|
+
epochsNumber,
|
|
787
|
+
tokenAmountInWei,
|
|
788
|
+
blockchain,
|
|
789
|
+
);
|
|
790
|
+
|
|
791
|
+
return {
|
|
792
|
+
UAL,
|
|
793
|
+
operation: getOperationStatusObject({ status: 'COMPLETED' }, null),
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
async addTokens(UAL, options = {}) {
|
|
798
|
+
const blockchain = this.inputService.getBlockchain(options);
|
|
799
|
+
const tokenAmount = this.inputService.getTokenAmount(options);
|
|
800
|
+
|
|
801
|
+
const { tokenId } = resolveUAL(UAL);
|
|
802
|
+
|
|
803
|
+
let tokenAmountInWei;
|
|
804
|
+
|
|
805
|
+
if (tokenAmount != null) {
|
|
806
|
+
tokenAmountInWei = tokenAmount;
|
|
807
|
+
} else {
|
|
808
|
+
const endpoint = this.inputService.getEndpoint(options);
|
|
809
|
+
const port = this.inputService.getPort(options);
|
|
810
|
+
const authToken = this.inputService.getAuthToken(options);
|
|
811
|
+
const hashFunctionId = this.inputService.getHashFunctionId(options);
|
|
812
|
+
|
|
813
|
+
const latestFinalizedState = await this.blockchainService.getLatestAssertionId(
|
|
814
|
+
tokenId,
|
|
815
|
+
blockchain,
|
|
816
|
+
);
|
|
817
|
+
|
|
818
|
+
const latestFinalizedStateSize = await this.blockchainService.getAssertionSize(
|
|
819
|
+
latestFinalizedState,
|
|
820
|
+
blockchain,
|
|
821
|
+
);
|
|
822
|
+
|
|
823
|
+
tokenAmountInWei = await this._getUpdateBidSuggestion(
|
|
824
|
+
UAL,
|
|
825
|
+
blockchain,
|
|
826
|
+
endpoint,
|
|
827
|
+
port,
|
|
828
|
+
authToken,
|
|
829
|
+
latestFinalizedState,
|
|
830
|
+
latestFinalizedStateSize,
|
|
831
|
+
hashFunctionId,
|
|
832
|
+
);
|
|
833
|
+
|
|
834
|
+
if (tokenAmountInWei <= 0) {
|
|
835
|
+
throw Error(
|
|
836
|
+
`Token amount is bigger than default suggested amount, please specify exact tokenAmount if you still want to add more tokens!`,
|
|
837
|
+
);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
this.validationService.validateAddTokens(UAL, tokenAmountInWei, blockchain);
|
|
842
|
+
|
|
843
|
+
await this.blockchainService.addTokens(tokenId, tokenAmountInWei, blockchain);
|
|
844
|
+
|
|
845
|
+
return {
|
|
846
|
+
UAL,
|
|
847
|
+
operation: getOperationStatusObject({ status: 'COMPLETED' }, null),
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
async addUpdateTokens(UAL, options = {}) {
|
|
852
|
+
const blockchain = this.inputService.getBlockchain(options);
|
|
853
|
+
const tokenAmount = this.inputService.getTokenAmount(options);
|
|
854
|
+
|
|
855
|
+
const { tokenId } = resolveUAL(UAL);
|
|
856
|
+
|
|
857
|
+
let tokenAmountInWei;
|
|
858
|
+
|
|
859
|
+
if (tokenAmount != null) {
|
|
860
|
+
tokenAmountInWei = tokenAmount;
|
|
861
|
+
} else {
|
|
862
|
+
const endpoint = this.inputService.getEndpoint(options);
|
|
863
|
+
const port = this.inputService.getPort(options);
|
|
864
|
+
const authToken = this.inputService.getAuthToken(options);
|
|
865
|
+
const hashFunctionId = this.inputService.getHashFunctionId(options);
|
|
866
|
+
|
|
867
|
+
const unfinalizedState = await this.blockchainService.getUnfinalizedState(
|
|
868
|
+
tokenId,
|
|
869
|
+
blockchain,
|
|
870
|
+
);
|
|
871
|
+
|
|
872
|
+
const unfinalizedStateSize = await this.blockchainService.getAssertionSize(
|
|
873
|
+
unfinalizedState,
|
|
874
|
+
blockchain,
|
|
875
|
+
);
|
|
876
|
+
|
|
877
|
+
tokenAmountInWei = await this._getUpdateBidSuggestion(
|
|
878
|
+
UAL,
|
|
879
|
+
blockchain,
|
|
880
|
+
endpoint,
|
|
881
|
+
port,
|
|
882
|
+
authToken,
|
|
883
|
+
unfinalizedState,
|
|
884
|
+
unfinalizedStateSize,
|
|
885
|
+
hashFunctionId,
|
|
886
|
+
);
|
|
887
|
+
if (tokenAmountInWei <= 0) {
|
|
888
|
+
throw Error(
|
|
889
|
+
`Token amount is bigger than default suggested amount, please specify exact tokenAmount if you still want to add more tokens!`,
|
|
890
|
+
);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
this.validationService.validateAddTokens(UAL, tokenAmountInWei, blockchain);
|
|
895
|
+
|
|
896
|
+
await this.blockchainService.addUpdateTokens(tokenId, tokenAmountInWei, blockchain);
|
|
897
|
+
|
|
898
|
+
return {
|
|
899
|
+
UAL,
|
|
900
|
+
operation: getOperationStatusObject({ status: 'COMPLETED' }, null),
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
async _getUpdateBidSuggestion(
|
|
905
|
+
UAL,
|
|
906
|
+
blockchain,
|
|
907
|
+
endpoint,
|
|
908
|
+
port,
|
|
909
|
+
authToken,
|
|
910
|
+
assertionId,
|
|
911
|
+
size,
|
|
912
|
+
hashFunctionId,
|
|
913
|
+
) {
|
|
914
|
+
const { contract, tokenId } = resolveUAL(UAL);
|
|
915
|
+
const firstAssertionId = await this.blockchainService.getAssertionIdByIndex(
|
|
916
|
+
tokenId,
|
|
917
|
+
0,
|
|
918
|
+
blockchain,
|
|
919
|
+
);
|
|
920
|
+
|
|
921
|
+
const keyword = ethers.solidityPacked(['address', 'bytes32'], [contract, firstAssertionId]);
|
|
922
|
+
|
|
923
|
+
const agreementId = ethers.sha256(
|
|
924
|
+
ethers.solidityPacked(['address', 'uint256', 'bytes'], [contract, tokenId, keyword]),
|
|
925
|
+
);
|
|
926
|
+
const agreementData = await this.blockchainService.getAgreementData(
|
|
927
|
+
agreementId,
|
|
928
|
+
blockchain,
|
|
929
|
+
);
|
|
930
|
+
|
|
931
|
+
const now = await this.blockchainService.getBlockchainTimestamp(blockchain);
|
|
932
|
+
const currentEpoch = Math.floor(
|
|
933
|
+
(now - agreementData.startTime) / agreementData.epochLength,
|
|
934
|
+
);
|
|
935
|
+
|
|
936
|
+
const epochsLeft = agreementData.epochsNumber - currentEpoch;
|
|
937
|
+
|
|
938
|
+
const bidSuggestion = await this.nodeApiService.getBidSuggestion(
|
|
939
|
+
endpoint,
|
|
940
|
+
port,
|
|
941
|
+
authToken,
|
|
942
|
+
blockchain.name.startsWith('otp') ? 'otp' : blockchain.name,
|
|
943
|
+
epochsLeft,
|
|
944
|
+
size,
|
|
945
|
+
contract,
|
|
946
|
+
assertionId,
|
|
947
|
+
hashFunctionId,
|
|
948
|
+
);
|
|
949
|
+
|
|
950
|
+
const tokenAmountInWei =
|
|
951
|
+
BigInt(bidSuggestion) -
|
|
952
|
+
(BigInt(agreementData.tokenAmount) + BigInt(agreementData.updateTokenAmount ?? 0));
|
|
953
|
+
|
|
954
|
+
return tokenAmountInWei > 0 ? tokenAmountInWei : 0;
|
|
955
|
+
}
|
|
275
956
|
}
|
|
957
|
+
|
|
276
958
|
module.exports = AssetOperationsManager;
|