@cheqd/did-provider-cheqd 4.4.1 → 4.5.0-develop.1
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/build/esm/did-manager/cheqd-did-provider.d.ts.map +1 -1
- package/build/esm/did-manager/cheqd-did-provider.js +2 -1
- package/build/esm/did-manager/cheqd-did-provider.js.map +1 -1
- package/build/esm/utils/helpers.d.ts +1 -1
- package/build/esm/utils/helpers.d.ts.map +1 -1
- package/build/tsconfig.esm.tsbuildinfo +1 -1
- package/build/tsconfig.types.tsbuildinfo +1 -1
- package/build/types/did-manager/cheqd-did-provider.d.ts.map +1 -1
- package/build/types/utils/helpers.d.ts +1 -1
- package/build/types/utils/helpers.d.ts.map +1 -1
- package/package.json +3 -9
- package/src/did-manager/cheqd-did-provider.ts +2 -0
- package/src/utils/helpers.ts +1 -1
- package/tsconfig.json +1 -1
- package/build/cjs/agent/ICheqd.d.ts +0 -769
- package/build/cjs/agent/ICheqd.d.ts.map +0 -1
- package/build/cjs/agent/ICheqd.js +0 -4399
- package/build/cjs/agent/ICheqd.js.map +0 -1
- package/build/cjs/agent/index.d.ts +0 -2
- package/build/cjs/agent/index.d.ts.map +0 -1
- package/build/cjs/agent/index.js +0 -18
- package/build/cjs/agent/index.js.map +0 -1
- package/build/cjs/did-manager/cheqd-did-provider.d.ts +0 -233
- package/build/cjs/did-manager/cheqd-did-provider.d.ts.map +0 -1
- package/build/cjs/did-manager/cheqd-did-provider.js +0 -750
- package/build/cjs/did-manager/cheqd-did-provider.js.map +0 -1
- package/build/cjs/did-manager/cheqd-did-resolver.d.ts +0 -26
- package/build/cjs/did-manager/cheqd-did-resolver.d.ts.map +0 -1
- package/build/cjs/did-manager/cheqd-did-resolver.js +0 -52
- package/build/cjs/did-manager/cheqd-did-resolver.js.map +0 -1
- package/build/cjs/did-manager/index.d.ts +0 -4
- package/build/cjs/did-manager/index.d.ts.map +0 -1
- package/build/cjs/did-manager/index.js +0 -20
- package/build/cjs/did-manager/index.js.map +0 -1
- package/build/cjs/did-manager/resolver.d.ts +0 -47
- package/build/cjs/did-manager/resolver.d.ts.map +0 -1
- package/build/cjs/did-manager/resolver.js +0 -75
- package/build/cjs/did-manager/resolver.js.map +0 -1
- package/build/cjs/dkg-threshold/index.d.ts +0 -2
- package/build/cjs/dkg-threshold/index.d.ts.map +0 -1
- package/build/cjs/dkg-threshold/index.js +0 -18
- package/build/cjs/dkg-threshold/index.js.map +0 -1
- package/build/cjs/dkg-threshold/lit-protocol/v2.d.ts +0 -95
- package/build/cjs/dkg-threshold/lit-protocol/v2.d.ts.map +0 -1
- package/build/cjs/dkg-threshold/lit-protocol/v2.js +0 -193
- package/build/cjs/dkg-threshold/lit-protocol/v2.js.map +0 -1
- package/build/cjs/dkg-threshold/lit-protocol/v3.d.ts +0 -95
- package/build/cjs/dkg-threshold/lit-protocol/v3.d.ts.map +0 -1
- package/build/cjs/dkg-threshold/lit-protocol/v3.js +0 -232
- package/build/cjs/dkg-threshold/lit-protocol/v3.js.map +0 -1
- package/build/cjs/dkg-threshold/lit-protocol/v6.d.ts +0 -131
- package/build/cjs/dkg-threshold/lit-protocol/v6.d.ts.map +0 -1
- package/build/cjs/dkg-threshold/lit-protocol/v6.js +0 -345
- package/build/cjs/dkg-threshold/lit-protocol/v6.js.map +0 -1
- package/build/cjs/index.d.ts +0 -9
- package/build/cjs/index.d.ts.map +0 -1
- package/build/cjs/index.js +0 -25
- package/build/cjs/index.js.map +0 -1
- package/build/cjs/utils/constants.d.ts +0 -2
- package/build/cjs/utils/constants.d.ts.map +0 -1
- package/build/cjs/utils/constants.js +0 -5
- package/build/cjs/utils/constants.js.map +0 -1
- package/build/cjs/utils/env.d.ts +0 -7
- package/build/cjs/utils/env.d.ts.map +0 -1
- package/build/cjs/utils/env.js +0 -19
- package/build/cjs/utils/env.js.map +0 -1
- package/build/cjs/utils/helpers.d.ts +0 -18
- package/build/cjs/utils/helpers.d.ts.map +0 -1
- package/build/cjs/utils/helpers.js +0 -112
- package/build/cjs/utils/helpers.js.map +0 -1
- package/build/cjs/utils/index.d.ts +0 -3
- package/build/cjs/utils/index.d.ts.map +0 -1
- package/build/cjs/utils/index.js +0 -19
- package/build/cjs/utils/index.js.map +0 -1
- package/build/tsconfig.cjs.tsbuildinfo +0 -1
|
@@ -1,4399 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Cheqd = exports.CheqdDidMethod = exports.DidPrefix = exports.DelegateCapacityCreditMethodName = exports.MintCapacityCreditMethodName = exports.ObservePaymentConditionMethodName = exports.TransactSendTokensMethodName = exports.UnsuspendCredentialsMethodName = exports.UnsuspendCredentialMethodName = exports.SuspendCredentialsMethodName = exports.SuspendCredentialMethodName = exports.RevokeCredentialsMethodName = exports.RevokeCredentialMethodName = exports.CheckCredentialStatusMethodName = exports.VerifyPresentationMethodName = exports.VerifyCredentialMethodName = exports.IssueSuspendableCredentialWithStatusList2021MethodName = exports.IssueRevocableCredentialWithStatusList2021MethodName = exports.GenerateStatusList2021MethodName = exports.GenerateVersionIdMethodName = exports.GenerateKeyPairMethodName = exports.GenerateDidDocWithLinkedResourceMethodName = exports.GenerateDidDocMethodName = exports.BroadcastStatusList2021MethodName = exports.CreateStatusList2021MethodName = exports.CreateResourceMethodName = exports.DeactivateIdentifierMethodName = exports.UpdateIdentifierMethodName = exports.CreateIdentifierMethodName = exports.RemoteListPattern = exports.AccessControlConditionReturnValueComparators = exports.AccessControlConditionTypes = void 0;
|
|
7
|
-
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars, @typescript-eslint/no-non-null-assertion */
|
|
8
|
-
// any is used for extensibility
|
|
9
|
-
// unused vars are kept by convention
|
|
10
|
-
// non-null assertion is used when we know better than the compiler that the value is not null or undefined
|
|
11
|
-
const sdk_1 = require("@cheqd/sdk");
|
|
12
|
-
const cheqd_did_provider_js_1 = require("../did-manager/cheqd-did-provider.js");
|
|
13
|
-
const uint8arrays_1 = require("uint8arrays");
|
|
14
|
-
const did_jwt_1 = require("did-jwt");
|
|
15
|
-
const vc_status_list_1 = require("@digitalbazaar/vc-status-list");
|
|
16
|
-
const uuid_1 = require("uuid");
|
|
17
|
-
const fs_1 = __importDefault(require("fs"));
|
|
18
|
-
const debug_1 = __importDefault(require("debug"));
|
|
19
|
-
const v6_js_1 = require("../dkg-threshold/lit-protocol/v6.js");
|
|
20
|
-
const helpers_js_1 = require("../utils/helpers.js");
|
|
21
|
-
const cheqd_did_resolver_js_1 = require("../did-manager/cheqd-did-resolver.js");
|
|
22
|
-
const v2_js_1 = require("../dkg-threshold/lit-protocol/v2.js");
|
|
23
|
-
const debug = (0, debug_1.default)('veramo:did-provider-cheqd');
|
|
24
|
-
exports.AccessControlConditionTypes = {
|
|
25
|
-
timelockPayment: 'timelockPayment',
|
|
26
|
-
memoNonce: 'memoNonce',
|
|
27
|
-
balance: 'balance',
|
|
28
|
-
};
|
|
29
|
-
exports.AccessControlConditionReturnValueComparators = {
|
|
30
|
-
lessThan: '<',
|
|
31
|
-
greaterThan: '>',
|
|
32
|
-
equalTo: '=',
|
|
33
|
-
lessThanOrEqualTo: '<=',
|
|
34
|
-
greaterThanOrEqualTo: '>=',
|
|
35
|
-
};
|
|
36
|
-
exports.RemoteListPattern = /^(https:\/\/)?[a-z0-9_-]+(\.[a-z0-9_-]+)*\.[a-z]{2,}\/1\.0\/identifiers\/did:cheqd:[a-z]+:[a-zA-Z0-9-]+\?((resourceName=[^&]*)&(resourceType=[^&]*)|((resourceType=[^&]*)&(resourceName=[^&]*)))$/;
|
|
37
|
-
exports.CreateIdentifierMethodName = 'cheqdCreateIdentifier';
|
|
38
|
-
exports.UpdateIdentifierMethodName = 'cheqdUpdateIdentifier';
|
|
39
|
-
exports.DeactivateIdentifierMethodName = 'cheqdDeactivateIdentifier';
|
|
40
|
-
exports.CreateResourceMethodName = 'cheqdCreateLinkedResource';
|
|
41
|
-
exports.CreateStatusList2021MethodName = 'cheqdCreateStatusList2021';
|
|
42
|
-
exports.BroadcastStatusList2021MethodName = 'cheqdBroadcastStatusList2021';
|
|
43
|
-
exports.GenerateDidDocMethodName = 'cheqdGenerateDidDoc';
|
|
44
|
-
exports.GenerateDidDocWithLinkedResourceMethodName = 'cheqdGenerateDidDocWithLinkedResource';
|
|
45
|
-
exports.GenerateKeyPairMethodName = 'cheqdGenerateIdentityKeys';
|
|
46
|
-
exports.GenerateVersionIdMethodName = 'cheqdGenerateVersionId';
|
|
47
|
-
exports.GenerateStatusList2021MethodName = 'cheqdGenerateStatusList2021';
|
|
48
|
-
exports.IssueRevocableCredentialWithStatusList2021MethodName = 'cheqdIssueRevocableCredentialWithStatusList2021';
|
|
49
|
-
exports.IssueSuspendableCredentialWithStatusList2021MethodName = 'cheqdIssueSuspendableCredentialWithStatusList2021';
|
|
50
|
-
exports.VerifyCredentialMethodName = 'cheqdVerifyCredential';
|
|
51
|
-
exports.VerifyPresentationMethodName = 'cheqdVerifyPresentation';
|
|
52
|
-
exports.CheckCredentialStatusMethodName = 'cheqdCheckCredentialStatus';
|
|
53
|
-
exports.RevokeCredentialMethodName = 'cheqdRevokeCredential';
|
|
54
|
-
exports.RevokeCredentialsMethodName = 'cheqdRevokeCredentials';
|
|
55
|
-
exports.SuspendCredentialMethodName = 'cheqdSuspendCredential';
|
|
56
|
-
exports.SuspendCredentialsMethodName = 'cheqdSuspendCredentials';
|
|
57
|
-
exports.UnsuspendCredentialMethodName = 'cheqdUnsuspendCredential';
|
|
58
|
-
exports.UnsuspendCredentialsMethodName = 'cheqdUnsuspendCredentials';
|
|
59
|
-
exports.TransactSendTokensMethodName = 'cheqdTransactSendTokens';
|
|
60
|
-
exports.ObservePaymentConditionMethodName = 'cheqdObservePaymentCondition';
|
|
61
|
-
exports.MintCapacityCreditMethodName = 'cheqdMintCapacityCredit';
|
|
62
|
-
exports.DelegateCapacityCreditMethodName = 'cheqdDelegateCapacityCredit';
|
|
63
|
-
exports.DidPrefix = 'did';
|
|
64
|
-
exports.CheqdDidMethod = 'cheqd';
|
|
65
|
-
class Cheqd {
|
|
66
|
-
methods;
|
|
67
|
-
schema = {
|
|
68
|
-
components: {
|
|
69
|
-
schemas: {},
|
|
70
|
-
methods: {
|
|
71
|
-
cheqdCreateIdentifier: {
|
|
72
|
-
description: 'Create a new identifier',
|
|
73
|
-
arguments: {
|
|
74
|
-
type: 'object',
|
|
75
|
-
properties: {
|
|
76
|
-
args: {
|
|
77
|
-
type: 'object',
|
|
78
|
-
description: 'A cheqdCreateIdentifierArgs object as any for extensibility',
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
required: ['args'],
|
|
82
|
-
},
|
|
83
|
-
returnType: {
|
|
84
|
-
type: 'object',
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
cheqdUpdateIdentifier: {
|
|
88
|
-
description: 'Update an identifier',
|
|
89
|
-
arguments: {
|
|
90
|
-
type: 'object',
|
|
91
|
-
properties: {
|
|
92
|
-
args: {
|
|
93
|
-
type: 'object',
|
|
94
|
-
description: 'A cheqdUpdateIdentifierArgs object as any for extensibility',
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
required: ['args'],
|
|
98
|
-
},
|
|
99
|
-
returnType: {
|
|
100
|
-
type: 'object',
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
cheqdDeactivateIdentifier: {
|
|
104
|
-
description: 'Deactivate an identifier',
|
|
105
|
-
arguments: {
|
|
106
|
-
type: 'object',
|
|
107
|
-
properties: {
|
|
108
|
-
args: {
|
|
109
|
-
type: 'object',
|
|
110
|
-
description: 'A cheqdDeactivateIdentifierArgs object as any for extensibility',
|
|
111
|
-
},
|
|
112
|
-
},
|
|
113
|
-
required: ['args'],
|
|
114
|
-
},
|
|
115
|
-
returnType: {
|
|
116
|
-
type: 'object',
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
cheqdCreateLinkedResource: {
|
|
120
|
-
description: 'Create a new resource',
|
|
121
|
-
arguments: {
|
|
122
|
-
type: 'object',
|
|
123
|
-
properties: {
|
|
124
|
-
args: {
|
|
125
|
-
type: 'object',
|
|
126
|
-
description: 'A cheqdCreateLinkedResource object as any for extensibility',
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
|
-
required: ['args'],
|
|
130
|
-
},
|
|
131
|
-
returnType: {
|
|
132
|
-
type: 'boolean',
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
cheqdCreateStatusList2021: {
|
|
136
|
-
description: 'Create a new Status List 2021',
|
|
137
|
-
arguments: {
|
|
138
|
-
type: 'object',
|
|
139
|
-
properties: {
|
|
140
|
-
args: {
|
|
141
|
-
type: 'object',
|
|
142
|
-
description: 'A cheqdCreateStatusList2021Args object as any for extensibility',
|
|
143
|
-
},
|
|
144
|
-
},
|
|
145
|
-
required: ['args'],
|
|
146
|
-
},
|
|
147
|
-
returnType: {
|
|
148
|
-
type: 'object',
|
|
149
|
-
},
|
|
150
|
-
},
|
|
151
|
-
cheqdBroadcastStatusList2021: {
|
|
152
|
-
description: 'Broadcast a Status List 2021 to cheqd ledger',
|
|
153
|
-
arguments: {
|
|
154
|
-
type: 'object',
|
|
155
|
-
properties: {
|
|
156
|
-
args: {
|
|
157
|
-
type: 'object',
|
|
158
|
-
description: 'A cheqdBroadcastStatusList2021Args object as any for extensibility',
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
required: ['args'],
|
|
162
|
-
},
|
|
163
|
-
returnType: {
|
|
164
|
-
type: 'object',
|
|
165
|
-
},
|
|
166
|
-
},
|
|
167
|
-
cheqdGenerateDidDoc: {
|
|
168
|
-
description: 'Generate a new DID document to use with `createIdentifier`',
|
|
169
|
-
arguments: {
|
|
170
|
-
type: 'object',
|
|
171
|
-
properties: {
|
|
172
|
-
args: {
|
|
173
|
-
type: 'object',
|
|
174
|
-
description: 'A cheqdGenerateDidDocArgs object as any for extensibility',
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
required: ['args'],
|
|
178
|
-
},
|
|
179
|
-
returnType: {
|
|
180
|
-
type: 'object',
|
|
181
|
-
},
|
|
182
|
-
},
|
|
183
|
-
cheqdGenerateDidDocWithLinkedResource: {
|
|
184
|
-
description: 'Generate a new DID document to use with `createIdentifier` and / or `createResource`',
|
|
185
|
-
arguments: {
|
|
186
|
-
type: 'object',
|
|
187
|
-
properties: {
|
|
188
|
-
args: {
|
|
189
|
-
type: 'object',
|
|
190
|
-
description: 'A cheqdGenerateDidDocWithLinkedResourceArgs object as any for extensibility',
|
|
191
|
-
},
|
|
192
|
-
},
|
|
193
|
-
required: ['args'],
|
|
194
|
-
},
|
|
195
|
-
returnType: {
|
|
196
|
-
type: 'object',
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
cheqdGenerateIdentityKeys: {
|
|
200
|
-
description: 'Generate a new key pair in hex to use with `createIdentifier`',
|
|
201
|
-
arguments: {
|
|
202
|
-
type: 'object',
|
|
203
|
-
properties: {
|
|
204
|
-
args: {
|
|
205
|
-
type: 'object',
|
|
206
|
-
description: 'A cheqdGenerateIdentityKeysArgs object as any for extensibility',
|
|
207
|
-
},
|
|
208
|
-
},
|
|
209
|
-
},
|
|
210
|
-
returnType: {
|
|
211
|
-
type: 'object',
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
cheqdGenerateVersionId: {
|
|
215
|
-
description: 'Generate a random uuid',
|
|
216
|
-
arguments: {
|
|
217
|
-
type: 'object',
|
|
218
|
-
properties: {
|
|
219
|
-
args: {
|
|
220
|
-
type: 'object',
|
|
221
|
-
description: 'A cheqdGenerateVersionIdArgs object as any for extensibility',
|
|
222
|
-
},
|
|
223
|
-
},
|
|
224
|
-
},
|
|
225
|
-
returnType: {
|
|
226
|
-
type: 'object',
|
|
227
|
-
},
|
|
228
|
-
},
|
|
229
|
-
cheqdGenerateStatusList2021: {
|
|
230
|
-
description: 'Generate a new Status List 2021',
|
|
231
|
-
arguments: {
|
|
232
|
-
type: 'object',
|
|
233
|
-
properties: {
|
|
234
|
-
args: {
|
|
235
|
-
type: 'object',
|
|
236
|
-
description: 'A cheqdGenerateStatusList2021Args object as any for extensibility',
|
|
237
|
-
},
|
|
238
|
-
},
|
|
239
|
-
},
|
|
240
|
-
returnType: {
|
|
241
|
-
type: 'string',
|
|
242
|
-
},
|
|
243
|
-
},
|
|
244
|
-
cheqdIssueRevocableCredentialWithStatusList2021: {
|
|
245
|
-
description: 'Issue a revocable credential with a Status List 2021 as credential status registry',
|
|
246
|
-
arguments: {
|
|
247
|
-
type: 'object',
|
|
248
|
-
properties: {
|
|
249
|
-
args: {
|
|
250
|
-
type: 'object',
|
|
251
|
-
description: 'A cheqdIssueCredentialWithStatusList2021Args object as any for extensibility',
|
|
252
|
-
},
|
|
253
|
-
},
|
|
254
|
-
required: ['args'],
|
|
255
|
-
},
|
|
256
|
-
returnType: {
|
|
257
|
-
type: 'object',
|
|
258
|
-
},
|
|
259
|
-
},
|
|
260
|
-
cheqdIssueSuspendableCredentialWithStatusList2021: {
|
|
261
|
-
description: 'Issue a suspendable credential with a Status List 2021 as credential status registry',
|
|
262
|
-
arguments: {
|
|
263
|
-
type: 'object',
|
|
264
|
-
properties: {
|
|
265
|
-
args: {
|
|
266
|
-
type: 'object',
|
|
267
|
-
description: 'A cheqdIssueCredentialWithStatusList2021Args object as any for extensibility',
|
|
268
|
-
},
|
|
269
|
-
},
|
|
270
|
-
required: ['args'],
|
|
271
|
-
},
|
|
272
|
-
returnType: {
|
|
273
|
-
type: 'object',
|
|
274
|
-
},
|
|
275
|
-
},
|
|
276
|
-
cheqdVerifyCredential: {
|
|
277
|
-
description: 'Verify a credential, enhanced by revocation / suspension check with a Status List 2021 as credential status registry',
|
|
278
|
-
arguments: {
|
|
279
|
-
type: 'object',
|
|
280
|
-
properties: {
|
|
281
|
-
args: {
|
|
282
|
-
type: 'object',
|
|
283
|
-
description: 'A cheqdVerifyCredentialWithStatusList2021Args object as any for extensibility',
|
|
284
|
-
},
|
|
285
|
-
},
|
|
286
|
-
required: ['args'],
|
|
287
|
-
},
|
|
288
|
-
returnType: {
|
|
289
|
-
type: 'object',
|
|
290
|
-
},
|
|
291
|
-
},
|
|
292
|
-
cheqdVerifyPresentation: {
|
|
293
|
-
description: 'Verify a presentation, enhanced by revocation / suspension check with a Status List 2021 as credential status registry',
|
|
294
|
-
arguments: {
|
|
295
|
-
type: 'object',
|
|
296
|
-
properties: {
|
|
297
|
-
args: {
|
|
298
|
-
type: 'object',
|
|
299
|
-
description: 'A cheqdVerifyPresentationWithStatusList2021Args object as any for extensibility',
|
|
300
|
-
},
|
|
301
|
-
},
|
|
302
|
-
required: ['args'],
|
|
303
|
-
},
|
|
304
|
-
returnType: {
|
|
305
|
-
type: 'object',
|
|
306
|
-
},
|
|
307
|
-
},
|
|
308
|
-
cheqdCheckCredentialStatus: {
|
|
309
|
-
description: 'Check the revocation / suspension status of a credential with a Status List 2021 as credential status registry',
|
|
310
|
-
arguments: {
|
|
311
|
-
type: 'object',
|
|
312
|
-
properties: {
|
|
313
|
-
args: {
|
|
314
|
-
type: 'object',
|
|
315
|
-
description: 'A cheqdCheckCredentialStatusWithStatusList2021Args object as any for extensibility',
|
|
316
|
-
},
|
|
317
|
-
},
|
|
318
|
-
required: ['args'],
|
|
319
|
-
},
|
|
320
|
-
returnType: {
|
|
321
|
-
type: 'object',
|
|
322
|
-
},
|
|
323
|
-
},
|
|
324
|
-
cheqdRevokeCredential: {
|
|
325
|
-
description: 'Revoke a credential against a Status List 2021 as credential status registry',
|
|
326
|
-
arguments: {
|
|
327
|
-
type: 'object',
|
|
328
|
-
properties: {
|
|
329
|
-
args: {
|
|
330
|
-
type: 'object',
|
|
331
|
-
description: 'A cheqdRevokeCredentialWithStatusList2021Args object as any for extensibility',
|
|
332
|
-
},
|
|
333
|
-
},
|
|
334
|
-
required: ['args'],
|
|
335
|
-
},
|
|
336
|
-
returnType: {
|
|
337
|
-
type: 'object',
|
|
338
|
-
},
|
|
339
|
-
},
|
|
340
|
-
cheqdRevokeCredentials: {
|
|
341
|
-
description: 'Revoke multiple credentials against a Status List 2021 as credential status registry',
|
|
342
|
-
arguments: {
|
|
343
|
-
type: 'object',
|
|
344
|
-
properties: {
|
|
345
|
-
args: {
|
|
346
|
-
type: 'object',
|
|
347
|
-
description: 'A cheqdRevokeBulkCredentialsWithStatusList2021Args object as any for extensibility',
|
|
348
|
-
},
|
|
349
|
-
},
|
|
350
|
-
required: ['args'],
|
|
351
|
-
},
|
|
352
|
-
returnType: {
|
|
353
|
-
type: 'array',
|
|
354
|
-
},
|
|
355
|
-
},
|
|
356
|
-
cheqdSuspendCredential: {
|
|
357
|
-
description: 'Suspend a credential against a Status List 2021 as credential status registry',
|
|
358
|
-
arguments: {
|
|
359
|
-
type: 'object',
|
|
360
|
-
properties: {
|
|
361
|
-
args: {
|
|
362
|
-
type: 'object',
|
|
363
|
-
description: 'A cheqdSuspendCredentialWithStatusList2021Args object as any for extensibility',
|
|
364
|
-
},
|
|
365
|
-
},
|
|
366
|
-
required: ['args'],
|
|
367
|
-
},
|
|
368
|
-
returnType: {
|
|
369
|
-
type: 'object',
|
|
370
|
-
},
|
|
371
|
-
},
|
|
372
|
-
cheqdSuspendCredentials: {
|
|
373
|
-
description: 'Suspend multiple credentials against a Status List 2021 as credential status registry',
|
|
374
|
-
arguments: {
|
|
375
|
-
type: 'object',
|
|
376
|
-
properties: {
|
|
377
|
-
args: {
|
|
378
|
-
type: 'object',
|
|
379
|
-
description: 'A cheqdSuspendBulkCredentialsWithStatusList2021Args object as any for extensibility',
|
|
380
|
-
},
|
|
381
|
-
},
|
|
382
|
-
required: ['args'],
|
|
383
|
-
},
|
|
384
|
-
returnType: {
|
|
385
|
-
type: 'array',
|
|
386
|
-
},
|
|
387
|
-
},
|
|
388
|
-
cheqdUnsuspendCredential: {
|
|
389
|
-
description: 'Unsuspend a credential against a Status List 2021 as credential status registry',
|
|
390
|
-
arguments: {
|
|
391
|
-
type: 'object',
|
|
392
|
-
properties: {
|
|
393
|
-
args: {
|
|
394
|
-
type: 'object',
|
|
395
|
-
description: 'cheqdUnsuspendCredentialWithStatusList2021Args object as any for extensibility',
|
|
396
|
-
},
|
|
397
|
-
},
|
|
398
|
-
required: ['args'],
|
|
399
|
-
},
|
|
400
|
-
returnType: {
|
|
401
|
-
type: 'object',
|
|
402
|
-
},
|
|
403
|
-
},
|
|
404
|
-
cheqdUnsuspendCredentials: {
|
|
405
|
-
description: 'Unsuspend multiple credentials against a Status List 2021 as credential status registry',
|
|
406
|
-
arguments: {
|
|
407
|
-
type: 'object',
|
|
408
|
-
properties: {
|
|
409
|
-
args: {
|
|
410
|
-
type: 'object',
|
|
411
|
-
description: 'A cheqdUnsuspendBulkCredentialsWithStatusList2021Args object as any for extensibility',
|
|
412
|
-
},
|
|
413
|
-
},
|
|
414
|
-
required: ['args'],
|
|
415
|
-
},
|
|
416
|
-
returnType: {
|
|
417
|
-
type: 'array',
|
|
418
|
-
},
|
|
419
|
-
},
|
|
420
|
-
cheqdTransactSendTokens: {
|
|
421
|
-
description: 'Send tokens from one account to another',
|
|
422
|
-
arguments: {
|
|
423
|
-
type: 'object',
|
|
424
|
-
properties: {
|
|
425
|
-
args: {
|
|
426
|
-
type: 'object',
|
|
427
|
-
description: 'A cheqdTransactSendTokensArgs object as any for extensibility',
|
|
428
|
-
},
|
|
429
|
-
},
|
|
430
|
-
required: ['args'],
|
|
431
|
-
},
|
|
432
|
-
returnType: {
|
|
433
|
-
type: 'object',
|
|
434
|
-
},
|
|
435
|
-
},
|
|
436
|
-
cheqdObservePaymentCondition: {
|
|
437
|
-
description: 'Observe payment conditions for a given set of payment conditions',
|
|
438
|
-
arguments: {
|
|
439
|
-
type: 'object',
|
|
440
|
-
properties: {
|
|
441
|
-
args: {
|
|
442
|
-
type: 'object',
|
|
443
|
-
description: 'cheqdObservePaymentConditionArgs object as any for extensibility',
|
|
444
|
-
},
|
|
445
|
-
},
|
|
446
|
-
required: ['args'],
|
|
447
|
-
},
|
|
448
|
-
returnType: {
|
|
449
|
-
type: 'object',
|
|
450
|
-
},
|
|
451
|
-
},
|
|
452
|
-
},
|
|
453
|
-
},
|
|
454
|
-
};
|
|
455
|
-
supportedDidProviders;
|
|
456
|
-
didProvider;
|
|
457
|
-
providerId;
|
|
458
|
-
static defaultStatusList2021Length = 16 * 1024 * 8; // 16KB in bits or 131072 bits / entries
|
|
459
|
-
static defaultContextV1 = 'https://www.w3.org/2018/credentials/v1';
|
|
460
|
-
static statusList2021Context = 'https://w3id.org/vc-status-list-2021/v1';
|
|
461
|
-
constructor(args) {
|
|
462
|
-
if (typeof args.providers !== 'object') {
|
|
463
|
-
throw new Error('[did-provider-cheqd]: at least one did provider is required');
|
|
464
|
-
}
|
|
465
|
-
this.supportedDidProviders = args.providers;
|
|
466
|
-
this.didProvider = args.providers[0];
|
|
467
|
-
this.providerId = Cheqd.generateProviderId(this.didProvider.network);
|
|
468
|
-
this.methods = {
|
|
469
|
-
[exports.CreateIdentifierMethodName]: this.CreateIdentifier.bind(this),
|
|
470
|
-
[exports.UpdateIdentifierMethodName]: this.UpdateIdentifier.bind(this),
|
|
471
|
-
[exports.DeactivateIdentifierMethodName]: this.DeactivateIdentifier.bind(this),
|
|
472
|
-
[exports.CreateResourceMethodName]: this.CreateResource.bind(this),
|
|
473
|
-
[exports.CreateStatusList2021MethodName]: this.CreateStatusList2021.bind(this),
|
|
474
|
-
[exports.BroadcastStatusList2021MethodName]: this.BroadcastStatusList2021.bind(this),
|
|
475
|
-
[exports.GenerateDidDocMethodName]: this.GenerateDidDoc.bind(this),
|
|
476
|
-
[exports.GenerateDidDocWithLinkedResourceMethodName]: this.GenerateDidDocWithLinkedResource.bind(this),
|
|
477
|
-
[exports.GenerateKeyPairMethodName]: this.GenerateIdentityKeys.bind(this),
|
|
478
|
-
[exports.GenerateVersionIdMethodName]: this.GenerateVersionId.bind(this),
|
|
479
|
-
[exports.GenerateStatusList2021MethodName]: this.GenerateStatusList2021.bind(this),
|
|
480
|
-
[exports.IssueRevocableCredentialWithStatusList2021MethodName]: this.IssueRevocableCredentialWithStatusList2021.bind(this),
|
|
481
|
-
[exports.IssueSuspendableCredentialWithStatusList2021MethodName]: this.IssueSuspendableCredentialWithStatusList2021.bind(this),
|
|
482
|
-
[exports.VerifyCredentialMethodName]: this.VerifyCredentialWithStatusList2021.bind(this),
|
|
483
|
-
[exports.VerifyPresentationMethodName]: this.VerifyPresentationWithStatusList2021.bind(this),
|
|
484
|
-
[exports.CheckCredentialStatusMethodName]: this.CheckCredentialStatusWithStatusList2021.bind(this),
|
|
485
|
-
[exports.RevokeCredentialMethodName]: this.RevokeCredentialWithStatusList2021.bind(this),
|
|
486
|
-
[exports.RevokeCredentialsMethodName]: this.RevokeBulkCredentialsWithStatusList2021.bind(this),
|
|
487
|
-
[exports.SuspendCredentialMethodName]: this.SuspendCredentialWithStatusList2021.bind(this),
|
|
488
|
-
[exports.SuspendCredentialsMethodName]: this.SuspendBulkCredentialsWithStatusList2021.bind(this),
|
|
489
|
-
[exports.UnsuspendCredentialMethodName]: this.UnsuspendCredentialWithStatusList2021.bind(this),
|
|
490
|
-
[exports.UnsuspendCredentialsMethodName]: this.UnsuspendBulkCredentialsWithStatusList2021.bind(this),
|
|
491
|
-
[exports.TransactSendTokensMethodName]: this.TransactSendTokens.bind(this),
|
|
492
|
-
[exports.ObservePaymentConditionMethodName]: this.ObservePaymentCondition.bind(this),
|
|
493
|
-
[exports.MintCapacityCreditMethodName]: this.MintCapacityCredit.bind(this),
|
|
494
|
-
[exports.DelegateCapacityCreditMethodName]: this.DelegateCapacityCredit.bind(this),
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
async CreateIdentifier(args, context) {
|
|
498
|
-
if (typeof args.kms !== 'string') {
|
|
499
|
-
throw new Error('[did-provider-cheqd]: kms is required');
|
|
500
|
-
}
|
|
501
|
-
if (typeof args.alias !== 'string') {
|
|
502
|
-
throw new Error('[did-provider-cheqd]: alias is required');
|
|
503
|
-
}
|
|
504
|
-
if (typeof args.document !== 'object') {
|
|
505
|
-
throw new Error('[did-provider-cheqd]: document object is required');
|
|
506
|
-
}
|
|
507
|
-
const provider = await Cheqd.getProviderFromDidUrl(args.document.id, this.supportedDidProviders);
|
|
508
|
-
this.didProvider = provider;
|
|
509
|
-
this.providerId = Cheqd.generateProviderId(this.didProvider.network);
|
|
510
|
-
return await context.agent.didManagerCreate({
|
|
511
|
-
kms: args.kms,
|
|
512
|
-
alias: args.alias,
|
|
513
|
-
provider: this.providerId,
|
|
514
|
-
options: {
|
|
515
|
-
document: args.document,
|
|
516
|
-
keys: args.keys,
|
|
517
|
-
versionId: args?.versionId,
|
|
518
|
-
fee: args?.fee,
|
|
519
|
-
},
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
async UpdateIdentifier(args, context) {
|
|
523
|
-
if (typeof args.kms !== 'string') {
|
|
524
|
-
throw new Error('[did-provider-cheqd]: kms is required');
|
|
525
|
-
}
|
|
526
|
-
if (typeof args.document !== 'object') {
|
|
527
|
-
throw new Error('[did-provider-cheqd]: document object is required');
|
|
528
|
-
}
|
|
529
|
-
const provider = await Cheqd.getProviderFromDidUrl(args.document.id, this.supportedDidProviders);
|
|
530
|
-
this.didProvider = provider;
|
|
531
|
-
this.providerId = Cheqd.generateProviderId(this.didProvider.network);
|
|
532
|
-
return await context.agent.didManagerUpdate({
|
|
533
|
-
did: args.document.id,
|
|
534
|
-
document: args.document,
|
|
535
|
-
options: {
|
|
536
|
-
kms: args.kms,
|
|
537
|
-
keys: args.keys,
|
|
538
|
-
versionId: args?.versionId,
|
|
539
|
-
fee: args?.fee,
|
|
540
|
-
},
|
|
541
|
-
});
|
|
542
|
-
}
|
|
543
|
-
async DeactivateIdentifier(args, context) {
|
|
544
|
-
if (typeof args.kms !== 'string') {
|
|
545
|
-
throw new Error('[did-provider-cheqd]: kms is required');
|
|
546
|
-
}
|
|
547
|
-
if (typeof args.document !== 'object') {
|
|
548
|
-
throw new Error('[did-provider-cheqd]: document object is required');
|
|
549
|
-
}
|
|
550
|
-
const provider = await Cheqd.getProviderFromDidUrl(args.document.id, this.supportedDidProviders);
|
|
551
|
-
this.didProvider = provider;
|
|
552
|
-
this.providerId = Cheqd.generateProviderId(this.didProvider.network);
|
|
553
|
-
return await this.didProvider.deactivateIdentifier({
|
|
554
|
-
did: args.document.id,
|
|
555
|
-
document: args.document,
|
|
556
|
-
options: {
|
|
557
|
-
keys: args.keys,
|
|
558
|
-
fee: args?.fee,
|
|
559
|
-
},
|
|
560
|
-
}, context);
|
|
561
|
-
}
|
|
562
|
-
async CreateResource(args, context) {
|
|
563
|
-
if (typeof args.kms !== 'string') {
|
|
564
|
-
throw new Error('[did-provider-cheqd]: kms is required');
|
|
565
|
-
}
|
|
566
|
-
if (typeof args.payload !== 'object') {
|
|
567
|
-
throw new Error('[did-provider-cheqd]: payload object is required');
|
|
568
|
-
}
|
|
569
|
-
if (typeof args.network !== 'string') {
|
|
570
|
-
throw new Error('[did-provider-cheqd]: network is required');
|
|
571
|
-
}
|
|
572
|
-
if (args?.file) {
|
|
573
|
-
args.payload.data = await Cheqd.getFile(args.file);
|
|
574
|
-
}
|
|
575
|
-
if (typeof args?.payload?.data === 'string') {
|
|
576
|
-
args.payload.data = (0, uint8arrays_1.fromString)(args.payload.data, 'base64');
|
|
577
|
-
}
|
|
578
|
-
this.providerId = Cheqd.generateProviderId(args.network);
|
|
579
|
-
this.didProvider = await Cheqd.getProviderFromNetwork(args.network, this.supportedDidProviders);
|
|
580
|
-
return await this.didProvider.createResource({
|
|
581
|
-
options: {
|
|
582
|
-
kms: args.kms,
|
|
583
|
-
payload: args.payload,
|
|
584
|
-
signInputs: args.signInputs,
|
|
585
|
-
fee: args?.fee,
|
|
586
|
-
},
|
|
587
|
-
}, context);
|
|
588
|
-
}
|
|
589
|
-
async CreateStatusList2021(args, context) {
|
|
590
|
-
if (typeof args.kms !== 'string') {
|
|
591
|
-
throw new Error('[did-provider-cheqd]: kms is required');
|
|
592
|
-
}
|
|
593
|
-
if (typeof args.issuerDid !== 'string' || !args.issuerDid) {
|
|
594
|
-
throw new Error('[did-provider-cheqd]: issuerDid is required');
|
|
595
|
-
}
|
|
596
|
-
if (typeof args.statusListName !== 'string' || !args.statusListName) {
|
|
597
|
-
throw new Error('[did-provider-cheqd]: statusListName is required');
|
|
598
|
-
}
|
|
599
|
-
if (typeof args.statusPurpose !== 'string' || !args.statusPurpose) {
|
|
600
|
-
throw new Error('[did-provider-cheqd]: statusPurpose is required');
|
|
601
|
-
}
|
|
602
|
-
if (typeof args.encrypted === 'undefined') {
|
|
603
|
-
throw new Error('[did-provider-cheqd]: encrypted is required');
|
|
604
|
-
}
|
|
605
|
-
// validate statusPurpose
|
|
606
|
-
if (!Object.values(cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes).includes(args.statusPurpose)) {
|
|
607
|
-
throw new Error(`[did-provider-cheqd]: statusPurpose must be one of ${Object.values(cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes).join(', ')}`);
|
|
608
|
-
}
|
|
609
|
-
// validate statusListLength
|
|
610
|
-
if (args?.statusListLength) {
|
|
611
|
-
if (typeof args.statusListLength !== 'number') {
|
|
612
|
-
throw new Error('[did-provider-cheqd]: statusListLength must be number');
|
|
613
|
-
}
|
|
614
|
-
if (args.statusListLength < Cheqd.defaultStatusList2021Length) {
|
|
615
|
-
throw new Error(`[did-provider-cheqd]: statusListLength must be greater than or equal to ${Cheqd.defaultStatusList2021Length} number of entries`);
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
// validate statusListEncoding
|
|
619
|
-
if (args?.statusListEncoding) {
|
|
620
|
-
if (typeof args.statusListEncoding !== 'string') {
|
|
621
|
-
throw new Error('[did-provider-cheqd]: statusListEncoding must be string');
|
|
622
|
-
}
|
|
623
|
-
if (!Object.values(cheqd_did_provider_js_1.DefaultStatusList2021Encodings).includes(args.statusListEncoding)) {
|
|
624
|
-
throw new Error(`[did-provider-cheqd]: statusListEncoding must be one of ${Object.values(cheqd_did_provider_js_1.DefaultStatusList2021Encodings).join(', ')}`);
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
// validate validUntil
|
|
628
|
-
if (args?.validUntil) {
|
|
629
|
-
if (typeof args.validUntil !== 'string') {
|
|
630
|
-
throw new Error('[did-provider-cheqd]: validUntil must be string');
|
|
631
|
-
}
|
|
632
|
-
if (new Date() <= new Date(args.validUntil)) {
|
|
633
|
-
throw new Error('[did-provider-cheqd]: validUntil must be greater than current date');
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
// validate args in pairs - case: encrypted
|
|
637
|
-
if (args.encrypted) {
|
|
638
|
-
// validate paymentConditions
|
|
639
|
-
if (!args?.paymentConditions ||
|
|
640
|
-
!args?.paymentConditions?.length ||
|
|
641
|
-
!Array.isArray(args?.paymentConditions) ||
|
|
642
|
-
args?.paymentConditions.length === 0) {
|
|
643
|
-
throw new Error('[did-provider-cheqd]: paymentConditions is required');
|
|
644
|
-
}
|
|
645
|
-
if (!args?.paymentConditions?.every((condition) => condition.feePaymentAddress && condition.feePaymentAmount && condition.intervalInSeconds)) {
|
|
646
|
-
throw new Error('[did-provider-cheqd]: paymentConditions must contain feePaymentAddress and feeAmount and intervalInSeconds');
|
|
647
|
-
}
|
|
648
|
-
if (!args?.paymentConditions?.every((condition) => typeof condition.feePaymentAddress === 'string' &&
|
|
649
|
-
typeof condition.feePaymentAmount === 'string' &&
|
|
650
|
-
typeof condition.intervalInSeconds === 'number')) {
|
|
651
|
-
throw new Error('[did-provider-cheqd]: feePaymentAddress and feePaymentAmount must be string and intervalInSeconds must be number');
|
|
652
|
-
}
|
|
653
|
-
if (!args?.paymentConditions?.every((condition) => condition.type === exports.AccessControlConditionTypes.timelockPayment)) {
|
|
654
|
-
throw new Error('[did-provider-cheqd]: paymentConditions must be of type timelockPayment');
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
// get network
|
|
658
|
-
const network = args.issuerDid.split(':')[2];
|
|
659
|
-
// define provider
|
|
660
|
-
const provider = (function (that) {
|
|
661
|
-
// switch on network
|
|
662
|
-
return (that.supportedDidProviders.find((provider) => provider.network === network) ||
|
|
663
|
-
(function () {
|
|
664
|
-
throw new Error(`[did-provider-cheqd]: no relevant providers found`);
|
|
665
|
-
})());
|
|
666
|
-
})(this);
|
|
667
|
-
// generate bitstring
|
|
668
|
-
const bitstring = await context.agent[exports.GenerateStatusList2021MethodName]({
|
|
669
|
-
length: args?.statusListLength || Cheqd.defaultStatusList2021Length,
|
|
670
|
-
bitstringEncoding: args?.statusListEncoding || cheqd_did_provider_js_1.DefaultStatusList2021Encodings.base64url,
|
|
671
|
-
});
|
|
672
|
-
// construct data and metadata tuple
|
|
673
|
-
const data = args.encrypted
|
|
674
|
-
? await (async function (that) {
|
|
675
|
-
// encrypt bitstring - case: symmetric
|
|
676
|
-
const { encryptedString: symmetricEncryptionCiphertext, symmetricKey } = await v6_js_1.LitProtocol.encryptDirect((0, uint8arrays_1.fromString)(bitstring, args?.statusListEncoding || cheqd_did_provider_js_1.DefaultStatusList2021Encodings.base64url));
|
|
677
|
-
// instantiate dkg-threshold client, in which case lit-protocol is used
|
|
678
|
-
const lit = await provider.instantiateDkgThresholdProtocolClient({});
|
|
679
|
-
// construct access control conditions
|
|
680
|
-
const unifiedAccessControlConditions = await Promise.all(args.paymentConditions.map(async (condition) => {
|
|
681
|
-
switch (condition.type) {
|
|
682
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
683
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
684
|
-
key: '$.tx_responses.*.timestamp',
|
|
685
|
-
comparator: '<=',
|
|
686
|
-
value: `${condition.intervalInSeconds}`,
|
|
687
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight, args?.dkgOptions?.chain || that.didProvider.dkgOptions.chain);
|
|
688
|
-
default:
|
|
689
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
690
|
-
}
|
|
691
|
-
}));
|
|
692
|
-
// encrypt bitstring - case: threshold
|
|
693
|
-
const { encryptedString: thresholdEncryptionCiphertext, stringHash } = await lit.encrypt((0, uint8arrays_1.fromString)(bitstring, args?.statusListEncoding || cheqd_did_provider_js_1.DefaultStatusList2021Encodings.base64url), unifiedAccessControlConditions);
|
|
694
|
-
// construct encoded list
|
|
695
|
-
const encodedList = `${await (0, helpers_js_1.blobToHexString)(symmetricEncryptionCiphertext)}-${(0, uint8arrays_1.toString)(thresholdEncryptionCiphertext, 'hex')}`;
|
|
696
|
-
// return result tuple
|
|
697
|
-
switch (args.statusPurpose) {
|
|
698
|
-
case cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.revocation:
|
|
699
|
-
return [
|
|
700
|
-
{
|
|
701
|
-
StatusList2021: {
|
|
702
|
-
statusPurpose: args.statusPurpose,
|
|
703
|
-
encodedList,
|
|
704
|
-
validFrom: new Date().toISOString(),
|
|
705
|
-
validUntil: args?.validUntil,
|
|
706
|
-
},
|
|
707
|
-
metadata: {
|
|
708
|
-
type: cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes.revocation,
|
|
709
|
-
encrypted: true,
|
|
710
|
-
encoding: args?.statusListEncoding || cheqd_did_provider_js_1.DefaultStatusList2021Encodings.base64url,
|
|
711
|
-
statusListHash: stringHash,
|
|
712
|
-
paymentConditions: args.paymentConditions,
|
|
713
|
-
},
|
|
714
|
-
},
|
|
715
|
-
{
|
|
716
|
-
symmetricEncryptionCiphertext: await (0, helpers_js_1.blobToHexString)(symmetricEncryptionCiphertext),
|
|
717
|
-
thresholdEncryptionCiphertext: (0, uint8arrays_1.toString)(thresholdEncryptionCiphertext, 'hex'),
|
|
718
|
-
stringHash,
|
|
719
|
-
symmetricKey: (0, uint8arrays_1.toString)(symmetricKey, 'hex'),
|
|
720
|
-
},
|
|
721
|
-
];
|
|
722
|
-
case cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension:
|
|
723
|
-
return [
|
|
724
|
-
{
|
|
725
|
-
StatusList2021: {
|
|
726
|
-
statusPurpose: args.statusPurpose,
|
|
727
|
-
encodedList,
|
|
728
|
-
validFrom: new Date().toISOString(),
|
|
729
|
-
validUntil: args?.validUntil,
|
|
730
|
-
},
|
|
731
|
-
metadata: {
|
|
732
|
-
type: cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes.suspension,
|
|
733
|
-
encrypted: true,
|
|
734
|
-
encoding: args?.statusListEncoding || cheqd_did_provider_js_1.DefaultStatusList2021Encodings.base64url,
|
|
735
|
-
statusListHash: stringHash,
|
|
736
|
-
paymentConditions: args.paymentConditions,
|
|
737
|
-
},
|
|
738
|
-
},
|
|
739
|
-
{
|
|
740
|
-
symmetricEncryptionCiphertext: await (0, helpers_js_1.blobToHexString)(symmetricEncryptionCiphertext),
|
|
741
|
-
thresholdEncryptionCiphertext: (0, uint8arrays_1.toString)(thresholdEncryptionCiphertext, 'hex'),
|
|
742
|
-
stringHash,
|
|
743
|
-
symmetricKey: (0, uint8arrays_1.toString)(symmetricKey, 'hex'),
|
|
744
|
-
},
|
|
745
|
-
];
|
|
746
|
-
default:
|
|
747
|
-
throw new Error(`[did-provider-cheqd]: status purpose is not valid ${args.statusPurpose}`);
|
|
748
|
-
}
|
|
749
|
-
})(this)
|
|
750
|
-
: await (async function () {
|
|
751
|
-
switch (args.statusPurpose) {
|
|
752
|
-
case cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.revocation:
|
|
753
|
-
return [
|
|
754
|
-
{
|
|
755
|
-
StatusList2021: {
|
|
756
|
-
statusPurpose: args.statusPurpose,
|
|
757
|
-
encodedList: bitstring,
|
|
758
|
-
validFrom: new Date().toISOString(),
|
|
759
|
-
validUntil: args?.validUntil,
|
|
760
|
-
},
|
|
761
|
-
metadata: {
|
|
762
|
-
type: cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes.revocation,
|
|
763
|
-
encrypted: false,
|
|
764
|
-
encoding: args?.statusListEncoding || cheqd_did_provider_js_1.DefaultStatusList2021Encodings.base64url,
|
|
765
|
-
},
|
|
766
|
-
},
|
|
767
|
-
undefined,
|
|
768
|
-
];
|
|
769
|
-
case cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension:
|
|
770
|
-
return [
|
|
771
|
-
{
|
|
772
|
-
StatusList2021: {
|
|
773
|
-
statusPurpose: args.statusPurpose,
|
|
774
|
-
encodedList: bitstring,
|
|
775
|
-
validFrom: new Date().toISOString(),
|
|
776
|
-
validUntil: args?.validUntil,
|
|
777
|
-
},
|
|
778
|
-
metadata: {
|
|
779
|
-
type: cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes.suspension,
|
|
780
|
-
encrypted: false,
|
|
781
|
-
encoding: args?.statusListEncoding || cheqd_did_provider_js_1.DefaultStatusList2021Encodings.base64url,
|
|
782
|
-
},
|
|
783
|
-
},
|
|
784
|
-
undefined,
|
|
785
|
-
];
|
|
786
|
-
default:
|
|
787
|
-
throw new Error('[did-provider-cheqd]: statusPurpose is not valid');
|
|
788
|
-
}
|
|
789
|
-
})();
|
|
790
|
-
// construct payload
|
|
791
|
-
const payload = {
|
|
792
|
-
id: (0, uuid_1.v4)(),
|
|
793
|
-
collectionId: args.issuerDid.split(':').reverse()[0],
|
|
794
|
-
name: args.statusListName,
|
|
795
|
-
resourceType: cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes[args.statusPurpose],
|
|
796
|
-
version: args?.resourceVersion || new Date().toISOString(),
|
|
797
|
-
alsoKnownAs: args?.alsoKnownAs || [],
|
|
798
|
-
data: (0, uint8arrays_1.fromString)(JSON.stringify(data[0]), 'utf-8'),
|
|
799
|
-
};
|
|
800
|
-
// return result
|
|
801
|
-
return {
|
|
802
|
-
created: await context.agent[exports.BroadcastStatusList2021MethodName]({
|
|
803
|
-
kms: args.kms,
|
|
804
|
-
payload,
|
|
805
|
-
network: network,
|
|
806
|
-
}),
|
|
807
|
-
resource: data[0],
|
|
808
|
-
resourceMetadata: await Cheqd.fetchStatusList2021Metadata({
|
|
809
|
-
credentialStatus: {
|
|
810
|
-
id: `${cheqd_did_resolver_js_1.DefaultResolverUrl}${args.issuerDid}?resourceName=${args.statusListName}&resourceType=${cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes[args.statusPurpose]}`,
|
|
811
|
-
type: 'StatusList2021Entry',
|
|
812
|
-
},
|
|
813
|
-
}),
|
|
814
|
-
encrypted: args.encrypted,
|
|
815
|
-
symmetricKey: args.encrypted && args.returnSymmetricKey ? data[1]?.symmetricKey : undefined,
|
|
816
|
-
};
|
|
817
|
-
}
|
|
818
|
-
async BroadcastStatusList2021(args, context) {
|
|
819
|
-
if (typeof args.kms !== 'string') {
|
|
820
|
-
throw new Error('[did-provider-cheqd]: kms is required');
|
|
821
|
-
}
|
|
822
|
-
if (typeof args.payload !== 'object') {
|
|
823
|
-
throw new Error('[did-provider-cheqd]: payload object is required');
|
|
824
|
-
}
|
|
825
|
-
if (typeof args.network !== 'string') {
|
|
826
|
-
throw new Error('[did-provider-cheqd]: network is required');
|
|
827
|
-
}
|
|
828
|
-
if (args?.file) {
|
|
829
|
-
args.payload.data = await Cheqd.getFile(args.file);
|
|
830
|
-
}
|
|
831
|
-
if (typeof args?.payload?.data === 'string') {
|
|
832
|
-
args.payload.data = (0, uint8arrays_1.fromString)(args.payload.data, 'base64');
|
|
833
|
-
}
|
|
834
|
-
// TODO: validate data as per bitstring
|
|
835
|
-
// validate resource type
|
|
836
|
-
if (!Object.values(cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes).includes(args?.payload?.resourceType)) {
|
|
837
|
-
throw new Error(`[did-provider-cheqd]: resourceType must be one of ${Object.values(cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes).join(', ')}`);
|
|
838
|
-
}
|
|
839
|
-
this.providerId = Cheqd.generateProviderId(args.network);
|
|
840
|
-
this.didProvider = await Cheqd.getProviderFromNetwork(args.network, this.supportedDidProviders);
|
|
841
|
-
return await this.didProvider.createResource({
|
|
842
|
-
options: {
|
|
843
|
-
kms: args.kms,
|
|
844
|
-
payload: args.payload,
|
|
845
|
-
signInputs: args.signInputs,
|
|
846
|
-
fee: args?.fee ||
|
|
847
|
-
(await sdk_1.ResourceModule.generateCreateResourceJsonFees((await this.didProvider.getWalletAccounts())[0].address)),
|
|
848
|
-
},
|
|
849
|
-
}, context);
|
|
850
|
-
}
|
|
851
|
-
async GenerateDidDoc(args, context) {
|
|
852
|
-
if (typeof args.verificationMethod !== 'string') {
|
|
853
|
-
throw new Error('[did-provider-cheqd]: verificationMethod is required');
|
|
854
|
-
}
|
|
855
|
-
if (typeof args.methodSpecificIdAlgo !== 'string') {
|
|
856
|
-
throw new Error('[did-provider-cheqd]: methodSpecificIdAlgo is required');
|
|
857
|
-
}
|
|
858
|
-
if (typeof args.network !== 'string') {
|
|
859
|
-
throw new Error('[did-provider-cheqd]: network is required');
|
|
860
|
-
}
|
|
861
|
-
const keyPair = (0, sdk_1.createKeyPairBase64)();
|
|
862
|
-
const keyPairHex = {
|
|
863
|
-
publicKey: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(keyPair.publicKey, 'base64'), 'hex'),
|
|
864
|
-
privateKey: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(keyPair.privateKey, 'base64'), 'hex'),
|
|
865
|
-
};
|
|
866
|
-
const verificationKeys = (0, sdk_1.createVerificationKeys)(keyPair.publicKey, args.methodSpecificIdAlgo, 'key-1', args.network);
|
|
867
|
-
const verificationMethods = (0, sdk_1.createDidVerificationMethod)([args.verificationMethod], [verificationKeys]);
|
|
868
|
-
return {
|
|
869
|
-
didDoc: (0, sdk_1.createDidPayload)(verificationMethods, [verificationKeys]),
|
|
870
|
-
versionId: (0, uuid_1.v4)(),
|
|
871
|
-
keys: [
|
|
872
|
-
{
|
|
873
|
-
publicKeyHex: keyPairHex.publicKey,
|
|
874
|
-
privateKeyHex: keyPairHex.privateKey,
|
|
875
|
-
kid: keyPairHex.publicKey,
|
|
876
|
-
type: 'Ed25519',
|
|
877
|
-
},
|
|
878
|
-
],
|
|
879
|
-
};
|
|
880
|
-
}
|
|
881
|
-
async GenerateDidDocWithLinkedResource(args, context) {
|
|
882
|
-
if (typeof args.verificationMethod !== 'string') {
|
|
883
|
-
throw new Error('[did-provider-cheqd]: verificationMethod is required');
|
|
884
|
-
}
|
|
885
|
-
if (typeof args.methodSpecificIdAlgo !== 'string') {
|
|
886
|
-
throw new Error('[did-provider-cheqd]: methodSpecificIdAlgo is required');
|
|
887
|
-
}
|
|
888
|
-
if (typeof args.network !== 'string') {
|
|
889
|
-
throw new Error('[did-provider-cheqd]: network is required');
|
|
890
|
-
}
|
|
891
|
-
const keyPair = (0, sdk_1.createKeyPairBase64)();
|
|
892
|
-
const keyPairHex = {
|
|
893
|
-
publicKey: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(keyPair.publicKey, 'base64'), 'hex'),
|
|
894
|
-
privateKey: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(keyPair.privateKey, 'base64'), 'hex'),
|
|
895
|
-
};
|
|
896
|
-
const verificationKeys = (0, sdk_1.createVerificationKeys)(keyPair.publicKey, args.methodSpecificIdAlgo, 'key-1', args.network);
|
|
897
|
-
const verificationMethods = (0, sdk_1.createDidVerificationMethod)([args.verificationMethod], [verificationKeys]);
|
|
898
|
-
const payload = (0, sdk_1.createDidPayload)(verificationMethods, [verificationKeys]);
|
|
899
|
-
return {
|
|
900
|
-
didDoc: payload,
|
|
901
|
-
versionId: (0, uuid_1.v4)(),
|
|
902
|
-
keys: [
|
|
903
|
-
{
|
|
904
|
-
publicKeyHex: keyPairHex.publicKey,
|
|
905
|
-
privateKeyHex: keyPairHex.privateKey,
|
|
906
|
-
kid: keyPairHex.publicKey,
|
|
907
|
-
type: 'Ed25519',
|
|
908
|
-
},
|
|
909
|
-
],
|
|
910
|
-
linkedResource: {
|
|
911
|
-
id: (0, uuid_1.v4)(),
|
|
912
|
-
collectionId: payload.id.split(':').reverse()[0],
|
|
913
|
-
name: 'sample json resource',
|
|
914
|
-
version: '1.0.0',
|
|
915
|
-
resourceType: 'SampleResource',
|
|
916
|
-
alsoKnownAs: [],
|
|
917
|
-
data: (0, uint8arrays_1.toString)(new TextEncoder().encode(JSON.stringify({ sample: 'json' })), 'base64'),
|
|
918
|
-
},
|
|
919
|
-
};
|
|
920
|
-
}
|
|
921
|
-
async GenerateIdentityKeys(args, context) {
|
|
922
|
-
const keyPair = (0, sdk_1.createKeyPairHex)();
|
|
923
|
-
return {
|
|
924
|
-
publicKeyHex: keyPair.publicKey,
|
|
925
|
-
privateKeyHex: keyPair.privateKey,
|
|
926
|
-
kid: keyPair.publicKey,
|
|
927
|
-
type: 'Ed25519',
|
|
928
|
-
};
|
|
929
|
-
}
|
|
930
|
-
async GenerateVersionId(args, context) {
|
|
931
|
-
return (0, uuid_1.v4)();
|
|
932
|
-
}
|
|
933
|
-
async GenerateStatusList2021(args, context) {
|
|
934
|
-
const statusList = args?.buffer
|
|
935
|
-
? new vc_status_list_1.StatusList({ buffer: args.buffer })
|
|
936
|
-
: new vc_status_list_1.StatusList({ length: args?.length || Cheqd.defaultStatusList2021Length });
|
|
937
|
-
const encoded = (await statusList.encode());
|
|
938
|
-
switch (args?.bitstringEncoding) {
|
|
939
|
-
case 'base64url':
|
|
940
|
-
return encoded;
|
|
941
|
-
case 'hex':
|
|
942
|
-
return (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(encoded, 'base64url'), 'hex');
|
|
943
|
-
default:
|
|
944
|
-
return encoded;
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
async IssueRevocableCredentialWithStatusList2021(args, context) {
|
|
948
|
-
// generate index
|
|
949
|
-
const statusListIndex = args.statusOptions.statusListIndex ||
|
|
950
|
-
(await (0, helpers_js_1.randomFromRange)(args.statusOptions.statusListRangeStart || 0, (args.statusOptions.statusListRangeEnd || Cheqd.defaultStatusList2021Length) - 1, args.statusOptions.indexNotIn || []));
|
|
951
|
-
// construct issuer
|
|
952
|
-
const issuer = args.issuanceOptions.credential.issuer.id
|
|
953
|
-
? args.issuanceOptions.credential.issuer.id
|
|
954
|
-
: args.issuanceOptions.credential.issuer;
|
|
955
|
-
// generate status list credential
|
|
956
|
-
const statusListCredential = `${cheqd_did_resolver_js_1.DefaultResolverUrl}${issuer}?resourceName=${args.statusOptions.statusListName}&resourceType=${cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes.revocation}`;
|
|
957
|
-
// construct credential status
|
|
958
|
-
const credentialStatus = {
|
|
959
|
-
id: `${statusListCredential}#${statusListIndex}`,
|
|
960
|
-
type: 'StatusList2021Entry',
|
|
961
|
-
statusPurpose: cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.revocation,
|
|
962
|
-
statusListIndex: `${statusListIndex}`,
|
|
963
|
-
};
|
|
964
|
-
// add credential status to credential
|
|
965
|
-
args.issuanceOptions.credential.credentialStatus = credentialStatus;
|
|
966
|
-
// add relevant context
|
|
967
|
-
args.issuanceOptions.credential['@context'] = (function () {
|
|
968
|
-
// if no context is provided, add default context
|
|
969
|
-
if (!args.issuanceOptions.credential['@context']) {
|
|
970
|
-
return [Cheqd.defaultContextV1, Cheqd.statusList2021Context];
|
|
971
|
-
}
|
|
972
|
-
// if context is provided as an array, add default context if it is not already present
|
|
973
|
-
if (Array.isArray(args.issuanceOptions.credential['@context'])) {
|
|
974
|
-
if (args.issuanceOptions.credential['@context'].length === 0) {
|
|
975
|
-
return [Cheqd.defaultContextV1, Cheqd.statusList2021Context];
|
|
976
|
-
}
|
|
977
|
-
if (!args.issuanceOptions.credential['@context'].includes(Cheqd.statusList2021Context)) {
|
|
978
|
-
return [...args.issuanceOptions.credential['@context'], Cheqd.statusList2021Context];
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
// if context is provided as a string, add default context if it is not already present
|
|
982
|
-
if (typeof args.issuanceOptions.credential['@context'] === 'string')
|
|
983
|
-
return [Cheqd.defaultContextV1, Cheqd.statusList2021Context];
|
|
984
|
-
})();
|
|
985
|
-
// create a credential
|
|
986
|
-
const credential = await context.agent.createVerifiableCredential(args.issuanceOptions);
|
|
987
|
-
return credential;
|
|
988
|
-
}
|
|
989
|
-
async IssueSuspendableCredentialWithStatusList2021(args, context) {
|
|
990
|
-
// generate index
|
|
991
|
-
const statusListIndex = args.statusOptions.statusListIndex ||
|
|
992
|
-
(await (0, helpers_js_1.randomFromRange)(args.statusOptions.statusListRangeStart || 0, (args.statusOptions.statusListRangeEnd || Cheqd.defaultStatusList2021Length) - 1, args.statusOptions.indexNotIn || []));
|
|
993
|
-
// construct issuer
|
|
994
|
-
const issuer = args.issuanceOptions.credential.issuer.id
|
|
995
|
-
? args.issuanceOptions.credential.issuer.id
|
|
996
|
-
: args.issuanceOptions.credential.issuer;
|
|
997
|
-
// generate status list credential
|
|
998
|
-
const statusListCredential = `${cheqd_did_resolver_js_1.DefaultResolverUrl}${issuer}?resourceName=${args.statusOptions.statusListName}&resourceType=${cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes.suspension}`;
|
|
999
|
-
// construct credential status
|
|
1000
|
-
const credentialStatus = {
|
|
1001
|
-
id: `${statusListCredential}#${statusListIndex}`,
|
|
1002
|
-
type: 'StatusList2021Entry',
|
|
1003
|
-
statusPurpose: cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension,
|
|
1004
|
-
statusListIndex: `${statusListIndex}`,
|
|
1005
|
-
};
|
|
1006
|
-
// add credential status to credential
|
|
1007
|
-
args.issuanceOptions.credential.credentialStatus = credentialStatus;
|
|
1008
|
-
// add relevant context
|
|
1009
|
-
args.issuanceOptions.credential['@context'] = (function () {
|
|
1010
|
-
// if no context is provided, add default context
|
|
1011
|
-
if (!args.issuanceOptions.credential['@context']) {
|
|
1012
|
-
return [Cheqd.defaultContextV1, Cheqd.statusList2021Context];
|
|
1013
|
-
}
|
|
1014
|
-
// if context is provided as an array, add default context if it is not already present
|
|
1015
|
-
if (Array.isArray(args.issuanceOptions.credential['@context'])) {
|
|
1016
|
-
if (args.issuanceOptions.credential['@context'].length === 0) {
|
|
1017
|
-
return [Cheqd.defaultContextV1, Cheqd.statusList2021Context];
|
|
1018
|
-
}
|
|
1019
|
-
if (!args.issuanceOptions.credential['@context'].includes(Cheqd.statusList2021Context)) {
|
|
1020
|
-
return [...args.issuanceOptions.credential['@context'], Cheqd.statusList2021Context];
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
// if context is provided as a string, add default context if it is not already present
|
|
1024
|
-
if (typeof args.issuanceOptions.credential['@context'] === 'string')
|
|
1025
|
-
return [Cheqd.defaultContextV1, Cheqd.statusList2021Context];
|
|
1026
|
-
})();
|
|
1027
|
-
// create a credential
|
|
1028
|
-
const credential = await context.agent.createVerifiableCredential(args.issuanceOptions);
|
|
1029
|
-
return credential;
|
|
1030
|
-
}
|
|
1031
|
-
async VerifyCredentialWithStatusList2021(args, context) {
|
|
1032
|
-
// verify default policies
|
|
1033
|
-
const verificationResult = await context.agent.verifyCredential({
|
|
1034
|
-
...args?.verificationArgs,
|
|
1035
|
-
credential: args.credential,
|
|
1036
|
-
policies: {
|
|
1037
|
-
...args?.verificationArgs?.policies,
|
|
1038
|
-
credentialStatus: false,
|
|
1039
|
-
},
|
|
1040
|
-
});
|
|
1041
|
-
// early return if verification failed
|
|
1042
|
-
if (!verificationResult.verified) {
|
|
1043
|
-
return { verified: false, error: verificationResult.error };
|
|
1044
|
-
}
|
|
1045
|
-
// if jwt credential, decode it
|
|
1046
|
-
const credential = typeof args.credential === 'string' ? await Cheqd.decodeCredentialJWT(args.credential) : args.credential;
|
|
1047
|
-
// define issuer
|
|
1048
|
-
const issuer = typeof credential.issuer === 'string' ? credential.issuer : credential.issuer.id;
|
|
1049
|
-
// define provider, if applicable
|
|
1050
|
-
this.didProvider = await Cheqd.getProviderFromDidUrl(issuer, this.supportedDidProviders);
|
|
1051
|
-
// define provider id, if applicable
|
|
1052
|
-
this.providerId = Cheqd.generateProviderId(issuer);
|
|
1053
|
-
// define dkg options, if provided
|
|
1054
|
-
args.dkgOptions ||= this.didProvider.dkgOptions;
|
|
1055
|
-
// verify credential status
|
|
1056
|
-
switch (credential.credentialStatus?.statusPurpose) {
|
|
1057
|
-
case cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.revocation:
|
|
1058
|
-
return {
|
|
1059
|
-
...verificationResult,
|
|
1060
|
-
revoked: await Cheqd.checkRevoked(credential, { ...args.options, topArgs: args }),
|
|
1061
|
-
};
|
|
1062
|
-
case cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension:
|
|
1063
|
-
return {
|
|
1064
|
-
...verificationResult,
|
|
1065
|
-
suspended: await Cheqd.checkSuspended(credential, { ...args.options, topArgs: args }),
|
|
1066
|
-
};
|
|
1067
|
-
default:
|
|
1068
|
-
throw new Error(`[did-provider-cheqd]: verify credential: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
async VerifyPresentationWithStatusList2021(args, context) {
|
|
1072
|
-
// verify default policies
|
|
1073
|
-
const verificationResult = await context.agent.verifyPresentation({
|
|
1074
|
-
...args?.verificationArgs,
|
|
1075
|
-
presentation: args.presentation,
|
|
1076
|
-
policies: {
|
|
1077
|
-
...args?.verificationArgs?.policies,
|
|
1078
|
-
credentialStatus: false,
|
|
1079
|
-
},
|
|
1080
|
-
});
|
|
1081
|
-
// early return if verification failed
|
|
1082
|
-
if (!verificationResult.verified) {
|
|
1083
|
-
return { verified: false, error: verificationResult.error };
|
|
1084
|
-
}
|
|
1085
|
-
// early return if no verifiable credentials are provided
|
|
1086
|
-
if (!args.presentation.verifiableCredential)
|
|
1087
|
-
throw new Error('[did-provider-cheqd]: verify presentation: presentation.verifiableCredential is required');
|
|
1088
|
-
// verify credential(s) status(es)
|
|
1089
|
-
for (let credential of args.presentation.verifiableCredential) {
|
|
1090
|
-
// if jwt credential, decode it
|
|
1091
|
-
if (typeof credential === 'string')
|
|
1092
|
-
credential = await Cheqd.decodeCredentialJWT(credential);
|
|
1093
|
-
// define issuer
|
|
1094
|
-
const issuer = typeof credential.issuer === 'string' ? credential.issuer : credential.issuer.id;
|
|
1095
|
-
// define provider, if applicable
|
|
1096
|
-
this.didProvider = await Cheqd.getProviderFromDidUrl(issuer, this.supportedDidProviders);
|
|
1097
|
-
// define provider id, if applicable
|
|
1098
|
-
this.providerId = Cheqd.generateProviderId(issuer);
|
|
1099
|
-
// define dkg options, if provided
|
|
1100
|
-
args.dkgOptions ||= this.didProvider.dkgOptions;
|
|
1101
|
-
switch (credential.credentialStatus?.statusPurpose) {
|
|
1102
|
-
case cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.revocation:
|
|
1103
|
-
return {
|
|
1104
|
-
...verificationResult,
|
|
1105
|
-
revoked: await Cheqd.checkRevoked(credential, { ...args.options, topArgs: args }),
|
|
1106
|
-
};
|
|
1107
|
-
case cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension:
|
|
1108
|
-
return {
|
|
1109
|
-
...verificationResult,
|
|
1110
|
-
suspended: await Cheqd.checkSuspended(credential, { ...args.options, topArgs: args }),
|
|
1111
|
-
};
|
|
1112
|
-
default:
|
|
1113
|
-
throw new Error(`[did-provider-cheqd]: verify presentation: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
return { ...verificationResult, verified: true };
|
|
1117
|
-
}
|
|
1118
|
-
async CheckCredentialStatusWithStatusList2021(args, context) {
|
|
1119
|
-
// verify credential, if provided and status options are not
|
|
1120
|
-
if (args?.credential && !args?.statusOptions) {
|
|
1121
|
-
const verificationResult = await context.agent.verifyCredential({
|
|
1122
|
-
...args?.verificationOptions,
|
|
1123
|
-
credential: args.credential,
|
|
1124
|
-
policies: {
|
|
1125
|
-
credentialStatus: false,
|
|
1126
|
-
},
|
|
1127
|
-
});
|
|
1128
|
-
// early return if verification failed
|
|
1129
|
-
if (!verificationResult.verified) {
|
|
1130
|
-
return { revoked: false, error: verificationResult.error };
|
|
1131
|
-
}
|
|
1132
|
-
}
|
|
1133
|
-
// if status options are provided, give precedence
|
|
1134
|
-
if (args?.statusOptions) {
|
|
1135
|
-
// validate status options - case: statusOptions.issuerDid
|
|
1136
|
-
if (!args.statusOptions.issuerDid)
|
|
1137
|
-
throw new Error('[did-provider-cheqd]: check status: statusOptions.issuerDid is required');
|
|
1138
|
-
// validate status options - case: statusOptions.statusListName
|
|
1139
|
-
if (!args.statusOptions.statusListName)
|
|
1140
|
-
throw new Error('[did-provider-cheqd]: check status: statusOptions.statusListName is required');
|
|
1141
|
-
// validate status options - case: statusOptions.statusListIndex
|
|
1142
|
-
if (!args.statusOptions.statusPurpose)
|
|
1143
|
-
throw new Error('[did-provider-cheqd]: check status: statusOptions.statusListIndex is required');
|
|
1144
|
-
// validate status options - case: statusOptions.statusListIndex
|
|
1145
|
-
if (!args.statusOptions.statusListIndex)
|
|
1146
|
-
throw new Error('[did-provider-cheqd]: check status: statusOptions.statusListIndex is required');
|
|
1147
|
-
// generate resource type
|
|
1148
|
-
const resourceType = args.statusOptions.statusPurpose === cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.revocation
|
|
1149
|
-
? cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes.revocation
|
|
1150
|
-
: cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes.suspension;
|
|
1151
|
-
// construct status list credential
|
|
1152
|
-
const statusListCredential = `${cheqd_did_resolver_js_1.DefaultResolverUrl}${args.statusOptions.issuerDid}?resourceName=${args.statusOptions.statusListName}&resourceType=${resourceType}`;
|
|
1153
|
-
// construct credential status
|
|
1154
|
-
args.credential = {
|
|
1155
|
-
'@context': [],
|
|
1156
|
-
issuer: args.statusOptions.issuerDid,
|
|
1157
|
-
credentialSubject: {},
|
|
1158
|
-
credentialStatus: {
|
|
1159
|
-
id: `${statusListCredential}#${args.statusOptions.statusListIndex}`,
|
|
1160
|
-
type: 'StatusList2021Entry',
|
|
1161
|
-
statusPurpose: `${args.statusOptions.statusPurpose}`,
|
|
1162
|
-
statusListIndex: `${args.statusOptions.statusListIndex}`,
|
|
1163
|
-
},
|
|
1164
|
-
issuanceDate: '',
|
|
1165
|
-
proof: {},
|
|
1166
|
-
};
|
|
1167
|
-
}
|
|
1168
|
-
// validate args - case: credential
|
|
1169
|
-
if (!args.credential)
|
|
1170
|
-
throw new Error('[did-provider-cheqd]: revocation: credential is required');
|
|
1171
|
-
// if jwt credential, decode it
|
|
1172
|
-
const credential = typeof args.credential === 'string' ? await Cheqd.decodeCredentialJWT(args.credential) : args.credential;
|
|
1173
|
-
// define issuer
|
|
1174
|
-
const issuer = typeof credential.issuer === 'string' ? credential.issuer : credential.issuer.id;
|
|
1175
|
-
// define provider, if applicable
|
|
1176
|
-
this.didProvider = await Cheqd.getProviderFromDidUrl(issuer, this.supportedDidProviders);
|
|
1177
|
-
// define provider id, if applicable
|
|
1178
|
-
this.providerId = Cheqd.generateProviderId(issuer);
|
|
1179
|
-
// define dkg options, if provided
|
|
1180
|
-
args.dkgOptions ||= this.didProvider.dkgOptions;
|
|
1181
|
-
switch (credential.credentialStatus?.statusPurpose) {
|
|
1182
|
-
case cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.revocation:
|
|
1183
|
-
return { revoked: await Cheqd.checkRevoked(credential, { ...args.options, topArgs: args }) };
|
|
1184
|
-
case cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension:
|
|
1185
|
-
return { suspended: await Cheqd.checkSuspended(credential, { ...args.options, topArgs: args }) };
|
|
1186
|
-
default:
|
|
1187
|
-
throw new Error(`[did-provider-cheqd]: check status: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1190
|
-
async RevokeCredentialWithStatusList2021(args, context) {
|
|
1191
|
-
// verify credential, if provided and revocation options are not
|
|
1192
|
-
if (args?.credential && !args?.revocationOptions) {
|
|
1193
|
-
const verificationResult = await context.agent.verifyCredential({
|
|
1194
|
-
...args?.verificationOptions,
|
|
1195
|
-
credential: args.credential,
|
|
1196
|
-
policies: {
|
|
1197
|
-
credentialStatus: false,
|
|
1198
|
-
},
|
|
1199
|
-
});
|
|
1200
|
-
// early return if verification failed
|
|
1201
|
-
if (!verificationResult.verified) {
|
|
1202
|
-
return { revoked: false, error: verificationResult.error };
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1205
|
-
// if revocation options are provided, give precedence
|
|
1206
|
-
if (args?.revocationOptions) {
|
|
1207
|
-
// validate revocation options - case: revocationOptions.issuerDid
|
|
1208
|
-
if (!args.revocationOptions.issuerDid)
|
|
1209
|
-
throw new Error('[did-provider-cheqd]: revocation: revocationOptions.issuerDid is required');
|
|
1210
|
-
// validate revocation options - case: revocationOptions.statusListName
|
|
1211
|
-
if (!args.revocationOptions.statusListName)
|
|
1212
|
-
throw new Error('[did-provider-cheqd]: revocation: revocationOptions.statusListName is required');
|
|
1213
|
-
// validate revocation options - case: revocationOptions.statusListIndex
|
|
1214
|
-
if (!args.revocationOptions.statusListIndex)
|
|
1215
|
-
throw new Error('[did-provider-cheqd]: revocation: revocationOptions.statusListIndex is required');
|
|
1216
|
-
// construct status list credential
|
|
1217
|
-
const statusListCredential = `${cheqd_did_resolver_js_1.DefaultResolverUrl}${args.revocationOptions.issuerDid}?resourceName=${args.revocationOptions.statusListName}&resourceType=${cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes.revocation}`;
|
|
1218
|
-
// construct credential status
|
|
1219
|
-
args.credential = {
|
|
1220
|
-
'@context': [],
|
|
1221
|
-
issuer: args.revocationOptions.issuerDid,
|
|
1222
|
-
credentialSubject: {},
|
|
1223
|
-
credentialStatus: {
|
|
1224
|
-
id: `${statusListCredential}#${args.revocationOptions.statusListIndex}`,
|
|
1225
|
-
type: 'StatusList2021Entry',
|
|
1226
|
-
statusPurpose: cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.revocation,
|
|
1227
|
-
statusListIndex: `${args.revocationOptions.statusListIndex}`,
|
|
1228
|
-
},
|
|
1229
|
-
issuanceDate: '',
|
|
1230
|
-
proof: {},
|
|
1231
|
-
};
|
|
1232
|
-
}
|
|
1233
|
-
// validate args - case: credential
|
|
1234
|
-
if (!args.credential)
|
|
1235
|
-
throw new Error('[did-provider-cheqd]: revocation: credential is required');
|
|
1236
|
-
// if jwt credential, decode it
|
|
1237
|
-
const credential = typeof args.credential === 'string' ? await Cheqd.decodeCredentialJWT(args.credential) : args.credential;
|
|
1238
|
-
// validate status purpose
|
|
1239
|
-
if (credential.credentialStatus?.statusPurpose !== cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.revocation) {
|
|
1240
|
-
throw new Error(`[did-provider-cheqd]: revocation: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
|
|
1241
|
-
}
|
|
1242
|
-
// validate args in pairs - case: statusListFile and statusList
|
|
1243
|
-
if (args.options?.statusListFile && args.options?.statusList) {
|
|
1244
|
-
throw new Error('[did-provider-cheqd]: revocation: statusListFile and statusList are mutually exclusive');
|
|
1245
|
-
}
|
|
1246
|
-
// validate args in pairs - case: statusListFile and fetchList
|
|
1247
|
-
if (args.options?.statusListFile && args.options?.fetchList) {
|
|
1248
|
-
throw new Error('[did-provider-cheqd]: revocation: statusListFile and fetchList are mutually exclusive');
|
|
1249
|
-
}
|
|
1250
|
-
// validate args in pairs - case: statusList and fetchList
|
|
1251
|
-
if (args.options?.statusList && args.options?.fetchList) {
|
|
1252
|
-
throw new Error('[did-provider-cheqd]: revocation: statusList and fetchList are mutually exclusive');
|
|
1253
|
-
}
|
|
1254
|
-
// validate args in pairs - case: publish
|
|
1255
|
-
if (args.options?.publish && !args.fetchList && !(args.options?.statusListFile || args.options?.statusList)) {
|
|
1256
|
-
throw new Error('[did-provider-cheqd]: revocation: publish requires statusListFile or statusList, if fetchList is disabled');
|
|
1257
|
-
}
|
|
1258
|
-
// define issuer
|
|
1259
|
-
const issuer = typeof credential.issuer === 'string' ? credential.issuer : credential.issuer.id;
|
|
1260
|
-
// define provider, if applicable
|
|
1261
|
-
this.didProvider = await Cheqd.getProviderFromDidUrl(issuer, this.supportedDidProviders);
|
|
1262
|
-
// define provider id, if applicable
|
|
1263
|
-
this.providerId = Cheqd.generateProviderId(issuer);
|
|
1264
|
-
// define dkg options, if provided
|
|
1265
|
-
args.dkgOptions ||= this.didProvider.dkgOptions;
|
|
1266
|
-
// revoke credential
|
|
1267
|
-
return await Cheqd.revokeCredential(credential, {
|
|
1268
|
-
...args.options,
|
|
1269
|
-
topArgs: args,
|
|
1270
|
-
publishOptions: {
|
|
1271
|
-
context,
|
|
1272
|
-
statusListEncoding: args?.options?.statusListEncoding,
|
|
1273
|
-
statusListValidUntil: args?.options?.statusListValidUntil,
|
|
1274
|
-
resourceId: args?.options?.resourceId,
|
|
1275
|
-
resourceVersion: args?.options?.resourceVersion,
|
|
1276
|
-
resourceAlsoKnownAs: args?.options?.alsoKnownAs,
|
|
1277
|
-
signInputs: args?.options?.signInputs,
|
|
1278
|
-
fee: args?.options?.fee,
|
|
1279
|
-
},
|
|
1280
|
-
});
|
|
1281
|
-
}
|
|
1282
|
-
async RevokeBulkCredentialsWithStatusList2021(args, context) {
|
|
1283
|
-
// verify credential, if provided and revocation options are not
|
|
1284
|
-
if (args?.credentials && !args?.revocationOptions) {
|
|
1285
|
-
const verificationResult = await Promise.all(args.credentials.map(async (credential) => {
|
|
1286
|
-
return await context.agent.verifyCredential({
|
|
1287
|
-
...args?.verificationOptions,
|
|
1288
|
-
credential,
|
|
1289
|
-
policies: {
|
|
1290
|
-
credentialStatus: false,
|
|
1291
|
-
},
|
|
1292
|
-
});
|
|
1293
|
-
}));
|
|
1294
|
-
// early return if verification failed for any credential
|
|
1295
|
-
if (verificationResult.some((result) => !result.verified)) {
|
|
1296
|
-
// define verified
|
|
1297
|
-
return {
|
|
1298
|
-
revoked: Array(args.credentials.length).fill(false),
|
|
1299
|
-
error: verificationResult.find((result) => !result.verified).error || {
|
|
1300
|
-
message: 'verification: could not verify credential',
|
|
1301
|
-
},
|
|
1302
|
-
};
|
|
1303
|
-
}
|
|
1304
|
-
}
|
|
1305
|
-
// if revocation options are provided, give precedence
|
|
1306
|
-
if (args?.revocationOptions) {
|
|
1307
|
-
// validate revocation options - case: revocationOptions.issuerDid
|
|
1308
|
-
if (!args.revocationOptions.issuerDid)
|
|
1309
|
-
throw new Error('[did-provider-cheqd]: revocation: revocationOptions.issuerDid is required');
|
|
1310
|
-
// validate revocation options - case: revocationOptions.statusListName
|
|
1311
|
-
if (!args.revocationOptions.statusListName)
|
|
1312
|
-
throw new Error('[did-provider-cheqd]: revocation: revocationOptions.statusListName is required');
|
|
1313
|
-
// validate revocation options - case: revocationOptions.statusListIndices
|
|
1314
|
-
if (!args.revocationOptions.statusListIndices ||
|
|
1315
|
-
!args.revocationOptions.statusListIndices.length ||
|
|
1316
|
-
args.revocationOptions.statusListIndices.length === 0 ||
|
|
1317
|
-
!args.revocationOptions.statusListIndices.every((index) => !isNaN(+index)))
|
|
1318
|
-
throw new Error('[did-provider-cheqd]: revocation: revocationOptions.statusListIndex is required and must be an array of indices');
|
|
1319
|
-
// construct status list credential
|
|
1320
|
-
const statusListCredential = `${cheqd_did_resolver_js_1.DefaultResolverUrl}${args.revocationOptions.issuerDid}?resourceName=${args.revocationOptions.statusListName}&resourceType=${cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes.revocation}`;
|
|
1321
|
-
// construct credential status
|
|
1322
|
-
args.credentials = args.revocationOptions.statusListIndices.map((index) => ({
|
|
1323
|
-
'@context': [],
|
|
1324
|
-
issuer: args.revocationOptions.issuerDid,
|
|
1325
|
-
credentialSubject: {},
|
|
1326
|
-
credentialStatus: {
|
|
1327
|
-
id: `${statusListCredential}#${index}`,
|
|
1328
|
-
type: 'StatusList2021Entry',
|
|
1329
|
-
statusPurpose: cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.revocation,
|
|
1330
|
-
statusListIndex: `${index}`,
|
|
1331
|
-
},
|
|
1332
|
-
issuanceDate: '',
|
|
1333
|
-
proof: {},
|
|
1334
|
-
}));
|
|
1335
|
-
}
|
|
1336
|
-
// validate args - case: credentials
|
|
1337
|
-
if (!args.credentials || !args.credentials.length || args.credentials.length === 0)
|
|
1338
|
-
throw new Error('[did-provider-cheqd]: revocation: credentials is required and must be an array of credentials');
|
|
1339
|
-
// if jwt credentials, decode them
|
|
1340
|
-
const credentials = await Promise.all(args.credentials.map(async (credential) => typeof credential === 'string' ? await Cheqd.decodeCredentialJWT(credential) : credential));
|
|
1341
|
-
// validate args in pairs - case: statusListFile and statusList
|
|
1342
|
-
if (args.options?.statusListFile && args.options?.statusList) {
|
|
1343
|
-
throw new Error('[did-provider-cheqd]: revocation: statusListFile and statusList are mutually exclusive');
|
|
1344
|
-
}
|
|
1345
|
-
// validate args in pairs - case: statusListFile and fetchList
|
|
1346
|
-
if (args.options?.statusListFile && args.options?.fetchList) {
|
|
1347
|
-
throw new Error('[did-provider-cheqd]: revocation: statusListFile and fetchList are mutually exclusive');
|
|
1348
|
-
}
|
|
1349
|
-
// validate args in pairs - case: statusList and fetchList
|
|
1350
|
-
if (args.options?.statusList && args.options?.fetchList) {
|
|
1351
|
-
throw new Error('[did-provider-cheqd]: revocation: statusList and fetchList are mutually exclusive');
|
|
1352
|
-
}
|
|
1353
|
-
// validate args in pairs - case: publish
|
|
1354
|
-
if (args.options?.publish && !args.fetchList && !(args.options?.statusListFile || args.options?.statusList)) {
|
|
1355
|
-
throw new Error('[did-provider-cheqd]: revocation: publish requires statusListFile or statusList, if fetchList is disabled');
|
|
1356
|
-
}
|
|
1357
|
-
// define issuer
|
|
1358
|
-
const issuer = typeof credentials[0].issuer === 'string'
|
|
1359
|
-
? credentials[0].issuer
|
|
1360
|
-
: credentials[0].issuer.id;
|
|
1361
|
-
// define provider, if applicable
|
|
1362
|
-
this.didProvider = await Cheqd.getProviderFromDidUrl(issuer, this.supportedDidProviders);
|
|
1363
|
-
// define provider id, if applicable
|
|
1364
|
-
this.providerId = Cheqd.generateProviderId(issuer);
|
|
1365
|
-
// define dkg options, if provided
|
|
1366
|
-
args.dkgOptions ||= this.didProvider.dkgOptions;
|
|
1367
|
-
// revoke credentials
|
|
1368
|
-
return await Cheqd.revokeCredentials(credentials, {
|
|
1369
|
-
...args.options,
|
|
1370
|
-
topArgs: args,
|
|
1371
|
-
publishOptions: {
|
|
1372
|
-
context,
|
|
1373
|
-
resourceId: args?.options?.resourceId,
|
|
1374
|
-
resourceVersion: args?.options?.resourceVersion,
|
|
1375
|
-
resourceAlsoKnownAs: args?.options?.alsoKnownAs,
|
|
1376
|
-
signInputs: args?.options?.signInputs,
|
|
1377
|
-
fee: args?.options?.fee,
|
|
1378
|
-
},
|
|
1379
|
-
});
|
|
1380
|
-
}
|
|
1381
|
-
async SuspendCredentialWithStatusList2021(args, context) {
|
|
1382
|
-
// verify credential, if provided and suspension options are not
|
|
1383
|
-
if (args?.credential && !args?.suspensionOptions) {
|
|
1384
|
-
const verificationResult = await context.agent.verifyCredential({
|
|
1385
|
-
...args?.verificationOptions,
|
|
1386
|
-
credential: args.credential,
|
|
1387
|
-
policies: {
|
|
1388
|
-
credentialStatus: false,
|
|
1389
|
-
},
|
|
1390
|
-
});
|
|
1391
|
-
// early return if verification failed
|
|
1392
|
-
if (!verificationResult.verified) {
|
|
1393
|
-
return { suspended: false, error: verificationResult.error };
|
|
1394
|
-
}
|
|
1395
|
-
}
|
|
1396
|
-
// if suspension options are provided, give precedence
|
|
1397
|
-
if (args?.suspensionOptions) {
|
|
1398
|
-
// validate suspension options - case: suspensionOptions.issuerDid
|
|
1399
|
-
if (!args.suspensionOptions.issuerDid)
|
|
1400
|
-
throw new Error('[did-provider-cheqd]: suspension: suspensionOptions.issuerDid is required');
|
|
1401
|
-
// validate suspension options - case: suspensionOptions.statusListName
|
|
1402
|
-
if (!args.suspensionOptions.statusListName)
|
|
1403
|
-
throw new Error('[did-provider-cheqd]: suspension: suspensionOptions.statusListName is required');
|
|
1404
|
-
// validate suspension options - case: suspensionOptions.statusListIndex
|
|
1405
|
-
if (!args.suspensionOptions.statusListIndex)
|
|
1406
|
-
throw new Error('[did-provider-cheqd]: suspension: suspensionOptions.statusListIndex is required');
|
|
1407
|
-
// construct status list credential
|
|
1408
|
-
const statusListCredential = `${cheqd_did_resolver_js_1.DefaultResolverUrl}${args.suspensionOptions.issuerDid}?resourceName=${args.suspensionOptions.statusListName}&resourceType=${cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes.suspension}`;
|
|
1409
|
-
// construct credential status
|
|
1410
|
-
args.credential = {
|
|
1411
|
-
'@context': [],
|
|
1412
|
-
issuer: args.suspensionOptions.issuerDid,
|
|
1413
|
-
credentialSubject: {},
|
|
1414
|
-
credentialStatus: {
|
|
1415
|
-
id: `${statusListCredential}#${args.suspensionOptions.statusListIndex}`,
|
|
1416
|
-
type: 'StatusList2021Entry',
|
|
1417
|
-
statusPurpose: cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension,
|
|
1418
|
-
statusListIndex: `${args.suspensionOptions.statusListIndex}`,
|
|
1419
|
-
},
|
|
1420
|
-
issuanceDate: '',
|
|
1421
|
-
proof: {},
|
|
1422
|
-
};
|
|
1423
|
-
}
|
|
1424
|
-
// validate args - case: credential
|
|
1425
|
-
if (!args.credential)
|
|
1426
|
-
throw new Error('[did-provider-cheqd]: suspension: credential is required');
|
|
1427
|
-
// if jwt credential, decode it
|
|
1428
|
-
const credential = typeof args.credential === 'string' ? await Cheqd.decodeCredentialJWT(args.credential) : args.credential;
|
|
1429
|
-
// validate status purpose
|
|
1430
|
-
if (credential.credentialStatus?.statusPurpose !== cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension) {
|
|
1431
|
-
throw new Error(`[did-provider-cheqd]: suspension: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
|
|
1432
|
-
}
|
|
1433
|
-
// validate args in pairs - case: statusListFile and statusList
|
|
1434
|
-
if (args.options?.statusListFile && args.options?.statusList) {
|
|
1435
|
-
throw new Error('[did-provider-cheqd]: suspension: statusListFile and statusList are mutually exclusive');
|
|
1436
|
-
}
|
|
1437
|
-
// validate args in pairs - case: statusListFile and fetchList
|
|
1438
|
-
if (args.options?.statusListFile && args.options?.fetchList) {
|
|
1439
|
-
throw new Error('[did-provider-cheqd]: suspension: statusListFile and fetchList are mutually exclusive');
|
|
1440
|
-
}
|
|
1441
|
-
// validate args in pairs - case: statusList and fetchList
|
|
1442
|
-
if (args.options?.statusList && args.options?.fetchList) {
|
|
1443
|
-
throw new Error('[did-provider-cheqd]: suspension: statusList and fetchList are mutually exclusive');
|
|
1444
|
-
}
|
|
1445
|
-
// validate args in pairs - case: publish
|
|
1446
|
-
if (args.options?.publish && !args.fetchList && !(args.options?.statusListFile || args.options?.statusList)) {
|
|
1447
|
-
throw new Error('[did-provider-cheqd]: suspension: publish requires statusListFile or statusList, if fetchList is disabled');
|
|
1448
|
-
}
|
|
1449
|
-
// define issuer
|
|
1450
|
-
const issuer = typeof credential.issuer === 'string' ? credential.issuer : credential.issuer.id;
|
|
1451
|
-
// define provider, if applicable
|
|
1452
|
-
this.didProvider = await Cheqd.getProviderFromDidUrl(issuer, this.supportedDidProviders);
|
|
1453
|
-
// define provider id, if applicable
|
|
1454
|
-
this.providerId = Cheqd.generateProviderId(issuer);
|
|
1455
|
-
// define dkg options, if provided
|
|
1456
|
-
args.dkgOptions ||= this.didProvider.dkgOptions;
|
|
1457
|
-
// suspend credential
|
|
1458
|
-
return await Cheqd.suspendCredential(credential, {
|
|
1459
|
-
...args.options,
|
|
1460
|
-
topArgs: args,
|
|
1461
|
-
publishOptions: {
|
|
1462
|
-
context,
|
|
1463
|
-
statusListEncoding: args?.options?.statusListEncoding,
|
|
1464
|
-
statusListValidUntil: args?.options?.statusListValidUntil,
|
|
1465
|
-
resourceId: args?.options?.resourceId,
|
|
1466
|
-
resourceVersion: args?.options?.resourceVersion,
|
|
1467
|
-
resourceAlsoKnownAs: args?.options?.alsoKnownAs,
|
|
1468
|
-
signInputs: args?.options?.signInputs,
|
|
1469
|
-
fee: args?.options?.fee,
|
|
1470
|
-
},
|
|
1471
|
-
});
|
|
1472
|
-
}
|
|
1473
|
-
async SuspendBulkCredentialsWithStatusList2021(args, context) {
|
|
1474
|
-
// verify credential, if provided and suspension options are not
|
|
1475
|
-
if (args?.credentials && !args?.suspensionOptions) {
|
|
1476
|
-
const verificationResult = await Promise.all(args.credentials.map(async (credential) => {
|
|
1477
|
-
return await context.agent.verifyCredential({
|
|
1478
|
-
...args?.verificationOptions,
|
|
1479
|
-
credential,
|
|
1480
|
-
policies: {
|
|
1481
|
-
credentialStatus: false,
|
|
1482
|
-
},
|
|
1483
|
-
});
|
|
1484
|
-
}));
|
|
1485
|
-
// early return if verification failed for any credential
|
|
1486
|
-
if (verificationResult.some((result) => !result.verified)) {
|
|
1487
|
-
// define verified
|
|
1488
|
-
return {
|
|
1489
|
-
suspended: Array(args.credentials.length).fill(false),
|
|
1490
|
-
error: verificationResult.find((result) => !result.verified).error || {
|
|
1491
|
-
message: 'verification: could not verify credential',
|
|
1492
|
-
},
|
|
1493
|
-
};
|
|
1494
|
-
}
|
|
1495
|
-
}
|
|
1496
|
-
// if suspension options are provided, give precedence
|
|
1497
|
-
if (args?.suspensionOptions) {
|
|
1498
|
-
// validate suspension options - case: suspensionOptions.issuerDid
|
|
1499
|
-
if (!args.suspensionOptions.issuerDid)
|
|
1500
|
-
throw new Error('[did-provider-cheqd]: suspension: suspensionOptions.issuerDid is required');
|
|
1501
|
-
// validate suspension options - case: suspensionOptions.statusListName
|
|
1502
|
-
if (!args.suspensionOptions.statusListName)
|
|
1503
|
-
throw new Error('[did-provider-cheqd]: suspension: suspensionOptions.statusListName is required');
|
|
1504
|
-
// validate suspension options - case: suspensionOptions.statusListIndices
|
|
1505
|
-
if (!args.suspensionOptions.statusListIndices ||
|
|
1506
|
-
!args.suspensionOptions.statusListIndices.length ||
|
|
1507
|
-
args.suspensionOptions.statusListIndices.length === 0 ||
|
|
1508
|
-
!args.suspensionOptions.statusListIndices.every((index) => !isNaN(+index)))
|
|
1509
|
-
throw new Error('[did-provider-cheqd]: suspension: suspensionOptions.statusListIndex is required and must be an array of indices');
|
|
1510
|
-
// construct status list credential
|
|
1511
|
-
const statusListCredential = `${cheqd_did_resolver_js_1.DefaultResolverUrl}${args.suspensionOptions.issuerDid}?resourceName=${args.suspensionOptions.statusListName}&resourceType=${cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes.suspension}`;
|
|
1512
|
-
// construct credential status
|
|
1513
|
-
args.credentials = args.suspensionOptions.statusListIndices.map((index) => ({
|
|
1514
|
-
'@context': [],
|
|
1515
|
-
issuer: args.suspensionOptions.issuerDid,
|
|
1516
|
-
credentialSubject: {},
|
|
1517
|
-
credentialStatus: {
|
|
1518
|
-
id: `${statusListCredential}#${index}`,
|
|
1519
|
-
type: 'StatusList2021Entry',
|
|
1520
|
-
statusPurpose: cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension,
|
|
1521
|
-
statusListIndex: `${index}`,
|
|
1522
|
-
},
|
|
1523
|
-
issuanceDate: '',
|
|
1524
|
-
proof: {},
|
|
1525
|
-
}));
|
|
1526
|
-
}
|
|
1527
|
-
// validate args - case: credentials
|
|
1528
|
-
if (!args.credentials || !args.credentials.length || args.credentials.length === 0)
|
|
1529
|
-
throw new Error('[did-provider-cheqd]: suspension: credentials is required and must be an array of credentials');
|
|
1530
|
-
// if jwt credentials, decode them
|
|
1531
|
-
const credentials = await Promise.all(args.credentials.map(async (credential) => typeof credential === 'string' ? await Cheqd.decodeCredentialJWT(credential) : credential));
|
|
1532
|
-
// validate args in pairs - case: statusListFile and statusList
|
|
1533
|
-
if (args.options?.statusListFile && args.options?.statusList) {
|
|
1534
|
-
throw new Error('[did-provider-cheqd]: suspension: statusListFile and statusList are mutually exclusive');
|
|
1535
|
-
}
|
|
1536
|
-
// validate args in pairs - case: statusListFile and fetchList
|
|
1537
|
-
if (args.options?.statusListFile && args.options?.fetchList) {
|
|
1538
|
-
throw new Error('[did-provider-cheqd]: suspension: statusListFile and fetchList are mutually exclusive');
|
|
1539
|
-
}
|
|
1540
|
-
// validate args in pairs - case: statusList and fetchList
|
|
1541
|
-
if (args.options?.statusList && args.options?.fetchList) {
|
|
1542
|
-
throw new Error('[did-provider-cheqd]: suspension: statusList and fetchList are mutually exclusive');
|
|
1543
|
-
}
|
|
1544
|
-
// validate args in pairs - case: publish
|
|
1545
|
-
if (args.options?.publish && !args.fetchList && !(args.options?.statusListFile || args.options?.statusList)) {
|
|
1546
|
-
throw new Error('[did-provider-cheqd]: suspension: publish requires statusListFile or statusList, if fetchList is disabled');
|
|
1547
|
-
}
|
|
1548
|
-
// define issuer
|
|
1549
|
-
const issuer = typeof credentials[0].issuer === 'string'
|
|
1550
|
-
? credentials[0].issuer
|
|
1551
|
-
: credentials[0].issuer.id;
|
|
1552
|
-
// define provider, if applicable
|
|
1553
|
-
this.didProvider = await Cheqd.getProviderFromDidUrl(issuer, this.supportedDidProviders);
|
|
1554
|
-
// define provider id, if applicable
|
|
1555
|
-
this.providerId = Cheqd.generateProviderId(issuer);
|
|
1556
|
-
// define dkg options, if provided
|
|
1557
|
-
args.dkgOptions ||= this.didProvider.dkgOptions;
|
|
1558
|
-
// suspend credentials
|
|
1559
|
-
return await Cheqd.suspendCredentials(credentials, {
|
|
1560
|
-
...args.options,
|
|
1561
|
-
topArgs: args,
|
|
1562
|
-
publishOptions: {
|
|
1563
|
-
context,
|
|
1564
|
-
resourceId: args?.options?.resourceId,
|
|
1565
|
-
resourceVersion: args?.options?.resourceVersion,
|
|
1566
|
-
resourceAlsoKnownAs: args?.options?.alsoKnownAs,
|
|
1567
|
-
signInputs: args?.options?.signInputs,
|
|
1568
|
-
fee: args?.options?.fee,
|
|
1569
|
-
},
|
|
1570
|
-
});
|
|
1571
|
-
}
|
|
1572
|
-
async UnsuspendCredentialWithStatusList2021(args, context) {
|
|
1573
|
-
// verify credential, if provided and unsuspension options are not
|
|
1574
|
-
if (args?.credential && !args?.unsuspensionOptions) {
|
|
1575
|
-
const verificationResult = await context.agent.verifyCredential({
|
|
1576
|
-
...args?.verificationOptions,
|
|
1577
|
-
credential: args.credential,
|
|
1578
|
-
policies: {
|
|
1579
|
-
credentialStatus: false,
|
|
1580
|
-
},
|
|
1581
|
-
});
|
|
1582
|
-
// early return if verification failed
|
|
1583
|
-
if (!verificationResult.verified) {
|
|
1584
|
-
return { unsuspended: false, error: verificationResult.error };
|
|
1585
|
-
}
|
|
1586
|
-
}
|
|
1587
|
-
// if unsuspension options are provided, give precedence
|
|
1588
|
-
if (args?.unsuspensionOptions) {
|
|
1589
|
-
// validate unsuspension options - case: unsuspensionOptions.issuerDid
|
|
1590
|
-
if (!args.unsuspensionOptions.issuerDid)
|
|
1591
|
-
throw new Error('[did-provider-cheqd]: unsuspension: unsuspensionOptions.issuerDid is required');
|
|
1592
|
-
// validate unsuspension options - case: unsuspensionOptions.statusListName
|
|
1593
|
-
if (!args.unsuspensionOptions.statusListName)
|
|
1594
|
-
throw new Error('[did-provider-cheqd]: unsuspension: unsuspensionOptions.statusListName is required');
|
|
1595
|
-
// validate unsuspension options - case: unsuspensionOptions.statusListIndex
|
|
1596
|
-
if (!args.unsuspensionOptions.statusListIndex)
|
|
1597
|
-
throw new Error('[did-provider-cheqd]: unsuspension: unsuspensionOptions.statusListIndex is required');
|
|
1598
|
-
// construct status list credential
|
|
1599
|
-
const statusListCredential = `${cheqd_did_resolver_js_1.DefaultResolverUrl}${args.unsuspensionOptions.issuerDid}?resourceName=${args.unsuspensionOptions.statusListName}&resourceType=${cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes.suspension}`;
|
|
1600
|
-
// construct credential status
|
|
1601
|
-
args.credential = {
|
|
1602
|
-
'@context': [],
|
|
1603
|
-
issuer: args.unsuspensionOptions.issuerDid,
|
|
1604
|
-
credentialSubject: {},
|
|
1605
|
-
credentialStatus: {
|
|
1606
|
-
id: `${statusListCredential}#${args.unsuspensionOptions.statusListIndex}`,
|
|
1607
|
-
type: 'StatusList2021Entry',
|
|
1608
|
-
statusPurpose: cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension,
|
|
1609
|
-
statusListIndex: `${args.unsuspensionOptions.statusListIndex}`,
|
|
1610
|
-
},
|
|
1611
|
-
issuanceDate: '',
|
|
1612
|
-
proof: {},
|
|
1613
|
-
};
|
|
1614
|
-
}
|
|
1615
|
-
// validate args - case: credential
|
|
1616
|
-
if (!args.credential)
|
|
1617
|
-
throw new Error('[did-provider-cheqd]: unsuspension: credential is required');
|
|
1618
|
-
// if jwt credential, decode it
|
|
1619
|
-
const credential = typeof args.credential === 'string' ? await Cheqd.decodeCredentialJWT(args.credential) : args.credential;
|
|
1620
|
-
// validate status purpose
|
|
1621
|
-
if (credential.credentialStatus?.statusPurpose !== cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension) {
|
|
1622
|
-
throw new Error(`[did-provider-cheqd]: suspension: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
|
|
1623
|
-
}
|
|
1624
|
-
// validate args in pairs - case: statusListFile and statusList
|
|
1625
|
-
if (args.options?.statusListFile && args.options?.statusList) {
|
|
1626
|
-
throw new Error('[did-provider-cheqd]: suspension: statusListFile and statusList are mutually exclusive');
|
|
1627
|
-
}
|
|
1628
|
-
// validate args in pairs - case: statusListFile and fetchList
|
|
1629
|
-
if (args.options?.statusListFile && args.options?.fetchList) {
|
|
1630
|
-
throw new Error('[did-provider-cheqd]: suspension: statusListFile and fetchList are mutually exclusive');
|
|
1631
|
-
}
|
|
1632
|
-
// validate args in pairs - case: statusList and fetchList
|
|
1633
|
-
if (args.options?.statusList && args.options?.fetchList) {
|
|
1634
|
-
throw new Error('[did-provider-cheqd]: suspension: statusList and fetchList are mutually exclusive');
|
|
1635
|
-
}
|
|
1636
|
-
// validate args in pairs - case: publish
|
|
1637
|
-
if (args.options?.publish && !args.fetchList && !(args.options?.statusListFile || args.options?.statusList)) {
|
|
1638
|
-
throw new Error('[did-provider-cheqd]: suspension: publish requires statusListFile or statusList, if fetchList is disabled');
|
|
1639
|
-
}
|
|
1640
|
-
// define issuer
|
|
1641
|
-
const issuer = typeof credential.issuer === 'string' ? credential.issuer : credential.issuer.id;
|
|
1642
|
-
// define provider, if applicable
|
|
1643
|
-
this.didProvider = await Cheqd.getProviderFromDidUrl(issuer, this.supportedDidProviders);
|
|
1644
|
-
// define provider id, if applicable
|
|
1645
|
-
this.providerId = Cheqd.generateProviderId(issuer);
|
|
1646
|
-
// define dkg options, if provided
|
|
1647
|
-
args.dkgOptions ||= this.didProvider.dkgOptions;
|
|
1648
|
-
// suspend credential
|
|
1649
|
-
return await Cheqd.unsuspendCredential(credential, {
|
|
1650
|
-
...args.options,
|
|
1651
|
-
topArgs: args,
|
|
1652
|
-
publishOptions: {
|
|
1653
|
-
context,
|
|
1654
|
-
statusListEncoding: args?.options?.statusListEncoding,
|
|
1655
|
-
statusListValidUntil: args?.options?.statusListValidUntil,
|
|
1656
|
-
resourceId: args?.options?.resourceId,
|
|
1657
|
-
resourceVersion: args?.options?.resourceVersion,
|
|
1658
|
-
resourceAlsoKnownAs: args?.options?.alsoKnownAs,
|
|
1659
|
-
signInputs: args?.options?.signInputs,
|
|
1660
|
-
fee: args?.options?.fee,
|
|
1661
|
-
},
|
|
1662
|
-
});
|
|
1663
|
-
}
|
|
1664
|
-
async UnsuspendBulkCredentialsWithStatusList2021(args, context) {
|
|
1665
|
-
// verify credential, if provided and unsuspension options are not
|
|
1666
|
-
if (args?.credentials && !args?.unsuspensionOptions) {
|
|
1667
|
-
const verificationResult = await Promise.all(args.credentials.map(async (credential) => {
|
|
1668
|
-
return await context.agent.verifyCredential({
|
|
1669
|
-
...args?.verificationOptions,
|
|
1670
|
-
credential,
|
|
1671
|
-
policies: {
|
|
1672
|
-
credentialStatus: false,
|
|
1673
|
-
},
|
|
1674
|
-
});
|
|
1675
|
-
}));
|
|
1676
|
-
// early return if verification failed for any credential
|
|
1677
|
-
if (verificationResult.some((result) => !result.verified)) {
|
|
1678
|
-
// define verified
|
|
1679
|
-
return {
|
|
1680
|
-
unsuspended: Array(args.credentials.length).fill(false),
|
|
1681
|
-
error: verificationResult.find((result) => !result.verified).error || {
|
|
1682
|
-
message: 'verification: could not verify credential',
|
|
1683
|
-
},
|
|
1684
|
-
};
|
|
1685
|
-
}
|
|
1686
|
-
}
|
|
1687
|
-
// if unsuspension options are provided, give precedence
|
|
1688
|
-
if (args?.unsuspensionOptions) {
|
|
1689
|
-
// validate unsuspension options - case: unsuspensionOptions.issuerDid
|
|
1690
|
-
if (!args.unsuspensionOptions.issuerDid)
|
|
1691
|
-
throw new Error('[did-provider-cheqd]: unsuspension: unsuspensionOptions.issuerDid is required');
|
|
1692
|
-
// validate unsuspension options - case: unsuspensionOptions.statusListName
|
|
1693
|
-
if (!args.unsuspensionOptions.statusListName)
|
|
1694
|
-
throw new Error('[did-provider-cheqd]: unsuspension: unsuspensionOptions.statusListName is required');
|
|
1695
|
-
// validate unsuspension options - case: unsuspensionOptions.statusListIndices
|
|
1696
|
-
if (!args.unsuspensionOptions.statusListIndices ||
|
|
1697
|
-
!args.unsuspensionOptions.statusListIndices.length ||
|
|
1698
|
-
args.unsuspensionOptions.statusListIndices.length === 0 ||
|
|
1699
|
-
!args.unsuspensionOptions.statusListIndices.every((index) => !isNaN(+index)))
|
|
1700
|
-
throw new Error('[did-provider-cheqd]: unsuspension: unsuspensionOptions.statusListIndex is required and must be an array of indices');
|
|
1701
|
-
// construct status list credential
|
|
1702
|
-
const statusListCredential = `${cheqd_did_resolver_js_1.DefaultResolverUrl}${args.unsuspensionOptions.issuerDid}?resourceName=${args.unsuspensionOptions.statusListName}&resourceType=${cheqd_did_provider_js_1.DefaultStatusList2021ResourceTypes.suspension}`;
|
|
1703
|
-
// construct credential status
|
|
1704
|
-
args.credentials = args.unsuspensionOptions.statusListIndices.map((index) => ({
|
|
1705
|
-
'@context': [],
|
|
1706
|
-
issuer: args.unsuspensionOptions.issuerDid,
|
|
1707
|
-
credentialSubject: {},
|
|
1708
|
-
credentialStatus: {
|
|
1709
|
-
id: `${statusListCredential}#${index}`,
|
|
1710
|
-
type: 'StatusList2021Entry',
|
|
1711
|
-
statusPurpose: cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension,
|
|
1712
|
-
statusListIndex: `${index}`,
|
|
1713
|
-
},
|
|
1714
|
-
issuanceDate: '',
|
|
1715
|
-
proof: {},
|
|
1716
|
-
}));
|
|
1717
|
-
}
|
|
1718
|
-
// validate args - case: credentials
|
|
1719
|
-
if (!args.credentials || !args.credentials.length || args.credentials.length === 0)
|
|
1720
|
-
throw new Error('[did-provider-cheqd]: unsuspension: credentials is required and must be an array of credentials');
|
|
1721
|
-
// if jwt credentials, decode them
|
|
1722
|
-
const credentials = await Promise.all(args.credentials.map(async (credential) => typeof credential === 'string' ? await Cheqd.decodeCredentialJWT(credential) : credential));
|
|
1723
|
-
// validate args in pairs - case: statusListFile and statusList
|
|
1724
|
-
if (args.options?.statusListFile && args.options?.statusList) {
|
|
1725
|
-
throw new Error('[did-provider-cheqd]: unsuspension: statusListFile and statusList are mutually exclusive');
|
|
1726
|
-
}
|
|
1727
|
-
// validate args in pairs - case: statusListFile and fetchList
|
|
1728
|
-
if (args.options?.statusListFile && args.options?.fetchList) {
|
|
1729
|
-
throw new Error('[did-provider-cheqd]: unsuspension: statusListFile and fetchList are mutually exclusive');
|
|
1730
|
-
}
|
|
1731
|
-
// validate args in pairs - case: statusList and fetchList
|
|
1732
|
-
if (args.options?.statusList && args.options?.fetchList) {
|
|
1733
|
-
throw new Error('[did-provider-cheqd]: unsuspension: statusList and fetchList are mutually exclusive');
|
|
1734
|
-
}
|
|
1735
|
-
// validate args in pairs - case: publish
|
|
1736
|
-
if (args.options?.publish && !args.fetchList && !(args.options?.statusListFile || args.options?.statusList)) {
|
|
1737
|
-
throw new Error('[did-provider-cheqd]: unsuspension: publish requires statusListFile or statusList, if fetchList is disabled');
|
|
1738
|
-
}
|
|
1739
|
-
// define issuer
|
|
1740
|
-
const issuer = typeof credentials[0].issuer === 'string'
|
|
1741
|
-
? credentials[0].issuer
|
|
1742
|
-
: credentials[0].issuer.id;
|
|
1743
|
-
// define provider, if applicable
|
|
1744
|
-
this.didProvider = await Cheqd.getProviderFromDidUrl(issuer, this.supportedDidProviders);
|
|
1745
|
-
// define provider id, if applicable
|
|
1746
|
-
this.providerId = Cheqd.generateProviderId(issuer);
|
|
1747
|
-
// define dkg options, if provided
|
|
1748
|
-
args.dkgOptions ||= this.didProvider.dkgOptions;
|
|
1749
|
-
// suspend credentials
|
|
1750
|
-
return await Cheqd.unsuspendCredentials(credentials, {
|
|
1751
|
-
...args.options,
|
|
1752
|
-
topArgs: args,
|
|
1753
|
-
publishOptions: {
|
|
1754
|
-
context,
|
|
1755
|
-
resourceId: args?.options?.resourceId,
|
|
1756
|
-
resourceVersion: args?.options?.resourceVersion,
|
|
1757
|
-
resourceAlsoKnownAs: args?.options?.alsoKnownAs,
|
|
1758
|
-
signInputs: args?.options?.signInputs,
|
|
1759
|
-
fee: args?.options?.fee,
|
|
1760
|
-
},
|
|
1761
|
-
});
|
|
1762
|
-
}
|
|
1763
|
-
async TransactSendTokens(args, context) {
|
|
1764
|
-
// define provider
|
|
1765
|
-
const provider = await Cheqd.getProviderFromNetwork(args.network, this.supportedDidProviders);
|
|
1766
|
-
try {
|
|
1767
|
-
// delegate to provider
|
|
1768
|
-
const transactionResult = await provider.transactSendTokens({
|
|
1769
|
-
recipientAddress: args.recipientAddress,
|
|
1770
|
-
amount: args.amount,
|
|
1771
|
-
memo: args.memo,
|
|
1772
|
-
txBytes: args.txBytes,
|
|
1773
|
-
});
|
|
1774
|
-
// return transaction result
|
|
1775
|
-
return {
|
|
1776
|
-
successful: !transactionResult.code,
|
|
1777
|
-
transactionHash: transactionResult.transactionHash,
|
|
1778
|
-
events: transactionResult.events,
|
|
1779
|
-
rawLog: transactionResult.rawLog,
|
|
1780
|
-
txResponse: args?.returnTxResponse ? transactionResult : undefined,
|
|
1781
|
-
};
|
|
1782
|
-
}
|
|
1783
|
-
catch (error) {
|
|
1784
|
-
// return error
|
|
1785
|
-
return {
|
|
1786
|
-
successful: false,
|
|
1787
|
-
error: error,
|
|
1788
|
-
};
|
|
1789
|
-
}
|
|
1790
|
-
}
|
|
1791
|
-
async ObservePaymentCondition(args, context) {
|
|
1792
|
-
// verify with raw unified access control condition, if any
|
|
1793
|
-
if (args?.unifiedAccessControlCondition) {
|
|
1794
|
-
// validate args - case: unifiedAccessControlCondition.chain
|
|
1795
|
-
if (!args.unifiedAccessControlCondition.chain ||
|
|
1796
|
-
!Object.values(v6_js_1.LitCompatibleCosmosChains).includes(args.unifiedAccessControlCondition.chain))
|
|
1797
|
-
throw new Error('[did-provider-cheqd]: observe: unifiedAccessControlCondition.chain is required and must be a valid Lit-compatible chain');
|
|
1798
|
-
// validate args - case: unifiedAccessControlCondition.path
|
|
1799
|
-
if (!args.unifiedAccessControlCondition.path)
|
|
1800
|
-
throw new Error('[did-provider-cheqd]: observe: unifiedAccessControlCondition.path is required');
|
|
1801
|
-
// validate args - case: unifiedAccessControlCondition.conditionType
|
|
1802
|
-
if (args.unifiedAccessControlCondition.conditionType !== 'cosmos')
|
|
1803
|
-
throw new Error('[did-provider-cheqd]: observe: unifiedAccessControlCondition.conditionType must be cosmos');
|
|
1804
|
-
// validate args - case: unifiedAccessControlCondition.method
|
|
1805
|
-
if (args.unifiedAccessControlCondition.method !== 'timelock')
|
|
1806
|
-
throw new Error('[did-provider-cheqd]: observe: unifiedAccessControlCondition.method must be timelock');
|
|
1807
|
-
// validate args - case: unifiedAccessControlCondition.parameters
|
|
1808
|
-
if (!args.unifiedAccessControlCondition.parameters ||
|
|
1809
|
-
!Array.isArray(args.unifiedAccessControlCondition.parameters) ||
|
|
1810
|
-
args.unifiedAccessControlCondition.parameters.length === 0 ||
|
|
1811
|
-
args.unifiedAccessControlCondition.parameters.length > 1)
|
|
1812
|
-
throw new Error('[did-provider-cheqd]: observe: unifiedAccessControlCondition.parameters is required and must be an array of length 1 of type string content');
|
|
1813
|
-
// validate args - case: unifiedAccessControlCondition.returnValueTest
|
|
1814
|
-
if (!args.unifiedAccessControlCondition.returnValueTest ||
|
|
1815
|
-
!args.unifiedAccessControlCondition.returnValueTest.comparator ||
|
|
1816
|
-
!args.unifiedAccessControlCondition.returnValueTest.key ||
|
|
1817
|
-
!args.unifiedAccessControlCondition.returnValueTest.value)
|
|
1818
|
-
throw new Error('[did-provider-cheqd]: observe: unifiedAccessControlCondition.returnValueTest is required');
|
|
1819
|
-
try {
|
|
1820
|
-
// define network
|
|
1821
|
-
const network = (function () {
|
|
1822
|
-
switch (args.unifiedAccessControlCondition.chain) {
|
|
1823
|
-
case v6_js_1.LitCompatibleCosmosChains.cheqdMainnet:
|
|
1824
|
-
return sdk_1.CheqdNetwork.Mainnet;
|
|
1825
|
-
case v6_js_1.LitCompatibleCosmosChains.cheqdTestnet:
|
|
1826
|
-
return sdk_1.CheqdNetwork.Testnet;
|
|
1827
|
-
default:
|
|
1828
|
-
throw new Error(`[did-provider-cheqd]: observe: Unsupported chain: ${args.unifiedAccessControlCondition.chain}`);
|
|
1829
|
-
}
|
|
1830
|
-
})();
|
|
1831
|
-
// get block height url
|
|
1832
|
-
const blockHeightUrl = (function () {
|
|
1833
|
-
switch (args.unifiedAccessControlCondition.parameters[0]) {
|
|
1834
|
-
case 'latest':
|
|
1835
|
-
return `${cheqd_did_provider_js_1.DefaultRESTUrls[network]}/cosmos/base/tendermint/v1beta1/blocks/latest`;
|
|
1836
|
-
default:
|
|
1837
|
-
return `${cheqd_did_provider_js_1.DefaultRESTUrls[network]}/cosmos/base/tendermint/v1beta1/blocks/${args.unifiedAccessControlCondition.parameters[0]}`;
|
|
1838
|
-
}
|
|
1839
|
-
})();
|
|
1840
|
-
// fetch block response
|
|
1841
|
-
const blockHeightResponse = (await (await fetch(blockHeightUrl)).json());
|
|
1842
|
-
// get timestamp from block response
|
|
1843
|
-
const blockTimestamp = Date.parse(blockHeightResponse.block.header.time);
|
|
1844
|
-
// construct url
|
|
1845
|
-
const url = `${cheqd_did_provider_js_1.DefaultRESTUrls[network]}${args.unifiedAccessControlCondition.path}`;
|
|
1846
|
-
// fetch relevant txs
|
|
1847
|
-
const txs = (await (await fetch(url)).json());
|
|
1848
|
-
// skim through txs for relevant events, in which case the transaction timestamp is within the defined interval in seconds, from the block timestamp
|
|
1849
|
-
const meetsConditionTxIndex = txs?.tx_responses?.findIndex((tx) => {
|
|
1850
|
-
// get tx timestamp
|
|
1851
|
-
const txTimestamp = Date.parse(tx.timestamp);
|
|
1852
|
-
// calculate diff in seconds
|
|
1853
|
-
const diffInSeconds = Math.floor((blockTimestamp - txTimestamp) / 1000);
|
|
1854
|
-
// return meets condition
|
|
1855
|
-
switch (args.unifiedAccessControlCondition.returnValueTest.comparator) {
|
|
1856
|
-
case '<':
|
|
1857
|
-
return diffInSeconds < parseInt(args.unifiedAccessControlCondition.returnValueTest.value);
|
|
1858
|
-
case '<=':
|
|
1859
|
-
return diffInSeconds <= parseInt(args.unifiedAccessControlCondition.returnValueTest.value);
|
|
1860
|
-
default:
|
|
1861
|
-
throw new Error(`[did-provider-cheqd]: observe: Unsupported comparator: ${args.unifiedAccessControlCondition.returnValueTest.comparator}`);
|
|
1862
|
-
}
|
|
1863
|
-
});
|
|
1864
|
-
// define meetsCondition
|
|
1865
|
-
const meetsCondition = typeof meetsConditionTxIndex !== 'undefined' && meetsConditionTxIndex !== -1;
|
|
1866
|
-
// return observation result
|
|
1867
|
-
return {
|
|
1868
|
-
subscribed: true,
|
|
1869
|
-
meetsCondition: meetsCondition,
|
|
1870
|
-
transactionHash: meetsCondition ? txs.tx_responses[meetsConditionTxIndex].txhash : undefined,
|
|
1871
|
-
events: meetsCondition ? txs.tx_responses[meetsConditionTxIndex].events : undefined,
|
|
1872
|
-
rawLog: meetsCondition ? txs.tx_responses[meetsConditionTxIndex].raw_log : undefined,
|
|
1873
|
-
txResponse: meetsCondition
|
|
1874
|
-
? args?.returnTxResponse
|
|
1875
|
-
? txs.tx_responses[meetsConditionTxIndex]
|
|
1876
|
-
: undefined
|
|
1877
|
-
: undefined,
|
|
1878
|
-
};
|
|
1879
|
-
}
|
|
1880
|
-
catch (error) {
|
|
1881
|
-
// return error
|
|
1882
|
-
return {
|
|
1883
|
-
subscribed: false,
|
|
1884
|
-
meetsCondition: false,
|
|
1885
|
-
error: error,
|
|
1886
|
-
};
|
|
1887
|
-
}
|
|
1888
|
-
}
|
|
1889
|
-
// validate access control conditions components - case: recipientAddress
|
|
1890
|
-
if (!args.recipientAddress) {
|
|
1891
|
-
throw new Error('[did-provider-cheqd]: observation: recipientAddress is required');
|
|
1892
|
-
}
|
|
1893
|
-
// validate access control conditions components - case: amount
|
|
1894
|
-
if (!args.amount || !args.amount.amount || !args.amount.denom || args.amount.denom !== 'ncheq') {
|
|
1895
|
-
throw new Error('[did-provider-cheqd]: observation: amount is required, and must be an object with amount and denom valid string properties, amongst which denom must be `ncheq`');
|
|
1896
|
-
}
|
|
1897
|
-
// validate access control conditions components - case: intervalInSeconds
|
|
1898
|
-
if (!args.intervalInSeconds) {
|
|
1899
|
-
throw new Error('[did-provider-cheqd]: observation: intervalInSeconds is required');
|
|
1900
|
-
}
|
|
1901
|
-
// validate access control conditions components - case: comparator
|
|
1902
|
-
if (!args.comparator || (args.comparator !== '<' && args.comparator !== '<=')) {
|
|
1903
|
-
throw new Error('[did-provider-cheqd]: observation: comparator is required and must be either `<` or `<=`');
|
|
1904
|
-
}
|
|
1905
|
-
// validate access control conditions components - case: network
|
|
1906
|
-
if (!args.network) {
|
|
1907
|
-
throw new Error('[did-provider-cheqd]: observation: network is required');
|
|
1908
|
-
}
|
|
1909
|
-
// define block height, if not provided
|
|
1910
|
-
args.blockHeight ||= 'latest';
|
|
1911
|
-
try {
|
|
1912
|
-
// get block height url
|
|
1913
|
-
const blockHeightUrl = (function () {
|
|
1914
|
-
switch (args.blockHeight) {
|
|
1915
|
-
case 'latest':
|
|
1916
|
-
return `${cheqd_did_provider_js_1.DefaultRESTUrls[args.network]}/cosmos/base/tendermint/v1beta1/blocks/latest`;
|
|
1917
|
-
default:
|
|
1918
|
-
return `${cheqd_did_provider_js_1.DefaultRESTUrls[args.network]}/cosmos/base/tendermint/v1beta1/blocks/${args.blockHeight}`;
|
|
1919
|
-
}
|
|
1920
|
-
})();
|
|
1921
|
-
// fetch block response
|
|
1922
|
-
const blockHeightResponse = (await (await fetch(blockHeightUrl)).json());
|
|
1923
|
-
// get timestamp from block response
|
|
1924
|
-
const blockTimestamp = Date.parse(blockHeightResponse.block.header.time);
|
|
1925
|
-
// otherwise, construct url, as per components
|
|
1926
|
-
const url = `${cheqd_did_provider_js_1.DefaultRESTUrls[args.network]}/cosmos/tx/v1beta1/txs?events=transfer.recipient='${args.recipientAddress}'&events=transfer.amount='${args.amount.amount}${args.amount.denom}'&order_by=2&pagination.limit=1`;
|
|
1927
|
-
// fetch relevant txs
|
|
1928
|
-
const txs = (await (await fetch(url)).json());
|
|
1929
|
-
// skim through txs for relevant events, in which case the transaction timestamp is within the defined interval in seconds, from the block timestamp
|
|
1930
|
-
const meetsConditionTxIndex = txs?.tx_responses?.findIndex((tx) => {
|
|
1931
|
-
// get tx timestamp
|
|
1932
|
-
const txTimestamp = Date.parse(tx.timestamp);
|
|
1933
|
-
// calculate diff in seconds
|
|
1934
|
-
const diffInSeconds = Math.floor((blockTimestamp - txTimestamp) / 1000);
|
|
1935
|
-
// return meets condition
|
|
1936
|
-
switch (args.comparator) {
|
|
1937
|
-
case '<':
|
|
1938
|
-
return diffInSeconds < args.intervalInSeconds;
|
|
1939
|
-
case '<=':
|
|
1940
|
-
return diffInSeconds <= args.intervalInSeconds;
|
|
1941
|
-
default:
|
|
1942
|
-
throw new Error(`[did-provider-cheqd]: observe: Unsupported comparator: ${args.unifiedAccessControlCondition.returnValueTest.comparator}`);
|
|
1943
|
-
}
|
|
1944
|
-
});
|
|
1945
|
-
// define meetsCondition
|
|
1946
|
-
const meetsCondition = typeof meetsConditionTxIndex !== 'undefined' && meetsConditionTxIndex !== -1;
|
|
1947
|
-
// return observation result
|
|
1948
|
-
return {
|
|
1949
|
-
subscribed: true,
|
|
1950
|
-
meetsCondition: meetsCondition,
|
|
1951
|
-
transactionHash: meetsCondition ? txs.tx_responses[meetsConditionTxIndex].txhash : undefined,
|
|
1952
|
-
events: meetsCondition ? txs.tx_responses[meetsConditionTxIndex].events : undefined,
|
|
1953
|
-
rawLog: meetsCondition ? txs.tx_responses[meetsConditionTxIndex].raw_log : undefined,
|
|
1954
|
-
txResponse: meetsCondition
|
|
1955
|
-
? args?.returnTxResponse
|
|
1956
|
-
? txs.tx_responses[meetsConditionTxIndex]
|
|
1957
|
-
: undefined
|
|
1958
|
-
: undefined,
|
|
1959
|
-
};
|
|
1960
|
-
}
|
|
1961
|
-
catch (error) {
|
|
1962
|
-
// return error
|
|
1963
|
-
return {
|
|
1964
|
-
subscribed: false,
|
|
1965
|
-
meetsCondition: false,
|
|
1966
|
-
error: error,
|
|
1967
|
-
};
|
|
1968
|
-
}
|
|
1969
|
-
}
|
|
1970
|
-
async MintCapacityCredit(args, context) {
|
|
1971
|
-
// define provider
|
|
1972
|
-
const provider = await Cheqd.getProviderFromNetwork(args.network, this.supportedDidProviders);
|
|
1973
|
-
try {
|
|
1974
|
-
// delegate to provider
|
|
1975
|
-
const mintingResult = await provider.mintCapacityCredit({
|
|
1976
|
-
effectiveDays: args.effectiveDays,
|
|
1977
|
-
requestsPerDay: args.requestsPerDay,
|
|
1978
|
-
requestsPerSecond: args.requestsPerSecond,
|
|
1979
|
-
requestsPerKilosecond: args.requestsPerKilosecond,
|
|
1980
|
-
});
|
|
1981
|
-
// return mint result
|
|
1982
|
-
return {
|
|
1983
|
-
minted: true,
|
|
1984
|
-
...mintingResult,
|
|
1985
|
-
};
|
|
1986
|
-
}
|
|
1987
|
-
catch (error) {
|
|
1988
|
-
// return error
|
|
1989
|
-
return {
|
|
1990
|
-
minted: false,
|
|
1991
|
-
error: error,
|
|
1992
|
-
};
|
|
1993
|
-
}
|
|
1994
|
-
}
|
|
1995
|
-
async DelegateCapacityCredit(args, context) {
|
|
1996
|
-
// define provider
|
|
1997
|
-
const provider = await Cheqd.getProviderFromNetwork(args.network, this.supportedDidProviders);
|
|
1998
|
-
try {
|
|
1999
|
-
// delegate to provider
|
|
2000
|
-
const delegationResult = await provider.delegateCapacityCredit({
|
|
2001
|
-
capacityTokenId: args.capacityTokenId,
|
|
2002
|
-
delegateeAddresses: args.delegateeAddresses,
|
|
2003
|
-
uses: args.usesPermitted,
|
|
2004
|
-
expiration: args.expiration,
|
|
2005
|
-
statement: args.statement,
|
|
2006
|
-
});
|
|
2007
|
-
// return delegation result
|
|
2008
|
-
return {
|
|
2009
|
-
delegated: true,
|
|
2010
|
-
...delegationResult,
|
|
2011
|
-
};
|
|
2012
|
-
}
|
|
2013
|
-
catch (error) {
|
|
2014
|
-
// return error
|
|
2015
|
-
return {
|
|
2016
|
-
delegated: false,
|
|
2017
|
-
error: error,
|
|
2018
|
-
};
|
|
2019
|
-
}
|
|
2020
|
-
}
|
|
2021
|
-
static async revokeCredential(credential, options) {
|
|
2022
|
-
try {
|
|
2023
|
-
// validate status purpose
|
|
2024
|
-
if (credential?.credentialStatus?.statusPurpose !== cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.revocation)
|
|
2025
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status purpose');
|
|
2026
|
-
// fetch status list 2021
|
|
2027
|
-
const publishedList = (await Cheqd.fetchStatusList2021(credential));
|
|
2028
|
-
// early return, if encrypted and no decryption key provided
|
|
2029
|
-
if (publishedList.metadata.encrypted && !options?.topArgs?.symmetricKey)
|
|
2030
|
-
throw new Error('[did-provider-cheqd]: revocation: symmetricKey is required, if status list 2021 is encrypted');
|
|
2031
|
-
// fetch status list 2021 inscribed in credential
|
|
2032
|
-
const statusList2021 = options?.topArgs?.fetchList
|
|
2033
|
-
? await (async function () {
|
|
2034
|
-
// if not encrypted, return bitstring
|
|
2035
|
-
if (!publishedList.metadata.encrypted)
|
|
2036
|
-
return publishedList.metadata.encoding === 'base64url'
|
|
2037
|
-
? publishedList.StatusList2021.encodedList
|
|
2038
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
2039
|
-
// decrypt + return bitstring, if qualified for migration
|
|
2040
|
-
if (publishedList.metadata.encryptedSymmetricKey)
|
|
2041
|
-
return await v2_js_1.LitProtocolV2.decryptDirect(await (0, helpers_js_1.toBlob)((0, uint8arrays_1.fromString)(publishedList.StatusList2021
|
|
2042
|
-
.encodedList, 'hex')), (0, uint8arrays_1.fromString)(options?.topArgs?.symmetricKey, 'hex'));
|
|
2043
|
-
// validate encoded list
|
|
2044
|
-
if (!(0, helpers_js_1.isEncodedList)(publishedList.StatusList2021.encodedList))
|
|
2045
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid encoded list');
|
|
2046
|
-
// otherwise, decrypt and return raw bitstring
|
|
2047
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)((0, uint8arrays_1.fromString)((0, helpers_js_1.getEncodedList)(publishedList.StatusList2021.encodedList, false)[0], 'hex'));
|
|
2048
|
-
// decrypt
|
|
2049
|
-
return (0, uint8arrays_1.toString)(await v6_js_1.LitProtocol.decryptDirect(scopedRawBlob, await (0, helpers_js_1.safeDeserialise)(options?.topArgs?.symmetricKey, uint8arrays_1.fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
|
|
2050
|
-
})()
|
|
2051
|
-
: await (async function () {
|
|
2052
|
-
// transcode to base64url, if needed
|
|
2053
|
-
const publishedListTranscoded = publishedList.metadata.encoding === 'base64url'
|
|
2054
|
-
? publishedList.StatusList2021.encodedList
|
|
2055
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
2056
|
-
// if status list 2021 is not fetched, read from file
|
|
2057
|
-
if (options?.statusListFile) {
|
|
2058
|
-
// if not encrypted, return bitstring
|
|
2059
|
-
if (!publishedList.metadata.encrypted) {
|
|
2060
|
-
// construct encoded status list
|
|
2061
|
-
const encoded = new vc_status_list_1.StatusList({
|
|
2062
|
-
buffer: await Cheqd.getFile(options.statusListFile),
|
|
2063
|
-
}).encode();
|
|
2064
|
-
// validate against published list
|
|
2065
|
-
if (encoded !== publishedListTranscoded)
|
|
2066
|
-
throw new Error('[did-provider-cheqd]: revocation: statusListFile does not match published status list 2021');
|
|
2067
|
-
// return encoded
|
|
2068
|
-
return encoded;
|
|
2069
|
-
}
|
|
2070
|
-
// otherwise, decrypt and return bitstring
|
|
2071
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)(await Cheqd.getFile(options.statusListFile));
|
|
2072
|
-
// decrypt
|
|
2073
|
-
const decrypted = (0, uint8arrays_1.toString)(await v6_js_1.LitProtocol.decryptDirect(scopedRawBlob, await (0, helpers_js_1.safeDeserialise)(options?.topArgs?.symmetricKey, uint8arrays_1.fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
|
|
2074
|
-
// validate against published list
|
|
2075
|
-
if (decrypted !== publishedListTranscoded)
|
|
2076
|
-
throw new Error('[did-provider-cheqd]: revocation: statusListFile does not match published status list 2021');
|
|
2077
|
-
// return decrypted
|
|
2078
|
-
return decrypted;
|
|
2079
|
-
}
|
|
2080
|
-
if (!options?.statusListInlineBitstring)
|
|
2081
|
-
throw new Error('[did-provider-cheqd]: revocation: statusListInlineBitstring is required, if statusListFile is not provided');
|
|
2082
|
-
// validate against published list
|
|
2083
|
-
if (options?.statusListInlineBitstring !== publishedListTranscoded)
|
|
2084
|
-
throw new Error('[did-provider-cheqd]: revocation: statusListInlineBitstring does not match published status list 2021');
|
|
2085
|
-
// otherwise, read from inline bitstring
|
|
2086
|
-
return options?.statusListInlineBitstring;
|
|
2087
|
-
})();
|
|
2088
|
-
// parse status list 2021
|
|
2089
|
-
const statusList = await vc_status_list_1.StatusList.decode({ encodedList: statusList2021 });
|
|
2090
|
-
// early exit, if credential is already revoked
|
|
2091
|
-
if (statusList.getStatus(Number(credential.credentialStatus.statusListIndex)))
|
|
2092
|
-
return { revoked: true };
|
|
2093
|
-
// update revocation status
|
|
2094
|
-
statusList.setStatus(Number(credential.credentialStatus.statusListIndex), true);
|
|
2095
|
-
// set in-memory status list ref
|
|
2096
|
-
const bitstring = (await statusList.encode());
|
|
2097
|
-
// cast top-level args
|
|
2098
|
-
const topArgs = options?.topArgs;
|
|
2099
|
-
// write status list 2021 to file, if provided
|
|
2100
|
-
if (topArgs?.writeToFile) {
|
|
2101
|
-
await Cheqd.writeFile((0, uint8arrays_1.fromString)(bitstring, 'base64url'), options?.statusListFile);
|
|
2102
|
-
}
|
|
2103
|
-
// publish status list 2021, if provided
|
|
2104
|
-
const published = topArgs?.publish
|
|
2105
|
-
? await (async function () {
|
|
2106
|
-
// fetch status list 2021 metadata
|
|
2107
|
-
const statusListMetadata = await Cheqd.fetchStatusList2021Metadata(credential);
|
|
2108
|
-
// publish status list 2021 as new version
|
|
2109
|
-
const scoped = topArgs.publishEncrypted
|
|
2110
|
-
? await (async function () {
|
|
2111
|
-
// validate encoding, if provided
|
|
2112
|
-
if (options?.publishOptions?.statusListEncoding &&
|
|
2113
|
-
!Object.values(cheqd_did_provider_js_1.DefaultStatusList2021Encodings).includes(options?.publishOptions?.statusListEncoding)) {
|
|
2114
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list encoding');
|
|
2115
|
-
}
|
|
2116
|
-
// validate validUntil, if provided
|
|
2117
|
-
if (options?.publishOptions?.statusListValidUntil) {
|
|
2118
|
-
// validate validUntil as string
|
|
2119
|
-
if (typeof options?.publishOptions?.statusListValidUntil !== 'string')
|
|
2120
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be string)');
|
|
2121
|
-
// validate validUntil as date
|
|
2122
|
-
if (isNaN(Date.parse(options?.publishOptions?.statusListValidUntil)))
|
|
2123
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be date)');
|
|
2124
|
-
// validate validUntil as future date
|
|
2125
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) < new Date())
|
|
2126
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be future date)');
|
|
2127
|
-
// validate validUntil towards validFrom
|
|
2128
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) <=
|
|
2129
|
-
new Date(publishedList.StatusList2021.validFrom))
|
|
2130
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be after validFrom)');
|
|
2131
|
-
}
|
|
2132
|
-
// validate paymentConditions, if provided
|
|
2133
|
-
if (topArgs?.paymentConditions) {
|
|
2134
|
-
if (!topArgs?.paymentConditions?.every((condition) => condition.feePaymentAddress &&
|
|
2135
|
-
condition.feePaymentAmount &&
|
|
2136
|
-
condition.intervalInSeconds)) {
|
|
2137
|
-
throw new Error('[did-provider-cheqd]: paymentConditions must contain feePaymentAddress and feeAmount and intervalInSeconds');
|
|
2138
|
-
}
|
|
2139
|
-
if (!topArgs?.paymentConditions?.every((condition) => typeof condition.feePaymentAddress === 'string' &&
|
|
2140
|
-
typeof condition.feePaymentAmount === 'string' &&
|
|
2141
|
-
typeof condition.intervalInSeconds === 'number')) {
|
|
2142
|
-
throw new Error('[did-provider-cheqd]: feePaymentAddress and feePaymentAmount must be string and intervalInSeconds must be number');
|
|
2143
|
-
}
|
|
2144
|
-
if (!topArgs?.paymentConditions?.every((condition) => condition.type === exports.AccessControlConditionTypes.timelockPayment)) {
|
|
2145
|
-
throw new Error('[did-provider-cheqd]: paymentConditions must be of type timelockPayment');
|
|
2146
|
-
}
|
|
2147
|
-
}
|
|
2148
|
-
// validate dkgOptions
|
|
2149
|
-
if (!topArgs?.dkgOptions ||
|
|
2150
|
-
!topArgs?.dkgOptions?.chain ||
|
|
2151
|
-
!topArgs?.dkgOptions?.network) {
|
|
2152
|
-
throw new Error('[did-provider-cheqd]: dkgOptions is required');
|
|
2153
|
-
}
|
|
2154
|
-
// encrypt bitstring - case: symmetric
|
|
2155
|
-
const { encryptedString: symmetricEncryptionCiphertext, stringHash: symmetricEncryptionStringHash, symmetricKey, } = await v6_js_1.LitProtocol.encryptDirect((0, uint8arrays_1.fromString)(bitstring, 'base64url'));
|
|
2156
|
-
// instantiate dkg-threshold client, in which case lit-protocol is used
|
|
2157
|
-
const lit = (await options.publishOptions.instantiateDkgClient);
|
|
2158
|
-
// construct access control conditions and payment conditions tuple
|
|
2159
|
-
const unifiedAccessControlConditionsTuple = publishedList.metadata.encrypted
|
|
2160
|
-
? await (async function () {
|
|
2161
|
-
// define payment conditions, give precedence to top-level args
|
|
2162
|
-
const paymentConditions = topArgs?.paymentConditions ||
|
|
2163
|
-
publishedList.metadata.paymentConditions;
|
|
2164
|
-
// return access control conditions and payment conditions tuple
|
|
2165
|
-
return [
|
|
2166
|
-
await Promise.all(paymentConditions.map(async (condition) => {
|
|
2167
|
-
switch (condition.type) {
|
|
2168
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
2169
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
2170
|
-
key: '$.tx_responses.*.timestamp',
|
|
2171
|
-
comparator: '<=',
|
|
2172
|
-
value: `${condition.intervalInSeconds}`,
|
|
2173
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight, topArgs?.dkgOptions?.chain);
|
|
2174
|
-
default:
|
|
2175
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
2176
|
-
}
|
|
2177
|
-
})),
|
|
2178
|
-
paymentConditions,
|
|
2179
|
-
];
|
|
2180
|
-
})()
|
|
2181
|
-
: await (async function () {
|
|
2182
|
-
// validate paymentConditions
|
|
2183
|
-
if (!topArgs?.paymentConditions) {
|
|
2184
|
-
throw new Error('[did-provider-cheqd]: paymentConditions is required');
|
|
2185
|
-
}
|
|
2186
|
-
// return access control conditions and payment conditions tuple
|
|
2187
|
-
return [
|
|
2188
|
-
await Promise.all(topArgs.paymentConditions.map(async (condition) => {
|
|
2189
|
-
switch (condition.type) {
|
|
2190
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
2191
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
2192
|
-
key: '$.tx_responses.*.timestamp',
|
|
2193
|
-
comparator: '<=',
|
|
2194
|
-
value: `${condition.intervalInSeconds}`,
|
|
2195
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight);
|
|
2196
|
-
default:
|
|
2197
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
2198
|
-
}
|
|
2199
|
-
})),
|
|
2200
|
-
topArgs.paymentConditions,
|
|
2201
|
-
];
|
|
2202
|
-
})();
|
|
2203
|
-
// encrypt bitstring - case: threshold
|
|
2204
|
-
const { encryptedString: thresholdEncryptionCiphertext, stringHash: thresholdEncryptionStringHash, } = await lit.encrypt((0, uint8arrays_1.fromString)(bitstring, 'base64url'), unifiedAccessControlConditionsTuple[0]);
|
|
2205
|
-
// construct encoded list
|
|
2206
|
-
const encodedList = `${await (0, helpers_js_1.blobToHexString)(symmetricEncryptionCiphertext)}-${(0, uint8arrays_1.toString)(thresholdEncryptionCiphertext, 'hex')}`;
|
|
2207
|
-
// define status list content
|
|
2208
|
-
const content = {
|
|
2209
|
-
StatusList2021: {
|
|
2210
|
-
statusPurpose: publishedList.StatusList2021.statusPurpose,
|
|
2211
|
-
encodedList,
|
|
2212
|
-
validFrom: publishedList.StatusList2021.validFrom,
|
|
2213
|
-
validUntil: options?.publishOptions?.statusListValidUntil ||
|
|
2214
|
-
publishedList.StatusList2021.validUntil,
|
|
2215
|
-
},
|
|
2216
|
-
metadata: {
|
|
2217
|
-
type: publishedList.metadata.type,
|
|
2218
|
-
encrypted: true,
|
|
2219
|
-
encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
|
|
2220
|
-
statusListHash: symmetricEncryptionStringHash === thresholdEncryptionStringHash
|
|
2221
|
-
? symmetricEncryptionStringHash
|
|
2222
|
-
: (function () {
|
|
2223
|
-
throw new Error('[did-provider-cheqd]: revocation: symmetricEncryptionStringHash and thresholdEncryptionStringHash do not match');
|
|
2224
|
-
})(),
|
|
2225
|
-
paymentConditions: unifiedAccessControlConditionsTuple[1],
|
|
2226
|
-
},
|
|
2227
|
-
};
|
|
2228
|
-
// return tuple of publish result and encryption relevant metadata
|
|
2229
|
-
return [
|
|
2230
|
-
await Cheqd.publishStatusList2021((0, uint8arrays_1.fromString)(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
|
|
2231
|
-
{
|
|
2232
|
-
symmetricEncryptionCiphertext,
|
|
2233
|
-
thresholdEncryptionCiphertext,
|
|
2234
|
-
stringHash: symmetricEncryptionStringHash,
|
|
2235
|
-
symmetricKey,
|
|
2236
|
-
},
|
|
2237
|
-
];
|
|
2238
|
-
})()
|
|
2239
|
-
: await (async function () {
|
|
2240
|
-
// validate encoding, if provided
|
|
2241
|
-
if (options?.publishOptions?.statusListEncoding &&
|
|
2242
|
-
!Object.values(cheqd_did_provider_js_1.DefaultStatusList2021Encodings).includes(options?.publishOptions?.statusListEncoding)) {
|
|
2243
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list encoding');
|
|
2244
|
-
}
|
|
2245
|
-
// validate validUntil, if provided
|
|
2246
|
-
if (options?.publishOptions?.statusListValidUntil) {
|
|
2247
|
-
// validate validUntil as string
|
|
2248
|
-
if (typeof options?.publishOptions?.statusListValidUntil !== 'string')
|
|
2249
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be string)');
|
|
2250
|
-
// validate validUntil as date
|
|
2251
|
-
if (isNaN(Date.parse(options?.publishOptions?.statusListValidUntil)))
|
|
2252
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be date)');
|
|
2253
|
-
// validate validUntil as future date
|
|
2254
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) < new Date())
|
|
2255
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be future date)');
|
|
2256
|
-
// validate validUntil towards validFrom
|
|
2257
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) <=
|
|
2258
|
-
new Date(publishedList.StatusList2021.validFrom))
|
|
2259
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be after validFrom)');
|
|
2260
|
-
}
|
|
2261
|
-
// define status list content
|
|
2262
|
-
const content = {
|
|
2263
|
-
StatusList2021: {
|
|
2264
|
-
statusPurpose: publishedList.StatusList2021.statusPurpose,
|
|
2265
|
-
encodedList: publishedList.metadata.encoding === 'base64url'
|
|
2266
|
-
? bitstring
|
|
2267
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(bitstring, 'base64url'), options.publishOptions
|
|
2268
|
-
.statusListEncoding),
|
|
2269
|
-
validFrom: publishedList.StatusList2021.validFrom,
|
|
2270
|
-
validUntil: options?.publishOptions?.statusListValidUntil ||
|
|
2271
|
-
publishedList.StatusList2021.validUntil,
|
|
2272
|
-
},
|
|
2273
|
-
metadata: {
|
|
2274
|
-
type: publishedList.metadata.type,
|
|
2275
|
-
encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
|
|
2276
|
-
encrypted: false,
|
|
2277
|
-
},
|
|
2278
|
-
};
|
|
2279
|
-
// return tuple of publish result and encryption relevant metadata
|
|
2280
|
-
return [
|
|
2281
|
-
await Cheqd.publishStatusList2021((0, uint8arrays_1.fromString)(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
|
|
2282
|
-
undefined,
|
|
2283
|
-
];
|
|
2284
|
-
})();
|
|
2285
|
-
// early exit, if publish failed
|
|
2286
|
-
if (!scoped[0])
|
|
2287
|
-
throw new Error('[did-provider-cheqd]: revocation: Failed to publish status list 2021');
|
|
2288
|
-
// return publish result
|
|
2289
|
-
return scoped;
|
|
2290
|
-
})()
|
|
2291
|
-
: undefined;
|
|
2292
|
-
return {
|
|
2293
|
-
revoked: true,
|
|
2294
|
-
published: topArgs?.publish ? true : undefined,
|
|
2295
|
-
statusList: topArgs?.returnUpdatedStatusList
|
|
2296
|
-
? (await Cheqd.fetchStatusList2021(credential))
|
|
2297
|
-
: undefined,
|
|
2298
|
-
symmetricKey: topArgs?.returnSymmetricKey
|
|
2299
|
-
? (0, uint8arrays_1.toString)(published?.[1]?.symmetricKey, 'hex')
|
|
2300
|
-
: undefined,
|
|
2301
|
-
resourceMetadata: topArgs?.returnStatusListMetadata
|
|
2302
|
-
? await Cheqd.fetchStatusList2021Metadata(credential)
|
|
2303
|
-
: undefined,
|
|
2304
|
-
};
|
|
2305
|
-
}
|
|
2306
|
-
catch (error) {
|
|
2307
|
-
// silent fail + early exit
|
|
2308
|
-
console.error(error);
|
|
2309
|
-
return { revoked: false, error: error };
|
|
2310
|
-
}
|
|
2311
|
-
}
|
|
2312
|
-
static async revokeCredentials(credentials, options) {
|
|
2313
|
-
// validate credentials - case: empty
|
|
2314
|
-
if (!credentials.length || credentials.length === 0)
|
|
2315
|
-
throw new Error('[did-provider-cheqd]: revocation: No credentials provided');
|
|
2316
|
-
// validate credentials - case: consistent issuer
|
|
2317
|
-
if (credentials
|
|
2318
|
-
.map((credential) => {
|
|
2319
|
-
return credential.issuer.id
|
|
2320
|
-
? credential.issuer.id
|
|
2321
|
-
: credential.issuer;
|
|
2322
|
-
})
|
|
2323
|
-
.filter((value, _, self) => value && value !== self[0]).length > 0)
|
|
2324
|
-
throw new Error('[did-provider-cheqd]: revocation: Credentials must be issued by the same issuer');
|
|
2325
|
-
// validate credentials - case: status list index
|
|
2326
|
-
if (credentials
|
|
2327
|
-
.map((credential) => credential.credentialStatus.statusListIndex)
|
|
2328
|
-
.filter((value, index, self) => self.indexOf(value) !== index).length > 0)
|
|
2329
|
-
throw new Error('[did-provider-cheqd]: revocation: Credentials must have unique status list index');
|
|
2330
|
-
// validate credentials - case: status purpose
|
|
2331
|
-
if (!credentials.every((credential) => credential.credentialStatus?.statusPurpose === cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.revocation))
|
|
2332
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status purpose');
|
|
2333
|
-
// validate credentials - case: status list id
|
|
2334
|
-
const remote = credentials[0].credentialStatus?.id
|
|
2335
|
-
? credentials[0].credentialStatus.id.split('#')[0]
|
|
2336
|
-
: (function () {
|
|
2337
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list id');
|
|
2338
|
-
})();
|
|
2339
|
-
// validate credentials - case: status list id format
|
|
2340
|
-
if (!exports.RemoteListPattern.test(remote))
|
|
2341
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list id format: expected: https://<optional_subdomain>.<sld>.<tld>/1.0/identifiers/<did:cheqd:<namespace>:<method_specific_id>>?resourceName=<resource_name>&resourceType=<resource_type>');
|
|
2342
|
-
if (!credentials.every((credential) => {
|
|
2343
|
-
return credential.credentialStatus.id.split('#')[0] === remote;
|
|
2344
|
-
}))
|
|
2345
|
-
throw new Error('[did-provider-cheqd]: revocation: Credentials must belong to the same status list');
|
|
2346
|
-
// validate credentials - case: status list type
|
|
2347
|
-
if (!credentials.every((credential) => credential.credentialStatus?.type === 'StatusList2021Entry'))
|
|
2348
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list type');
|
|
2349
|
-
try {
|
|
2350
|
-
// fetch status list 2021
|
|
2351
|
-
const publishedList = (await Cheqd.fetchStatusList2021(credentials[0]));
|
|
2352
|
-
// early return, if encrypted and no decryption key provided
|
|
2353
|
-
if (publishedList.metadata.encrypted && !options?.topArgs?.symmetricKey)
|
|
2354
|
-
throw new Error('[did-provider-cheqd]: revocation: symmetricKey is required, if status list 2021 is encrypted');
|
|
2355
|
-
// fetch status list 2021 inscribed in credential
|
|
2356
|
-
const statusList2021 = options?.topArgs?.fetchList
|
|
2357
|
-
? await (async function () {
|
|
2358
|
-
// if not encrypted, return bitstring
|
|
2359
|
-
if (!publishedList.metadata.encrypted)
|
|
2360
|
-
return publishedList.metadata.encoding === 'base64url'
|
|
2361
|
-
? publishedList.StatusList2021.encodedList
|
|
2362
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
2363
|
-
// decrypt + return bitstring, if qualified for migration
|
|
2364
|
-
if (publishedList.metadata.encryptedSymmetricKey)
|
|
2365
|
-
return await v2_js_1.LitProtocolV2.decryptDirect(await (0, helpers_js_1.toBlob)((0, uint8arrays_1.fromString)(publishedList.StatusList2021
|
|
2366
|
-
.encodedList, 'hex')), (0, uint8arrays_1.fromString)(options?.topArgs?.symmetricKey, 'hex'));
|
|
2367
|
-
// validate encoded list
|
|
2368
|
-
if (!(0, helpers_js_1.isEncodedList)(publishedList.StatusList2021.encodedList))
|
|
2369
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid encoded list');
|
|
2370
|
-
// otherwise, decrypt and return raw bitstring
|
|
2371
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)((0, uint8arrays_1.fromString)((0, helpers_js_1.getEncodedList)(publishedList.StatusList2021.encodedList, false)[0], 'hex'));
|
|
2372
|
-
// decrypt
|
|
2373
|
-
return (0, uint8arrays_1.toString)(await v6_js_1.LitProtocol.decryptDirect(scopedRawBlob, await (0, helpers_js_1.safeDeserialise)(options?.topArgs?.symmetricKey, uint8arrays_1.fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
|
|
2374
|
-
})()
|
|
2375
|
-
: await (async function () {
|
|
2376
|
-
// transcode to base64url, if needed
|
|
2377
|
-
const publishedListTranscoded = publishedList.metadata.encoding === 'base64url'
|
|
2378
|
-
? publishedList.StatusList2021.encodedList
|
|
2379
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
2380
|
-
// if status list 2021 is not fetched, read from file
|
|
2381
|
-
if (options?.statusListFile) {
|
|
2382
|
-
// if not encrypted, return bitstring
|
|
2383
|
-
if (!publishedList.metadata.encrypted) {
|
|
2384
|
-
// construct encoded status list
|
|
2385
|
-
const encoded = new vc_status_list_1.StatusList({
|
|
2386
|
-
buffer: await Cheqd.getFile(options.statusListFile),
|
|
2387
|
-
}).encode();
|
|
2388
|
-
// validate against published list
|
|
2389
|
-
if (encoded !== publishedListTranscoded)
|
|
2390
|
-
throw new Error('[did-provider-cheqd]: revocation: statusListFile does not match published status list 2021');
|
|
2391
|
-
// return encoded
|
|
2392
|
-
return encoded;
|
|
2393
|
-
}
|
|
2394
|
-
// otherwise, decrypt and return bitstring
|
|
2395
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)(await Cheqd.getFile(options.statusListFile));
|
|
2396
|
-
// decrypt
|
|
2397
|
-
const decrypted = (0, uint8arrays_1.toString)(await v6_js_1.LitProtocol.decryptDirect(scopedRawBlob, await (0, helpers_js_1.safeDeserialise)(options?.topArgs?.symmetricKey, uint8arrays_1.fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
|
|
2398
|
-
// validate against published list
|
|
2399
|
-
if (decrypted !== publishedListTranscoded)
|
|
2400
|
-
throw new Error('[did-provider-cheqd]: revocation: statusListFile does not match published status list 2021');
|
|
2401
|
-
// return decrypted
|
|
2402
|
-
return decrypted;
|
|
2403
|
-
}
|
|
2404
|
-
if (!options?.statusListInlineBitstring)
|
|
2405
|
-
throw new Error('[did-provider-cheqd]: revocation: statusListInlineBitstring is required, if statusListFile is not provided');
|
|
2406
|
-
// validate against published list
|
|
2407
|
-
if (options?.statusListInlineBitstring !== publishedListTranscoded)
|
|
2408
|
-
throw new Error('[did-provider-cheqd]: revocation: statusListInlineBitstring does not match published status list 2021');
|
|
2409
|
-
// otherwise, read from inline bitstring
|
|
2410
|
-
return options?.statusListInlineBitstring;
|
|
2411
|
-
})();
|
|
2412
|
-
// parse status list 2021
|
|
2413
|
-
const statusList = await vc_status_list_1.StatusList.decode({ encodedList: statusList2021 });
|
|
2414
|
-
// initiate bulk revocation
|
|
2415
|
-
const revoked = (await Promise.allSettled(credentials.map((credential) => {
|
|
2416
|
-
return (async function () {
|
|
2417
|
-
// early return, if no credential status
|
|
2418
|
-
if (!credential.credentialStatus)
|
|
2419
|
-
return { revoked: false };
|
|
2420
|
-
// early exit, if credential is already revoked
|
|
2421
|
-
if (statusList.getStatus(Number(credential.credentialStatus.statusListIndex)))
|
|
2422
|
-
return { revoked: true };
|
|
2423
|
-
// update revocation status
|
|
2424
|
-
statusList.setStatus(Number(credential.credentialStatus.statusListIndex), true);
|
|
2425
|
-
// return revocation status
|
|
2426
|
-
return { revoked: true };
|
|
2427
|
-
})();
|
|
2428
|
-
})));
|
|
2429
|
-
// revert bulk ops, if some failed
|
|
2430
|
-
if (revoked.some((result) => result.status === 'fulfilled' && !result.value.revoked))
|
|
2431
|
-
throw new Error(`[did-provider-cheqd]: revocation: Bulk revocation failed: already revoked credentials in revocation bundle: raw log: ${JSON.stringify(revoked.map((result) => ({
|
|
2432
|
-
revoked: result.status === 'fulfilled' ? result.value.revoked : false,
|
|
2433
|
-
})))}`);
|
|
2434
|
-
// set in-memory status list ref
|
|
2435
|
-
const bitstring = (await statusList.encode());
|
|
2436
|
-
// cast top-level args
|
|
2437
|
-
const topArgs = options?.topArgs;
|
|
2438
|
-
// write status list 2021 to file, if provided
|
|
2439
|
-
if (topArgs?.writeToFile) {
|
|
2440
|
-
await Cheqd.writeFile((0, uint8arrays_1.fromString)(bitstring, 'base64url'), options?.statusListFile);
|
|
2441
|
-
}
|
|
2442
|
-
// publish status list 2021, if provided
|
|
2443
|
-
const published = topArgs?.publish
|
|
2444
|
-
? await (async function () {
|
|
2445
|
-
// fetch status list 2021 metadata
|
|
2446
|
-
const statusListMetadata = await Cheqd.fetchStatusList2021Metadata(credentials[0]);
|
|
2447
|
-
// publish status list 2021 as new version
|
|
2448
|
-
const scoped = topArgs.publishEncrypted
|
|
2449
|
-
? await (async function () {
|
|
2450
|
-
// validate encoding, if provided
|
|
2451
|
-
if (options?.publishOptions?.statusListEncoding &&
|
|
2452
|
-
!Object.values(cheqd_did_provider_js_1.DefaultStatusList2021Encodings).includes(options?.publishOptions?.statusListEncoding)) {
|
|
2453
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list encoding');
|
|
2454
|
-
}
|
|
2455
|
-
// validate validUntil, if provided
|
|
2456
|
-
if (options?.publishOptions?.statusListValidUntil) {
|
|
2457
|
-
// validate validUntil as string
|
|
2458
|
-
if (typeof options?.publishOptions?.statusListValidUntil !== 'string')
|
|
2459
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be string)');
|
|
2460
|
-
// validate validUntil as date
|
|
2461
|
-
if (isNaN(Date.parse(options?.publishOptions?.statusListValidUntil)))
|
|
2462
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be date)');
|
|
2463
|
-
// validate validUntil as future date
|
|
2464
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) < new Date())
|
|
2465
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be future date)');
|
|
2466
|
-
// validate validUntil towards validFrom
|
|
2467
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) <=
|
|
2468
|
-
new Date(publishedList.StatusList2021.validFrom))
|
|
2469
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be after validFrom)');
|
|
2470
|
-
}
|
|
2471
|
-
// validate paymentConditions, if provided
|
|
2472
|
-
if (topArgs?.paymentConditions) {
|
|
2473
|
-
if (!topArgs?.paymentConditions?.every((condition) => condition.feePaymentAddress &&
|
|
2474
|
-
condition.feePaymentAmount &&
|
|
2475
|
-
condition.intervalInSeconds)) {
|
|
2476
|
-
throw new Error('[did-provider-cheqd]: paymentConditions must contain feePaymentAddress and feeAmount and intervalInSeconds');
|
|
2477
|
-
}
|
|
2478
|
-
if (!topArgs?.paymentConditions?.every((condition) => typeof condition.feePaymentAddress === 'string' &&
|
|
2479
|
-
typeof condition.feePaymentAmount === 'string' &&
|
|
2480
|
-
typeof condition.intervalInSeconds === 'number')) {
|
|
2481
|
-
throw new Error('[did-provider-cheqd]: feePaymentAddress and feePaymentAmount must be string and intervalInSeconds must be number');
|
|
2482
|
-
}
|
|
2483
|
-
if (!topArgs?.paymentConditions?.every((condition) => condition.type === exports.AccessControlConditionTypes.timelockPayment)) {
|
|
2484
|
-
throw new Error('[did-provider-cheqd]: paymentConditions must be of type timelockPayment');
|
|
2485
|
-
}
|
|
2486
|
-
}
|
|
2487
|
-
// validate dkgOptions
|
|
2488
|
-
if (!topArgs?.dkgOptions ||
|
|
2489
|
-
!topArgs?.dkgOptions?.chain ||
|
|
2490
|
-
!topArgs?.dkgOptions?.network) {
|
|
2491
|
-
throw new Error('[did-provider-cheqd]: dkgOptions is required');
|
|
2492
|
-
}
|
|
2493
|
-
// encrypt bitstring - case: symmetric
|
|
2494
|
-
const { encryptedString: symmetricEncryptionCiphertext, stringHash: symmetricEncryptionStringHash, symmetricKey, } = await v6_js_1.LitProtocol.encryptDirect((0, uint8arrays_1.fromString)(bitstring, 'base64url'));
|
|
2495
|
-
// instantiate dkg-threshold client, in which case lit-protocol is used
|
|
2496
|
-
const lit = (await options.publishOptions.instantiateDkgClient);
|
|
2497
|
-
// construct access control conditions and payment conditions tuple
|
|
2498
|
-
const unifiedAccessControlConditionsTuple = publishedList.metadata.encrypted
|
|
2499
|
-
? await (async function () {
|
|
2500
|
-
// define payment conditions, give precedence to top-level args
|
|
2501
|
-
const paymentConditions = topArgs?.paymentConditions ||
|
|
2502
|
-
publishedList.metadata.paymentConditions;
|
|
2503
|
-
// return access control conditions and payment conditions tuple
|
|
2504
|
-
return [
|
|
2505
|
-
await Promise.all(paymentConditions.map(async (condition) => {
|
|
2506
|
-
switch (condition.type) {
|
|
2507
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
2508
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
2509
|
-
key: '$.tx_responses.*.timestamp',
|
|
2510
|
-
comparator: '<=',
|
|
2511
|
-
value: `${condition.intervalInSeconds}`,
|
|
2512
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight, topArgs?.dkgOptions?.chain);
|
|
2513
|
-
default:
|
|
2514
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
2515
|
-
}
|
|
2516
|
-
})),
|
|
2517
|
-
paymentConditions,
|
|
2518
|
-
];
|
|
2519
|
-
})()
|
|
2520
|
-
: await (async function () {
|
|
2521
|
-
// validate paymentConditions
|
|
2522
|
-
if (!topArgs?.paymentConditions) {
|
|
2523
|
-
throw new Error('[did-provider-cheqd]: paymentConditions is required');
|
|
2524
|
-
}
|
|
2525
|
-
// return access control conditions and payment conditions tuple
|
|
2526
|
-
return [
|
|
2527
|
-
await Promise.all(topArgs.paymentConditions.map(async (condition) => {
|
|
2528
|
-
switch (condition.type) {
|
|
2529
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
2530
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
2531
|
-
key: '$.tx_responses.*.timestamp',
|
|
2532
|
-
comparator: '<=',
|
|
2533
|
-
value: `${condition.intervalInSeconds}`,
|
|
2534
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight);
|
|
2535
|
-
default:
|
|
2536
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
2537
|
-
}
|
|
2538
|
-
})),
|
|
2539
|
-
topArgs.paymentConditions,
|
|
2540
|
-
];
|
|
2541
|
-
})();
|
|
2542
|
-
// encrypt bitstring - case: threshold
|
|
2543
|
-
const { encryptedString: thresholdEncryptionCiphertext, stringHash: thresholdEncryptionStringHash, } = await lit.encrypt((0, uint8arrays_1.fromString)(bitstring, 'base64url'), unifiedAccessControlConditionsTuple[0]);
|
|
2544
|
-
// construct encoded list
|
|
2545
|
-
const encodedList = `${await (0, helpers_js_1.blobToHexString)(symmetricEncryptionCiphertext)}-${(0, uint8arrays_1.toString)(thresholdEncryptionCiphertext, 'hex')}`;
|
|
2546
|
-
// define status list content
|
|
2547
|
-
const content = {
|
|
2548
|
-
StatusList2021: {
|
|
2549
|
-
statusPurpose: publishedList.StatusList2021.statusPurpose,
|
|
2550
|
-
encodedList,
|
|
2551
|
-
validFrom: publishedList.StatusList2021.validFrom,
|
|
2552
|
-
validUntil: options?.publishOptions?.statusListValidUntil ||
|
|
2553
|
-
publishedList.StatusList2021.validUntil,
|
|
2554
|
-
},
|
|
2555
|
-
metadata: {
|
|
2556
|
-
type: publishedList.metadata.type,
|
|
2557
|
-
encrypted: true,
|
|
2558
|
-
encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
|
|
2559
|
-
statusListHash: symmetricEncryptionStringHash === thresholdEncryptionStringHash
|
|
2560
|
-
? symmetricEncryptionStringHash
|
|
2561
|
-
: (function () {
|
|
2562
|
-
throw new Error('[did-provider-cheqd]: revocation: symmetricEncryptionStringHash and thresholdEncryptionStringHash do not match');
|
|
2563
|
-
})(),
|
|
2564
|
-
paymentConditions: unifiedAccessControlConditionsTuple[1],
|
|
2565
|
-
},
|
|
2566
|
-
};
|
|
2567
|
-
// return tuple of publish result and encryption relevant metadata
|
|
2568
|
-
return [
|
|
2569
|
-
await Cheqd.publishStatusList2021((0, uint8arrays_1.fromString)(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
|
|
2570
|
-
{
|
|
2571
|
-
symmetricEncryptionCiphertext,
|
|
2572
|
-
thresholdEncryptionCiphertext,
|
|
2573
|
-
stringHash: symmetricEncryptionStringHash,
|
|
2574
|
-
symmetricKey,
|
|
2575
|
-
},
|
|
2576
|
-
];
|
|
2577
|
-
})()
|
|
2578
|
-
: await (async function () {
|
|
2579
|
-
// validate encoding, if provided
|
|
2580
|
-
if (options?.publishOptions?.statusListEncoding &&
|
|
2581
|
-
!Object.values(cheqd_did_provider_js_1.DefaultStatusList2021Encodings).includes(options?.publishOptions?.statusListEncoding)) {
|
|
2582
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list encoding');
|
|
2583
|
-
}
|
|
2584
|
-
// validate validUntil, if provided
|
|
2585
|
-
if (options?.publishOptions?.statusListValidUntil) {
|
|
2586
|
-
// validate validUntil as string
|
|
2587
|
-
if (typeof options?.publishOptions?.statusListValidUntil !== 'string')
|
|
2588
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be string)');
|
|
2589
|
-
// validate validUntil as date
|
|
2590
|
-
if (isNaN(Date.parse(options?.publishOptions?.statusListValidUntil)))
|
|
2591
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be date)');
|
|
2592
|
-
// validate validUntil as future date
|
|
2593
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) < new Date())
|
|
2594
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be future date)');
|
|
2595
|
-
// validate validUntil towards validFrom
|
|
2596
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) <=
|
|
2597
|
-
new Date(publishedList.StatusList2021.validFrom))
|
|
2598
|
-
throw new Error('[did-provider-cheqd]: revocation: Invalid status list validUntil (must be after validFrom)');
|
|
2599
|
-
}
|
|
2600
|
-
// define status list content
|
|
2601
|
-
const content = {
|
|
2602
|
-
StatusList2021: {
|
|
2603
|
-
statusPurpose: publishedList.StatusList2021.statusPurpose,
|
|
2604
|
-
encodedList: publishedList.metadata.encoding === 'base64url'
|
|
2605
|
-
? bitstring
|
|
2606
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(bitstring, 'base64url'), options.publishOptions
|
|
2607
|
-
.statusListEncoding),
|
|
2608
|
-
validFrom: publishedList.StatusList2021.validFrom,
|
|
2609
|
-
validUntil: options?.publishOptions?.statusListValidUntil ||
|
|
2610
|
-
publishedList.StatusList2021.validUntil,
|
|
2611
|
-
},
|
|
2612
|
-
metadata: {
|
|
2613
|
-
type: publishedList.metadata.type,
|
|
2614
|
-
encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
|
|
2615
|
-
encrypted: false,
|
|
2616
|
-
},
|
|
2617
|
-
};
|
|
2618
|
-
// return tuple of publish result and encryption relevant metadata
|
|
2619
|
-
return [
|
|
2620
|
-
await Cheqd.publishStatusList2021((0, uint8arrays_1.fromString)(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
|
|
2621
|
-
undefined,
|
|
2622
|
-
];
|
|
2623
|
-
})();
|
|
2624
|
-
// early exit, if publish failed
|
|
2625
|
-
if (!scoped[0])
|
|
2626
|
-
throw new Error('[did-provider-cheqd]: revocation: Failed to publish status list 2021');
|
|
2627
|
-
// return publish result
|
|
2628
|
-
return scoped;
|
|
2629
|
-
})()
|
|
2630
|
-
: undefined;
|
|
2631
|
-
return {
|
|
2632
|
-
revoked: revoked.map((result) => (result.status === 'fulfilled' ? result.value.revoked : false)),
|
|
2633
|
-
published: topArgs?.publish ? true : undefined,
|
|
2634
|
-
statusList: topArgs?.returnUpdatedStatusList
|
|
2635
|
-
? (await Cheqd.fetchStatusList2021(credentials[0]))
|
|
2636
|
-
: undefined,
|
|
2637
|
-
symmetricKey: topArgs?.returnSymmetricKey
|
|
2638
|
-
? (0, uint8arrays_1.toString)(published?.[1]?.symmetricKey, 'hex')
|
|
2639
|
-
: undefined,
|
|
2640
|
-
resourceMetadata: topArgs?.returnStatusListMetadata
|
|
2641
|
-
? await Cheqd.fetchStatusList2021Metadata(credentials[0])
|
|
2642
|
-
: undefined,
|
|
2643
|
-
};
|
|
2644
|
-
}
|
|
2645
|
-
catch (error) {
|
|
2646
|
-
// silent fail + early exit
|
|
2647
|
-
console.error(error);
|
|
2648
|
-
return { revoked: [], error: error };
|
|
2649
|
-
}
|
|
2650
|
-
}
|
|
2651
|
-
static async suspendCredential(credential, options) {
|
|
2652
|
-
try {
|
|
2653
|
-
// validate status purpose
|
|
2654
|
-
if (credential?.credentialStatus?.statusPurpose !== cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension)
|
|
2655
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status purpose');
|
|
2656
|
-
// fetch status list 2021
|
|
2657
|
-
const publishedList = (await Cheqd.fetchStatusList2021(credential));
|
|
2658
|
-
// early return, if encrypted and no decryption key provided
|
|
2659
|
-
if (publishedList.metadata.encrypted && !options?.topArgs?.symmetricKey)
|
|
2660
|
-
throw new Error('[did-provider-cheqd]: suspension: symmetricKey is required, if status list 2021 is encrypted');
|
|
2661
|
-
// fetch status list 2021 inscribed in credential
|
|
2662
|
-
const statusList2021 = options?.topArgs?.fetchList
|
|
2663
|
-
? await (async function () {
|
|
2664
|
-
// if not encrypted, return bitstring
|
|
2665
|
-
if (!publishedList.metadata.encrypted)
|
|
2666
|
-
return publishedList.metadata.encoding === 'base64url'
|
|
2667
|
-
? publishedList.StatusList2021.encodedList
|
|
2668
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
2669
|
-
// decrypt + return bitstring, if qualified for migration
|
|
2670
|
-
if (publishedList.metadata.encryptedSymmetricKey)
|
|
2671
|
-
return await v2_js_1.LitProtocolV2.decryptDirect(await (0, helpers_js_1.toBlob)((0, uint8arrays_1.fromString)(publishedList.StatusList2021
|
|
2672
|
-
.encodedList, 'hex')), (0, uint8arrays_1.fromString)(options?.topArgs?.symmetricKey, 'hex'));
|
|
2673
|
-
// validate encoded list
|
|
2674
|
-
if (!(0, helpers_js_1.isEncodedList)(publishedList.StatusList2021.encodedList))
|
|
2675
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid encoded list');
|
|
2676
|
-
// otherwise, decrypt and return raw bitstring
|
|
2677
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)((0, uint8arrays_1.fromString)((0, helpers_js_1.getEncodedList)(publishedList.StatusList2021.encodedList, false)[0], 'hex'));
|
|
2678
|
-
// decrypt
|
|
2679
|
-
return (0, uint8arrays_1.toString)(await v6_js_1.LitProtocol.decryptDirect(scopedRawBlob, await (0, helpers_js_1.safeDeserialise)(options?.topArgs?.symmetricKey, uint8arrays_1.fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
|
|
2680
|
-
})()
|
|
2681
|
-
: await (async function () {
|
|
2682
|
-
// transcode to base64url, if needed
|
|
2683
|
-
const publishedListTranscoded = publishedList.metadata.encoding === 'base64url'
|
|
2684
|
-
? publishedList.StatusList2021.encodedList
|
|
2685
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
2686
|
-
// if status list 2021 is not fetched, read from file
|
|
2687
|
-
if (options?.statusListFile) {
|
|
2688
|
-
// if not encrypted, return bitstring
|
|
2689
|
-
if (!publishedList.metadata.encrypted) {
|
|
2690
|
-
// construct encoded status list
|
|
2691
|
-
const encoded = new vc_status_list_1.StatusList({
|
|
2692
|
-
buffer: await Cheqd.getFile(options.statusListFile),
|
|
2693
|
-
}).encode();
|
|
2694
|
-
// validate against published list
|
|
2695
|
-
if (encoded !== publishedListTranscoded)
|
|
2696
|
-
throw new Error('[did-provider-cheqd]: suspension: statusListFile does not match published status list 2021');
|
|
2697
|
-
// return encoded
|
|
2698
|
-
return encoded;
|
|
2699
|
-
}
|
|
2700
|
-
// otherwise, decrypt and return bitstring
|
|
2701
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)(await Cheqd.getFile(options.statusListFile));
|
|
2702
|
-
// decrypt
|
|
2703
|
-
const decrypted = (0, uint8arrays_1.toString)(await v6_js_1.LitProtocol.decryptDirect(scopedRawBlob, await (0, helpers_js_1.safeDeserialise)(options?.topArgs?.symmetricKey, uint8arrays_1.fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
|
|
2704
|
-
// validate against published list
|
|
2705
|
-
if (decrypted !== publishedListTranscoded)
|
|
2706
|
-
throw new Error('[did-provider-cheqd]: suspension: statusListFile does not match published status list 2021');
|
|
2707
|
-
// return decrypted
|
|
2708
|
-
return decrypted;
|
|
2709
|
-
}
|
|
2710
|
-
if (!options?.statusListInlineBitstring)
|
|
2711
|
-
throw new Error('[did-provider-cheqd]: suspension: statusListInlineBitstring is required, if statusListFile is not provided');
|
|
2712
|
-
// validate against published list
|
|
2713
|
-
if (options?.statusListInlineBitstring !== publishedListTranscoded)
|
|
2714
|
-
throw new Error('[did-provider-cheqd]: suspension: statusListInlineBitstring does not match published status list 2021');
|
|
2715
|
-
// otherwise, read from inline bitstring
|
|
2716
|
-
return options?.statusListInlineBitstring;
|
|
2717
|
-
})();
|
|
2718
|
-
// parse status list 2021
|
|
2719
|
-
const statusList = await vc_status_list_1.StatusList.decode({ encodedList: statusList2021 });
|
|
2720
|
-
// early exit, if already suspended
|
|
2721
|
-
if (statusList.getStatus(Number(credential.credentialStatus.statusListIndex)))
|
|
2722
|
-
return { suspended: true };
|
|
2723
|
-
// update suspension status
|
|
2724
|
-
statusList.setStatus(Number(credential.credentialStatus.statusListIndex), true);
|
|
2725
|
-
// set in-memory status list ref
|
|
2726
|
-
const bitstring = (await statusList.encode());
|
|
2727
|
-
// cast top-level args
|
|
2728
|
-
const topArgs = options?.topArgs;
|
|
2729
|
-
// write status list 2021 to file, if provided
|
|
2730
|
-
if (topArgs?.writeToFile) {
|
|
2731
|
-
await Cheqd.writeFile((0, uint8arrays_1.fromString)(bitstring, 'base64url'), options?.statusListFile);
|
|
2732
|
-
}
|
|
2733
|
-
// publish status list 2021, if provided
|
|
2734
|
-
const published = topArgs?.publish
|
|
2735
|
-
? await (async function () {
|
|
2736
|
-
// fetch status list 2021 metadata
|
|
2737
|
-
const statusListMetadata = await Cheqd.fetchStatusList2021Metadata(credential);
|
|
2738
|
-
// publish status list 2021 as new version
|
|
2739
|
-
const scoped = topArgs.publishEncrypted
|
|
2740
|
-
? await (async function () {
|
|
2741
|
-
// validate encoding, if provided
|
|
2742
|
-
if (options?.publishOptions?.statusListEncoding &&
|
|
2743
|
-
!Object.values(cheqd_did_provider_js_1.DefaultStatusList2021Encodings).includes(options?.publishOptions?.statusListEncoding)) {
|
|
2744
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list encoding');
|
|
2745
|
-
}
|
|
2746
|
-
// validate validUntil, if provided
|
|
2747
|
-
if (options?.publishOptions?.statusListValidUntil) {
|
|
2748
|
-
// validate validUntil as string
|
|
2749
|
-
if (typeof options?.publishOptions?.statusListValidUntil !== 'string')
|
|
2750
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be string)');
|
|
2751
|
-
// validate validUntil as date
|
|
2752
|
-
if (isNaN(Date.parse(options?.publishOptions?.statusListValidUntil)))
|
|
2753
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be date)');
|
|
2754
|
-
// validate validUntil as future date
|
|
2755
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) < new Date())
|
|
2756
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be future date)');
|
|
2757
|
-
// validate validUntil towards validFrom
|
|
2758
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) <=
|
|
2759
|
-
new Date(publishedList.StatusList2021.validFrom))
|
|
2760
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be after validFrom)');
|
|
2761
|
-
}
|
|
2762
|
-
// validate paymentConditions, if provided
|
|
2763
|
-
if (topArgs?.paymentConditions) {
|
|
2764
|
-
if (!topArgs?.paymentConditions?.every((condition) => condition.feePaymentAddress &&
|
|
2765
|
-
condition.feePaymentAmount &&
|
|
2766
|
-
condition.intervalInSeconds)) {
|
|
2767
|
-
throw new Error('[did-provider-cheqd]: paymentConditions must contain feePaymentAddress and feeAmount and intervalInSeconds');
|
|
2768
|
-
}
|
|
2769
|
-
if (!topArgs?.paymentConditions?.every((condition) => typeof condition.feePaymentAddress === 'string' &&
|
|
2770
|
-
typeof condition.feePaymentAmount === 'string' &&
|
|
2771
|
-
typeof condition.intervalInSeconds === 'number')) {
|
|
2772
|
-
throw new Error('[did-provider-cheqd]: feePaymentAddress and feePaymentAmount must be string and intervalInSeconds must be number');
|
|
2773
|
-
}
|
|
2774
|
-
if (!topArgs?.paymentConditions?.every((condition) => condition.type === exports.AccessControlConditionTypes.timelockPayment)) {
|
|
2775
|
-
throw new Error('[did-provider-cheqd]: paymentConditions must be of type timelockPayment');
|
|
2776
|
-
}
|
|
2777
|
-
}
|
|
2778
|
-
// validate dkgOptions
|
|
2779
|
-
if (!topArgs?.dkgOptions ||
|
|
2780
|
-
!topArgs?.dkgOptions?.chain ||
|
|
2781
|
-
!topArgs?.dkgOptions?.network) {
|
|
2782
|
-
throw new Error('[did-provider-cheqd]: dkgOptions is required');
|
|
2783
|
-
}
|
|
2784
|
-
// encrypt bitstring - case: symmetric
|
|
2785
|
-
const { encryptedString: symmetricEncryptionCiphertext, stringHash: symmetricEncryptionStringHash, symmetricKey, } = await v6_js_1.LitProtocol.encryptDirect((0, uint8arrays_1.fromString)(bitstring, 'base64url'));
|
|
2786
|
-
// instantiate dkg-threshold client, in which case lit-protocol is used
|
|
2787
|
-
const lit = (await options.publishOptions.instantiateDkgClient);
|
|
2788
|
-
// construct access control conditions and payment conditions tuple
|
|
2789
|
-
const unifiedAccessControlConditionsTuple = publishedList.metadata.encrypted
|
|
2790
|
-
? await (async function () {
|
|
2791
|
-
// define payment conditions, give precedence to top-level args
|
|
2792
|
-
const paymentConditions = topArgs?.paymentConditions ||
|
|
2793
|
-
publishedList.metadata.paymentConditions;
|
|
2794
|
-
// return access control conditions and payment conditions tuple
|
|
2795
|
-
return [
|
|
2796
|
-
await Promise.all(paymentConditions.map(async (condition) => {
|
|
2797
|
-
switch (condition.type) {
|
|
2798
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
2799
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
2800
|
-
key: '$.tx_responses.*.timestamp',
|
|
2801
|
-
comparator: '<=',
|
|
2802
|
-
value: `${condition.intervalInSeconds}`,
|
|
2803
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight, topArgs?.dkgOptions?.chain);
|
|
2804
|
-
default:
|
|
2805
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
2806
|
-
}
|
|
2807
|
-
})),
|
|
2808
|
-
paymentConditions,
|
|
2809
|
-
];
|
|
2810
|
-
})()
|
|
2811
|
-
: await (async function () {
|
|
2812
|
-
// validate paymentConditions
|
|
2813
|
-
if (!topArgs?.paymentConditions) {
|
|
2814
|
-
throw new Error('[did-provider-cheqd]: paymentConditions is required');
|
|
2815
|
-
}
|
|
2816
|
-
// return access control conditions and payment conditions tuple
|
|
2817
|
-
return [
|
|
2818
|
-
await Promise.all(topArgs.paymentConditions.map(async (condition) => {
|
|
2819
|
-
switch (condition.type) {
|
|
2820
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
2821
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
2822
|
-
key: '$.tx_responses.*.timestamp',
|
|
2823
|
-
comparator: '<=',
|
|
2824
|
-
value: `${condition.intervalInSeconds}`,
|
|
2825
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight);
|
|
2826
|
-
default:
|
|
2827
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
2828
|
-
}
|
|
2829
|
-
})),
|
|
2830
|
-
topArgs.paymentConditions,
|
|
2831
|
-
];
|
|
2832
|
-
})();
|
|
2833
|
-
// encrypt bitstring - case: threshold
|
|
2834
|
-
const { encryptedString: thresholdEncryptionCiphertext, stringHash: thresholdEncryptionStringHash, } = await lit.encrypt((0, uint8arrays_1.fromString)(bitstring, 'base64url'), unifiedAccessControlConditionsTuple[0]);
|
|
2835
|
-
// construct encoded list
|
|
2836
|
-
const encodedList = `${await (0, helpers_js_1.blobToHexString)(symmetricEncryptionCiphertext)}-${(0, uint8arrays_1.toString)(thresholdEncryptionCiphertext, 'hex')}`;
|
|
2837
|
-
// define status list content
|
|
2838
|
-
const content = {
|
|
2839
|
-
StatusList2021: {
|
|
2840
|
-
statusPurpose: publishedList.StatusList2021.statusPurpose,
|
|
2841
|
-
encodedList,
|
|
2842
|
-
validFrom: publishedList.StatusList2021.validFrom,
|
|
2843
|
-
validUntil: options?.publishOptions?.statusListValidUntil ||
|
|
2844
|
-
publishedList.StatusList2021.validUntil,
|
|
2845
|
-
},
|
|
2846
|
-
metadata: {
|
|
2847
|
-
type: publishedList.metadata.type,
|
|
2848
|
-
encrypted: true,
|
|
2849
|
-
encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
|
|
2850
|
-
statusListHash: symmetricEncryptionStringHash === thresholdEncryptionStringHash
|
|
2851
|
-
? symmetricEncryptionStringHash
|
|
2852
|
-
: (function () {
|
|
2853
|
-
throw new Error('[did-provider-cheqd]: suspension: symmetricEncryptionStringHash and thresholdEncryptionStringHash do not match');
|
|
2854
|
-
})(),
|
|
2855
|
-
paymentConditions: unifiedAccessControlConditionsTuple[1],
|
|
2856
|
-
},
|
|
2857
|
-
};
|
|
2858
|
-
// return tuple of publish result and encryption relevant metadata
|
|
2859
|
-
return [
|
|
2860
|
-
await Cheqd.publishStatusList2021((0, uint8arrays_1.fromString)(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
|
|
2861
|
-
{
|
|
2862
|
-
symmetricEncryptionCiphertext,
|
|
2863
|
-
thresholdEncryptionCiphertext,
|
|
2864
|
-
stringHash: symmetricEncryptionStringHash,
|
|
2865
|
-
symmetricKey,
|
|
2866
|
-
},
|
|
2867
|
-
];
|
|
2868
|
-
})()
|
|
2869
|
-
: await (async function () {
|
|
2870
|
-
// validate encoding, if provided
|
|
2871
|
-
if (options?.publishOptions?.statusListEncoding &&
|
|
2872
|
-
!Object.values(cheqd_did_provider_js_1.DefaultStatusList2021Encodings).includes(options?.publishOptions?.statusListEncoding)) {
|
|
2873
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list encoding');
|
|
2874
|
-
}
|
|
2875
|
-
// validate validUntil, if provided
|
|
2876
|
-
if (options?.publishOptions?.statusListValidUntil) {
|
|
2877
|
-
// validate validUntil as string
|
|
2878
|
-
if (typeof options?.publishOptions?.statusListValidUntil !== 'string')
|
|
2879
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be string)');
|
|
2880
|
-
// validate validUntil as date
|
|
2881
|
-
if (isNaN(Date.parse(options?.publishOptions?.statusListValidUntil)))
|
|
2882
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be date)');
|
|
2883
|
-
// validate validUntil as future date
|
|
2884
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) < new Date())
|
|
2885
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be future date)');
|
|
2886
|
-
// validate validUntil towards validFrom
|
|
2887
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) <=
|
|
2888
|
-
new Date(publishedList.StatusList2021.validFrom))
|
|
2889
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be after validFrom)');
|
|
2890
|
-
}
|
|
2891
|
-
// define status list content
|
|
2892
|
-
const content = {
|
|
2893
|
-
StatusList2021: {
|
|
2894
|
-
statusPurpose: publishedList.StatusList2021.statusPurpose,
|
|
2895
|
-
encodedList: publishedList.metadata.encoding === 'base64url'
|
|
2896
|
-
? bitstring
|
|
2897
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(bitstring, 'base64url'), options.publishOptions
|
|
2898
|
-
.statusListEncoding),
|
|
2899
|
-
validFrom: publishedList.StatusList2021.validFrom,
|
|
2900
|
-
validUntil: options?.publishOptions?.statusListValidUntil ||
|
|
2901
|
-
publishedList.StatusList2021.validUntil,
|
|
2902
|
-
},
|
|
2903
|
-
metadata: {
|
|
2904
|
-
type: publishedList.metadata.type,
|
|
2905
|
-
encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
|
|
2906
|
-
encrypted: false,
|
|
2907
|
-
},
|
|
2908
|
-
};
|
|
2909
|
-
// return tuple of publish result and encryption relevant metadata
|
|
2910
|
-
return [
|
|
2911
|
-
await Cheqd.publishStatusList2021((0, uint8arrays_1.fromString)(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
|
|
2912
|
-
undefined,
|
|
2913
|
-
];
|
|
2914
|
-
})();
|
|
2915
|
-
// early exit, if publish failed
|
|
2916
|
-
if (!scoped[0])
|
|
2917
|
-
throw new Error('[did-provider-cheqd]: suspension: Failed to publish status list 2021');
|
|
2918
|
-
// return publish result
|
|
2919
|
-
return scoped;
|
|
2920
|
-
})()
|
|
2921
|
-
: undefined;
|
|
2922
|
-
return {
|
|
2923
|
-
suspended: true,
|
|
2924
|
-
published: topArgs?.publish ? true : undefined,
|
|
2925
|
-
statusList: topArgs?.returnUpdatedStatusList
|
|
2926
|
-
? (await Cheqd.fetchStatusList2021(credential))
|
|
2927
|
-
: undefined,
|
|
2928
|
-
symmetricKey: topArgs?.returnSymmetricKey
|
|
2929
|
-
? (0, uint8arrays_1.toString)(published?.[1]?.symmetricKey, 'hex')
|
|
2930
|
-
: undefined,
|
|
2931
|
-
resourceMetadata: topArgs?.returnStatusListMetadata
|
|
2932
|
-
? await Cheqd.fetchStatusList2021Metadata(credential)
|
|
2933
|
-
: undefined,
|
|
2934
|
-
};
|
|
2935
|
-
}
|
|
2936
|
-
catch (error) {
|
|
2937
|
-
// silent fail + early exit
|
|
2938
|
-
console.error(error);
|
|
2939
|
-
return { suspended: false, error: error };
|
|
2940
|
-
}
|
|
2941
|
-
}
|
|
2942
|
-
static async suspendCredentials(credentials, options) {
|
|
2943
|
-
// validate credentials - case: empty
|
|
2944
|
-
if (!credentials.length || credentials.length === 0)
|
|
2945
|
-
throw new Error('[did-provider-cheqd]: suspension: No credentials provided');
|
|
2946
|
-
// validate credentials - case: consistent issuer
|
|
2947
|
-
if (credentials
|
|
2948
|
-
.map((credential) => {
|
|
2949
|
-
return credential.issuer.id
|
|
2950
|
-
? credential.issuer.id
|
|
2951
|
-
: credential.issuer;
|
|
2952
|
-
})
|
|
2953
|
-
.filter((value, _, self) => value && value !== self[0]).length > 0)
|
|
2954
|
-
throw new Error('[did-provider-cheqd]: suspension: Credentials must be issued by the same issuer');
|
|
2955
|
-
// validate credentials - case: status list index
|
|
2956
|
-
if (credentials
|
|
2957
|
-
.map((credential) => credential.credentialStatus.statusListIndex)
|
|
2958
|
-
.filter((value, index, self) => self.indexOf(value) !== index).length > 0)
|
|
2959
|
-
throw new Error('[did-provider-cheqd]: suspension: Credentials must have unique status list index');
|
|
2960
|
-
// validate credentials - case: status purpose
|
|
2961
|
-
if (!credentials.every((credential) => credential.credentialStatus?.statusPurpose === cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension))
|
|
2962
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status purpose');
|
|
2963
|
-
// validate credentials - case: status list id
|
|
2964
|
-
const remote = credentials[0].credentialStatus?.id
|
|
2965
|
-
? credentials[0].credentialStatus.id.split('#')[0]
|
|
2966
|
-
: (function () {
|
|
2967
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list id');
|
|
2968
|
-
})();
|
|
2969
|
-
// validate credentials - case: status list id format
|
|
2970
|
-
if (!exports.RemoteListPattern.test(remote))
|
|
2971
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list id format: expected: https://<optional_subdomain>.<sld>.<tld>/1.0/identifiers/<did:cheqd:<namespace>:<method_specific_id>>?resourceName=<resource_name>&resourceType=<resource_type>');
|
|
2972
|
-
if (!credentials.every((credential) => {
|
|
2973
|
-
return credential.credentialStatus.id.split('#')[0] === remote;
|
|
2974
|
-
}))
|
|
2975
|
-
throw new Error('[did-provider-cheqd]: suspension: Credentials must belong to the same status list');
|
|
2976
|
-
// validate credentials - case: status list type
|
|
2977
|
-
if (!credentials.every((credential) => credential.credentialStatus?.type === 'StatusList2021Entry'))
|
|
2978
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list type');
|
|
2979
|
-
try {
|
|
2980
|
-
// fetch status list 2021
|
|
2981
|
-
const publishedList = (await Cheqd.fetchStatusList2021(credentials[0]));
|
|
2982
|
-
// early return, if encrypted and no decryption key provided
|
|
2983
|
-
if (publishedList.metadata.encrypted && !options?.topArgs?.symmetricKey)
|
|
2984
|
-
throw new Error('[did-provider-cheqd]: suspension: symmetricKey is required, if status list 2021 is encrypted');
|
|
2985
|
-
// fetch status list 2021 inscribed in credential
|
|
2986
|
-
const statusList2021 = options?.topArgs?.fetchList
|
|
2987
|
-
? await (async function () {
|
|
2988
|
-
// if not encrypted, return bitstring
|
|
2989
|
-
if (!publishedList.metadata.encrypted)
|
|
2990
|
-
return publishedList.metadata.encoding === 'base64url'
|
|
2991
|
-
? publishedList.StatusList2021.encodedList
|
|
2992
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
2993
|
-
// decrypt + return bitstring, if qualified for migration
|
|
2994
|
-
if (publishedList.metadata.encryptedSymmetricKey)
|
|
2995
|
-
return await v2_js_1.LitProtocolV2.decryptDirect(await (0, helpers_js_1.toBlob)((0, uint8arrays_1.fromString)(publishedList.StatusList2021
|
|
2996
|
-
.encodedList, 'hex')), (0, uint8arrays_1.fromString)(options?.topArgs?.symmetricKey, 'hex'));
|
|
2997
|
-
// validate encoded list
|
|
2998
|
-
if (!(0, helpers_js_1.isEncodedList)(publishedList.StatusList2021.encodedList))
|
|
2999
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid encoded list');
|
|
3000
|
-
// otherwise, decrypt and return raw bitstring
|
|
3001
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)((0, uint8arrays_1.fromString)((0, helpers_js_1.getEncodedList)(publishedList.StatusList2021.encodedList, false)[0], 'hex'));
|
|
3002
|
-
// decrypt
|
|
3003
|
-
return (0, uint8arrays_1.toString)(await v6_js_1.LitProtocol.decryptDirect(scopedRawBlob, await (0, helpers_js_1.safeDeserialise)(options?.topArgs?.symmetricKey, uint8arrays_1.fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
|
|
3004
|
-
})()
|
|
3005
|
-
: await (async function () {
|
|
3006
|
-
// transcode to base64url, if needed
|
|
3007
|
-
const publishedListTranscoded = publishedList.metadata.encoding === 'base64url'
|
|
3008
|
-
? publishedList.StatusList2021.encodedList
|
|
3009
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
3010
|
-
// if status list 2021 is not fetched, read from file
|
|
3011
|
-
if (options?.statusListFile) {
|
|
3012
|
-
// if not encrypted, return bitstring
|
|
3013
|
-
if (!publishedList.metadata.encrypted) {
|
|
3014
|
-
// construct encoded status list
|
|
3015
|
-
const encoded = new vc_status_list_1.StatusList({
|
|
3016
|
-
buffer: await Cheqd.getFile(options.statusListFile),
|
|
3017
|
-
}).encode();
|
|
3018
|
-
// validate against published list
|
|
3019
|
-
if (encoded !== publishedListTranscoded)
|
|
3020
|
-
throw new Error('[did-provider-cheqd]: suspension: statusListFile does not match published status list 2021');
|
|
3021
|
-
// return encoded
|
|
3022
|
-
return encoded;
|
|
3023
|
-
}
|
|
3024
|
-
// otherwise, decrypt and return bitstring
|
|
3025
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)(await Cheqd.getFile(options.statusListFile));
|
|
3026
|
-
// decrypt
|
|
3027
|
-
const decrypted = (0, uint8arrays_1.toString)(await v6_js_1.LitProtocol.decryptDirect(scopedRawBlob, await (0, helpers_js_1.safeDeserialise)(options?.topArgs?.symmetricKey, uint8arrays_1.fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
|
|
3028
|
-
// validate against published list
|
|
3029
|
-
if (decrypted !== publishedListTranscoded)
|
|
3030
|
-
throw new Error('[did-provider-cheqd]: suspension: statusListFile does not match published status list 2021');
|
|
3031
|
-
// return decrypted
|
|
3032
|
-
return decrypted;
|
|
3033
|
-
}
|
|
3034
|
-
if (!options?.statusListInlineBitstring)
|
|
3035
|
-
throw new Error('[did-provider-cheqd]: suspension: statusListInlineBitstring is required, if statusListFile is not provided');
|
|
3036
|
-
// validate against published list
|
|
3037
|
-
if (options?.statusListInlineBitstring !== publishedListTranscoded)
|
|
3038
|
-
throw new Error('[did-provider-cheqd]: suspension: statusListInlineBitstring does not match published status list 2021');
|
|
3039
|
-
// otherwise, read from inline bitstring
|
|
3040
|
-
return options?.statusListInlineBitstring;
|
|
3041
|
-
})();
|
|
3042
|
-
// parse status list 2021
|
|
3043
|
-
const statusList = await vc_status_list_1.StatusList.decode({ encodedList: statusList2021 });
|
|
3044
|
-
// initiate bulk suspension
|
|
3045
|
-
const suspended = (await Promise.allSettled(credentials.map((credential) => {
|
|
3046
|
-
return (async function () {
|
|
3047
|
-
// early return, if no credential status
|
|
3048
|
-
if (!credential.credentialStatus)
|
|
3049
|
-
return { suspended: false };
|
|
3050
|
-
// early exit, if credential is already suspended
|
|
3051
|
-
if (statusList.getStatus(Number(credential.credentialStatus.statusListIndex)))
|
|
3052
|
-
return { suspended: true };
|
|
3053
|
-
// update suspension status
|
|
3054
|
-
statusList.setStatus(Number(credential.credentialStatus.statusListIndex), true);
|
|
3055
|
-
// return suspension status
|
|
3056
|
-
return { suspended: true };
|
|
3057
|
-
})();
|
|
3058
|
-
})));
|
|
3059
|
-
// revert bulk ops, if some failed
|
|
3060
|
-
if (suspended.some((result) => result.status === 'fulfilled' && !result.value.suspended))
|
|
3061
|
-
throw new Error(`[did-provider-cheqd]: suspension: Bulk suspension failed: already suspended credentials in suspension bundle: raw log: ${JSON.stringify(suspended.map((result) => ({
|
|
3062
|
-
suspended: result.status === 'fulfilled' ? result.value.suspended : false,
|
|
3063
|
-
})))}`);
|
|
3064
|
-
// set in-memory status list ref
|
|
3065
|
-
const bitstring = (await statusList.encode());
|
|
3066
|
-
// cast top-level args
|
|
3067
|
-
const topArgs = options?.topArgs;
|
|
3068
|
-
// write status list 2021 to file, if provided
|
|
3069
|
-
if (topArgs?.writeToFile) {
|
|
3070
|
-
await Cheqd.writeFile((0, uint8arrays_1.fromString)(bitstring, 'base64url'), options?.statusListFile);
|
|
3071
|
-
}
|
|
3072
|
-
// publish status list 2021, if provided
|
|
3073
|
-
const published = topArgs?.publish
|
|
3074
|
-
? await (async function () {
|
|
3075
|
-
// fetch status list 2021 metadata
|
|
3076
|
-
const statusListMetadata = await Cheqd.fetchStatusList2021Metadata(credentials[0]);
|
|
3077
|
-
// publish status list 2021 as new version
|
|
3078
|
-
const scoped = topArgs.publishEncrypted
|
|
3079
|
-
? await (async function () {
|
|
3080
|
-
// validate encoding, if provided
|
|
3081
|
-
if (options?.publishOptions?.statusListEncoding &&
|
|
3082
|
-
!Object.values(cheqd_did_provider_js_1.DefaultStatusList2021Encodings).includes(options?.publishOptions?.statusListEncoding)) {
|
|
3083
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list encoding');
|
|
3084
|
-
}
|
|
3085
|
-
// validate validUntil, if provided
|
|
3086
|
-
if (options?.publishOptions?.statusListValidUntil) {
|
|
3087
|
-
// validate validUntil as string
|
|
3088
|
-
if (typeof options?.publishOptions?.statusListValidUntil !== 'string')
|
|
3089
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be string)');
|
|
3090
|
-
// validate validUntil as date
|
|
3091
|
-
if (isNaN(Date.parse(options?.publishOptions?.statusListValidUntil)))
|
|
3092
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be date)');
|
|
3093
|
-
// validate validUntil as future date
|
|
3094
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) < new Date())
|
|
3095
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be future date)');
|
|
3096
|
-
// validate validUntil towards validFrom
|
|
3097
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) <=
|
|
3098
|
-
new Date(publishedList.StatusList2021.validFrom))
|
|
3099
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be after validFrom)');
|
|
3100
|
-
}
|
|
3101
|
-
// validate paymentConditions, if provided
|
|
3102
|
-
if (topArgs?.paymentConditions) {
|
|
3103
|
-
if (!topArgs?.paymentConditions?.every((condition) => condition.feePaymentAddress &&
|
|
3104
|
-
condition.feePaymentAmount &&
|
|
3105
|
-
condition.intervalInSeconds)) {
|
|
3106
|
-
throw new Error('[did-provider-cheqd]: paymentConditions must contain feePaymentAddress and feeAmount and intervalInSeconds');
|
|
3107
|
-
}
|
|
3108
|
-
if (!topArgs?.paymentConditions?.every((condition) => typeof condition.feePaymentAddress === 'string' &&
|
|
3109
|
-
typeof condition.feePaymentAmount === 'string' &&
|
|
3110
|
-
typeof condition.intervalInSeconds === 'number')) {
|
|
3111
|
-
throw new Error('[did-provider-cheqd]: feePaymentAddress and feePaymentAmount must be string and intervalInSeconds must be number');
|
|
3112
|
-
}
|
|
3113
|
-
if (!topArgs?.paymentConditions?.every((condition) => condition.type === exports.AccessControlConditionTypes.timelockPayment)) {
|
|
3114
|
-
throw new Error('[did-provider-cheqd]: paymentConditions must be of type timelockPayment');
|
|
3115
|
-
}
|
|
3116
|
-
}
|
|
3117
|
-
// validate dkgOptions
|
|
3118
|
-
if (!topArgs?.dkgOptions ||
|
|
3119
|
-
!topArgs?.dkgOptions?.chain ||
|
|
3120
|
-
!topArgs?.dkgOptions?.network) {
|
|
3121
|
-
throw new Error('[did-provider-cheqd]: dkgOptions is required');
|
|
3122
|
-
}
|
|
3123
|
-
// encrypt bitstring - case: symmetric
|
|
3124
|
-
const { encryptedString: symmetricEncryptionCiphertext, stringHash: symmetricEncryptionStringHash, symmetricKey, } = await v6_js_1.LitProtocol.encryptDirect((0, uint8arrays_1.fromString)(bitstring, 'base64url'));
|
|
3125
|
-
// instantiate dkg-threshold client, in which case lit-protocol is used
|
|
3126
|
-
const lit = (await options.publishOptions.instantiateDkgClient);
|
|
3127
|
-
// construct access control conditions and payment conditions tuple
|
|
3128
|
-
const unifiedAccessControlConditionsTuple = publishedList.metadata.encrypted
|
|
3129
|
-
? await (async function () {
|
|
3130
|
-
// define payment conditions, give precedence to top-level args
|
|
3131
|
-
const paymentConditions = topArgs?.paymentConditions ||
|
|
3132
|
-
publishedList.metadata.paymentConditions;
|
|
3133
|
-
// return access control conditions and payment conditions tuple
|
|
3134
|
-
return [
|
|
3135
|
-
await Promise.all(paymentConditions.map(async (condition) => {
|
|
3136
|
-
switch (condition.type) {
|
|
3137
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
3138
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
3139
|
-
key: '$.tx_responses.*.timestamp',
|
|
3140
|
-
comparator: '<=',
|
|
3141
|
-
value: `${condition.intervalInSeconds}`,
|
|
3142
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight, topArgs?.dkgOptions?.chain);
|
|
3143
|
-
default:
|
|
3144
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
3145
|
-
}
|
|
3146
|
-
})),
|
|
3147
|
-
paymentConditions,
|
|
3148
|
-
];
|
|
3149
|
-
})()
|
|
3150
|
-
: await (async function () {
|
|
3151
|
-
// validate paymentConditions
|
|
3152
|
-
if (!topArgs?.paymentConditions) {
|
|
3153
|
-
throw new Error('[did-provider-cheqd]: paymentConditions is required');
|
|
3154
|
-
}
|
|
3155
|
-
// return access control conditions and payment conditions tuple
|
|
3156
|
-
return [
|
|
3157
|
-
await Promise.all(topArgs.paymentConditions.map(async (condition) => {
|
|
3158
|
-
switch (condition.type) {
|
|
3159
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
3160
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
3161
|
-
key: '$.tx_responses.*.timestamp',
|
|
3162
|
-
comparator: '<=',
|
|
3163
|
-
value: `${condition.intervalInSeconds}`,
|
|
3164
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight);
|
|
3165
|
-
default:
|
|
3166
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
3167
|
-
}
|
|
3168
|
-
})),
|
|
3169
|
-
topArgs.paymentConditions,
|
|
3170
|
-
];
|
|
3171
|
-
})();
|
|
3172
|
-
// encrypt bitstring - case: threshold
|
|
3173
|
-
const { encryptedString: thresholdEncryptionCiphertext, stringHash: thresholdEncryptionStringHash, } = await lit.encrypt((0, uint8arrays_1.fromString)(bitstring, 'base64url'), unifiedAccessControlConditionsTuple[0]);
|
|
3174
|
-
// construct encoded list
|
|
3175
|
-
const encodedList = `${await (0, helpers_js_1.blobToHexString)(symmetricEncryptionCiphertext)}-${(0, uint8arrays_1.toString)(thresholdEncryptionCiphertext, 'hex')}`;
|
|
3176
|
-
// define status list content
|
|
3177
|
-
const content = {
|
|
3178
|
-
StatusList2021: {
|
|
3179
|
-
statusPurpose: publishedList.StatusList2021.statusPurpose,
|
|
3180
|
-
encodedList,
|
|
3181
|
-
validFrom: publishedList.StatusList2021.validFrom,
|
|
3182
|
-
validUntil: options?.publishOptions?.statusListValidUntil ||
|
|
3183
|
-
publishedList.StatusList2021.validUntil,
|
|
3184
|
-
},
|
|
3185
|
-
metadata: {
|
|
3186
|
-
type: publishedList.metadata.type,
|
|
3187
|
-
encrypted: true,
|
|
3188
|
-
encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
|
|
3189
|
-
statusListHash: symmetricEncryptionStringHash === thresholdEncryptionStringHash
|
|
3190
|
-
? symmetricEncryptionStringHash
|
|
3191
|
-
: (function () {
|
|
3192
|
-
throw new Error('[did-provider-cheqd]: suspension: symmetricEncryptionStringHash and thresholdEncryptionStringHash do not match');
|
|
3193
|
-
})(),
|
|
3194
|
-
paymentConditions: unifiedAccessControlConditionsTuple[1],
|
|
3195
|
-
},
|
|
3196
|
-
};
|
|
3197
|
-
// return tuple of publish result and encryption relevant metadata
|
|
3198
|
-
return [
|
|
3199
|
-
await Cheqd.publishStatusList2021((0, uint8arrays_1.fromString)(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
|
|
3200
|
-
{
|
|
3201
|
-
symmetricEncryptionCiphertext,
|
|
3202
|
-
thresholdEncryptionCiphertext,
|
|
3203
|
-
stringHash: symmetricEncryptionStringHash,
|
|
3204
|
-
symmetricKey,
|
|
3205
|
-
},
|
|
3206
|
-
];
|
|
3207
|
-
})()
|
|
3208
|
-
: await (async function () {
|
|
3209
|
-
// validate encoding, if provided
|
|
3210
|
-
if (options?.publishOptions?.statusListEncoding &&
|
|
3211
|
-
!Object.values(cheqd_did_provider_js_1.DefaultStatusList2021Encodings).includes(options?.publishOptions?.statusListEncoding)) {
|
|
3212
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list encoding');
|
|
3213
|
-
}
|
|
3214
|
-
// validate validUntil, if provided
|
|
3215
|
-
if (options?.publishOptions?.statusListValidUntil) {
|
|
3216
|
-
// validate validUntil as string
|
|
3217
|
-
if (typeof options?.publishOptions?.statusListValidUntil !== 'string')
|
|
3218
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be string)');
|
|
3219
|
-
// validate validUntil as date
|
|
3220
|
-
if (isNaN(Date.parse(options?.publishOptions?.statusListValidUntil)))
|
|
3221
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be date)');
|
|
3222
|
-
// validate validUntil as future date
|
|
3223
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) < new Date())
|
|
3224
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be future date)');
|
|
3225
|
-
// validate validUntil towards validFrom
|
|
3226
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) <=
|
|
3227
|
-
new Date(publishedList.StatusList2021.validFrom))
|
|
3228
|
-
throw new Error('[did-provider-cheqd]: suspension: Invalid status list validUntil (must be after validFrom)');
|
|
3229
|
-
}
|
|
3230
|
-
// define status list content
|
|
3231
|
-
const content = {
|
|
3232
|
-
StatusList2021: {
|
|
3233
|
-
statusPurpose: publishedList.StatusList2021.statusPurpose,
|
|
3234
|
-
encodedList: publishedList.metadata.encoding === 'base64url'
|
|
3235
|
-
? bitstring
|
|
3236
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(bitstring, 'base64url'), options.publishOptions
|
|
3237
|
-
.statusListEncoding),
|
|
3238
|
-
validFrom: publishedList.StatusList2021.validFrom,
|
|
3239
|
-
validUntil: options?.publishOptions?.statusListValidUntil ||
|
|
3240
|
-
publishedList.StatusList2021.validUntil,
|
|
3241
|
-
},
|
|
3242
|
-
metadata: {
|
|
3243
|
-
type: publishedList.metadata.type,
|
|
3244
|
-
encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
|
|
3245
|
-
encrypted: false,
|
|
3246
|
-
},
|
|
3247
|
-
};
|
|
3248
|
-
// return tuple of publish result and encryption relevant metadata
|
|
3249
|
-
return [
|
|
3250
|
-
await Cheqd.publishStatusList2021((0, uint8arrays_1.fromString)(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
|
|
3251
|
-
undefined,
|
|
3252
|
-
];
|
|
3253
|
-
})();
|
|
3254
|
-
// early exit, if publish failed
|
|
3255
|
-
if (!scoped[0])
|
|
3256
|
-
throw new Error('[did-provider-cheqd]: suspension: Failed to publish status list 2021');
|
|
3257
|
-
// return publish result
|
|
3258
|
-
return scoped;
|
|
3259
|
-
})()
|
|
3260
|
-
: undefined;
|
|
3261
|
-
return {
|
|
3262
|
-
suspended: suspended.map((result) => (result.status === 'fulfilled' ? result.value.suspended : false)),
|
|
3263
|
-
published: topArgs?.publish ? true : undefined,
|
|
3264
|
-
statusList: topArgs?.returnUpdatedStatusList
|
|
3265
|
-
? (await Cheqd.fetchStatusList2021(credentials[0]))
|
|
3266
|
-
: undefined,
|
|
3267
|
-
symmetricKey: topArgs?.returnSymmetricKey
|
|
3268
|
-
? (0, uint8arrays_1.toString)(published?.[1]?.symmetricKey, 'hex')
|
|
3269
|
-
: undefined,
|
|
3270
|
-
resourceMetadata: topArgs?.returnStatusListMetadata
|
|
3271
|
-
? await Cheqd.fetchStatusList2021Metadata(credentials[0])
|
|
3272
|
-
: undefined,
|
|
3273
|
-
};
|
|
3274
|
-
}
|
|
3275
|
-
catch (error) {
|
|
3276
|
-
// silent fail + early exit
|
|
3277
|
-
console.error(error);
|
|
3278
|
-
return { suspended: [], error: error };
|
|
3279
|
-
}
|
|
3280
|
-
}
|
|
3281
|
-
static async unsuspendCredential(credential, options) {
|
|
3282
|
-
try {
|
|
3283
|
-
// validate status purpose
|
|
3284
|
-
if (credential?.credentialStatus?.statusPurpose !== cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension)
|
|
3285
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status purpose');
|
|
3286
|
-
// fetch status list 2021
|
|
3287
|
-
const publishedList = (await Cheqd.fetchStatusList2021(credential));
|
|
3288
|
-
// early return, if encrypted and no decryption key provided
|
|
3289
|
-
if (publishedList.metadata.encrypted && !options?.topArgs?.symmetricKey)
|
|
3290
|
-
throw new Error('[did-provider-cheqd]: unsuspension: symmetricKey is required, if status list 2021 is encrypted');
|
|
3291
|
-
// fetch status list 2021 inscribed in credential
|
|
3292
|
-
const statusList2021 = options?.topArgs?.fetchList
|
|
3293
|
-
? await (async function () {
|
|
3294
|
-
// if not encrypted, return bitstring
|
|
3295
|
-
if (!publishedList.metadata.encrypted)
|
|
3296
|
-
return publishedList.metadata.encoding === 'base64url'
|
|
3297
|
-
? publishedList.StatusList2021.encodedList
|
|
3298
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
3299
|
-
// decrypt + return bitstring, if qualified for migration
|
|
3300
|
-
if (publishedList.metadata.encryptedSymmetricKey)
|
|
3301
|
-
return await v2_js_1.LitProtocolV2.decryptDirect(await (0, helpers_js_1.toBlob)((0, uint8arrays_1.fromString)(publishedList.StatusList2021
|
|
3302
|
-
.encodedList, 'hex')), (0, uint8arrays_1.fromString)(options?.topArgs?.symmetricKey, 'hex'));
|
|
3303
|
-
// validate encoded list
|
|
3304
|
-
if (!(0, helpers_js_1.isEncodedList)(publishedList.StatusList2021.encodedList))
|
|
3305
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid encoded list');
|
|
3306
|
-
// otherwise, decrypt and return raw bitstring
|
|
3307
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)((0, uint8arrays_1.fromString)((0, helpers_js_1.getEncodedList)(publishedList.StatusList2021.encodedList, false)[0], 'hex'));
|
|
3308
|
-
// decrypt
|
|
3309
|
-
return (0, uint8arrays_1.toString)(await v6_js_1.LitProtocol.decryptDirect(scopedRawBlob, await (0, helpers_js_1.safeDeserialise)(options?.topArgs?.symmetricKey, uint8arrays_1.fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
|
|
3310
|
-
})()
|
|
3311
|
-
: await (async function () {
|
|
3312
|
-
// transcode to base64url, if needed
|
|
3313
|
-
const publishedListTranscoded = publishedList.metadata.encoding === 'base64url'
|
|
3314
|
-
? publishedList.StatusList2021.encodedList
|
|
3315
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
3316
|
-
// if status list 2021 is not fetched, read from file
|
|
3317
|
-
if (options?.statusListFile) {
|
|
3318
|
-
// if not encrypted, return bitstring
|
|
3319
|
-
if (!publishedList.metadata.encrypted) {
|
|
3320
|
-
// construct encoded status list
|
|
3321
|
-
const encoded = new vc_status_list_1.StatusList({
|
|
3322
|
-
buffer: await Cheqd.getFile(options.statusListFile),
|
|
3323
|
-
}).encode();
|
|
3324
|
-
// validate against published list
|
|
3325
|
-
if (encoded !== publishedListTranscoded)
|
|
3326
|
-
throw new Error('[did-provider-cheqd]: unsuspension: statusListFile does not match published status list 2021');
|
|
3327
|
-
// return encoded
|
|
3328
|
-
return encoded;
|
|
3329
|
-
}
|
|
3330
|
-
// otherwise, decrypt and return bitstring
|
|
3331
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)(await Cheqd.getFile(options.statusListFile));
|
|
3332
|
-
// decrypt
|
|
3333
|
-
const decrypted = (0, uint8arrays_1.toString)(await v6_js_1.LitProtocol.decryptDirect(scopedRawBlob, await (0, helpers_js_1.safeDeserialise)(options?.topArgs?.symmetricKey, uint8arrays_1.fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
|
|
3334
|
-
// validate against published list
|
|
3335
|
-
if (decrypted !== publishedListTranscoded)
|
|
3336
|
-
throw new Error('[did-provider-cheqd]: unsuspension: statusListFile does not match published status list 2021');
|
|
3337
|
-
// return decrypted
|
|
3338
|
-
return decrypted;
|
|
3339
|
-
}
|
|
3340
|
-
if (!options?.statusListInlineBitstring)
|
|
3341
|
-
throw new Error('[did-provider-cheqd]: unsuspension: statusListInlineBitstring is required, if statusListFile is not provided');
|
|
3342
|
-
// validate against published list
|
|
3343
|
-
if (options?.statusListInlineBitstring !== publishedListTranscoded)
|
|
3344
|
-
throw new Error('[did-provider-cheqd]: unsuspension: statusListInlineBitstring does not match published status list 2021');
|
|
3345
|
-
// otherwise, read from inline bitstring
|
|
3346
|
-
return options?.statusListInlineBitstring;
|
|
3347
|
-
})();
|
|
3348
|
-
// parse status list 2021
|
|
3349
|
-
const statusList = await vc_status_list_1.StatusList.decode({ encodedList: statusList2021 });
|
|
3350
|
-
// early exit, if already unsuspended
|
|
3351
|
-
if (!statusList.getStatus(Number(credential.credentialStatus.statusListIndex)))
|
|
3352
|
-
return { unsuspended: true };
|
|
3353
|
-
// update suspension status
|
|
3354
|
-
statusList.setStatus(Number(credential.credentialStatus.statusListIndex), false);
|
|
3355
|
-
// set in-memory status list ref
|
|
3356
|
-
const bitstring = (await statusList.encode());
|
|
3357
|
-
// cast top-level args
|
|
3358
|
-
const topArgs = options?.topArgs;
|
|
3359
|
-
// write status list 2021 to file, if provided
|
|
3360
|
-
if (topArgs?.writeToFile) {
|
|
3361
|
-
await Cheqd.writeFile((0, uint8arrays_1.fromString)(bitstring, 'base64url'), options?.statusListFile);
|
|
3362
|
-
}
|
|
3363
|
-
// publish status list 2021, if provided
|
|
3364
|
-
const published = topArgs?.publish
|
|
3365
|
-
? await (async function () {
|
|
3366
|
-
// fetch status list 2021 metadata
|
|
3367
|
-
const statusListMetadata = await Cheqd.fetchStatusList2021Metadata(credential);
|
|
3368
|
-
// publish status list 2021 as new version
|
|
3369
|
-
const scoped = topArgs.publishEncrypted
|
|
3370
|
-
? await (async function () {
|
|
3371
|
-
// validate encoding, if provided
|
|
3372
|
-
if (options?.publishOptions?.statusListEncoding &&
|
|
3373
|
-
!Object.values(cheqd_did_provider_js_1.DefaultStatusList2021Encodings).includes(options?.publishOptions?.statusListEncoding)) {
|
|
3374
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list encoding');
|
|
3375
|
-
}
|
|
3376
|
-
// validate validUntil, if provided
|
|
3377
|
-
if (options?.publishOptions?.statusListValidUntil) {
|
|
3378
|
-
// validate validUntil as string
|
|
3379
|
-
if (typeof options?.publishOptions?.statusListValidUntil !== 'string')
|
|
3380
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be string)');
|
|
3381
|
-
// validate validUntil as date
|
|
3382
|
-
if (isNaN(Date.parse(options?.publishOptions?.statusListValidUntil)))
|
|
3383
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be date)');
|
|
3384
|
-
// validate validUntil as future date
|
|
3385
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) < new Date())
|
|
3386
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be future date)');
|
|
3387
|
-
// validate validUntil towards validFrom
|
|
3388
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) <=
|
|
3389
|
-
new Date(publishedList.StatusList2021.validFrom))
|
|
3390
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be after validFrom)');
|
|
3391
|
-
}
|
|
3392
|
-
// validate paymentConditions, if provided
|
|
3393
|
-
if (topArgs?.paymentConditions) {
|
|
3394
|
-
if (!topArgs?.paymentConditions?.every((condition) => condition.feePaymentAddress &&
|
|
3395
|
-
condition.feePaymentAmount &&
|
|
3396
|
-
condition.intervalInSeconds)) {
|
|
3397
|
-
throw new Error('[did-provider-cheqd]: paymentConditions must contain feePaymentAddress and feeAmount and intervalInSeconds');
|
|
3398
|
-
}
|
|
3399
|
-
if (!topArgs?.paymentConditions?.every((condition) => typeof condition.feePaymentAddress === 'string' &&
|
|
3400
|
-
typeof condition.feePaymentAmount === 'string' &&
|
|
3401
|
-
typeof condition.intervalInSeconds === 'number')) {
|
|
3402
|
-
throw new Error('[did-provider-cheqd]: feePaymentAddress and feePaymentAmount must be string and intervalInSeconds must be number');
|
|
3403
|
-
}
|
|
3404
|
-
if (!topArgs?.paymentConditions?.every((condition) => condition.type === exports.AccessControlConditionTypes.timelockPayment)) {
|
|
3405
|
-
throw new Error('[did-provider-cheqd]: paymentConditions must be of type timelockPayment');
|
|
3406
|
-
}
|
|
3407
|
-
}
|
|
3408
|
-
// validate dkgOptions
|
|
3409
|
-
if (!topArgs?.dkgOptions ||
|
|
3410
|
-
!topArgs?.dkgOptions?.chain ||
|
|
3411
|
-
!topArgs?.dkgOptions?.network) {
|
|
3412
|
-
throw new Error('[did-provider-cheqd]: dkgOptions is required');
|
|
3413
|
-
}
|
|
3414
|
-
// encrypt bitstring - case: symmetric
|
|
3415
|
-
const { encryptedString: symmetricEncryptionCiphertext, stringHash: symmetricEncryptionStringHash, symmetricKey, } = await v6_js_1.LitProtocol.encryptDirect((0, uint8arrays_1.fromString)(bitstring, 'base64url'));
|
|
3416
|
-
// instantiate dkg-threshold client, in which case lit-protocol is used
|
|
3417
|
-
const lit = (await options.publishOptions.instantiateDkgClient);
|
|
3418
|
-
// construct access control conditions and payment conditions tuple
|
|
3419
|
-
const unifiedAccessControlConditionsTuple = publishedList.metadata.encrypted
|
|
3420
|
-
? await (async function () {
|
|
3421
|
-
// define payment conditions, give precedence to top-level args
|
|
3422
|
-
const paymentConditions = topArgs?.paymentConditions ||
|
|
3423
|
-
publishedList.metadata.paymentConditions;
|
|
3424
|
-
// return access control conditions and payment conditions tuple
|
|
3425
|
-
return [
|
|
3426
|
-
await Promise.all(paymentConditions.map(async (condition) => {
|
|
3427
|
-
switch (condition.type) {
|
|
3428
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
3429
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
3430
|
-
key: '$.tx_responses.*.timestamp',
|
|
3431
|
-
comparator: '<=',
|
|
3432
|
-
value: `${condition.intervalInSeconds}`,
|
|
3433
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight, topArgs?.dkgOptions?.chain);
|
|
3434
|
-
default:
|
|
3435
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
3436
|
-
}
|
|
3437
|
-
})),
|
|
3438
|
-
paymentConditions,
|
|
3439
|
-
];
|
|
3440
|
-
})()
|
|
3441
|
-
: await (async function () {
|
|
3442
|
-
// validate paymentConditions
|
|
3443
|
-
if (!topArgs?.paymentConditions) {
|
|
3444
|
-
throw new Error('[did-provider-cheqd]: paymentConditions is required');
|
|
3445
|
-
}
|
|
3446
|
-
// return access control conditions and payment conditions tuple
|
|
3447
|
-
return [
|
|
3448
|
-
await Promise.all(topArgs.paymentConditions.map(async (condition) => {
|
|
3449
|
-
switch (condition.type) {
|
|
3450
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
3451
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
3452
|
-
key: '$.tx_responses.*.timestamp',
|
|
3453
|
-
comparator: '<=',
|
|
3454
|
-
value: `${condition.intervalInSeconds}`,
|
|
3455
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight);
|
|
3456
|
-
default:
|
|
3457
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
3458
|
-
}
|
|
3459
|
-
})),
|
|
3460
|
-
topArgs.paymentConditions,
|
|
3461
|
-
];
|
|
3462
|
-
})();
|
|
3463
|
-
// encrypt bitstring - case: threshold
|
|
3464
|
-
const { encryptedString: thresholdEncryptionCiphertext, stringHash: thresholdEncryptionStringHash, } = await lit.encrypt((0, uint8arrays_1.fromString)(bitstring, 'base64url'), unifiedAccessControlConditionsTuple[0]);
|
|
3465
|
-
// construct encoded list
|
|
3466
|
-
const encodedList = `${await (0, helpers_js_1.blobToHexString)(symmetricEncryptionCiphertext)}-${(0, uint8arrays_1.toString)(thresholdEncryptionCiphertext, 'hex')}`;
|
|
3467
|
-
// define status list content
|
|
3468
|
-
const content = {
|
|
3469
|
-
StatusList2021: {
|
|
3470
|
-
statusPurpose: publishedList.StatusList2021.statusPurpose,
|
|
3471
|
-
encodedList,
|
|
3472
|
-
validFrom: publishedList.StatusList2021.validFrom,
|
|
3473
|
-
validUntil: options?.publishOptions?.statusListValidUntil ||
|
|
3474
|
-
publishedList.StatusList2021.validUntil,
|
|
3475
|
-
},
|
|
3476
|
-
metadata: {
|
|
3477
|
-
type: publishedList.metadata.type,
|
|
3478
|
-
encrypted: true,
|
|
3479
|
-
encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
|
|
3480
|
-
statusListHash: symmetricEncryptionStringHash === thresholdEncryptionStringHash
|
|
3481
|
-
? symmetricEncryptionStringHash
|
|
3482
|
-
: (function () {
|
|
3483
|
-
throw new Error('[did-provider-cheqd]: unsuspension: symmetricEncryptionStringHash and thresholdEncryptionStringHash do not match');
|
|
3484
|
-
})(),
|
|
3485
|
-
paymentConditions: unifiedAccessControlConditionsTuple[1],
|
|
3486
|
-
},
|
|
3487
|
-
};
|
|
3488
|
-
// return tuple of publish result and encryption relevant metadata
|
|
3489
|
-
return [
|
|
3490
|
-
await Cheqd.publishStatusList2021((0, uint8arrays_1.fromString)(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
|
|
3491
|
-
{
|
|
3492
|
-
symmetricEncryptionCiphertext,
|
|
3493
|
-
thresholdEncryptionCiphertext,
|
|
3494
|
-
stringHash: symmetricEncryptionStringHash,
|
|
3495
|
-
symmetricKey,
|
|
3496
|
-
},
|
|
3497
|
-
];
|
|
3498
|
-
})()
|
|
3499
|
-
: await (async function () {
|
|
3500
|
-
// validate encoding, if provided
|
|
3501
|
-
if (options?.publishOptions?.statusListEncoding &&
|
|
3502
|
-
!Object.values(cheqd_did_provider_js_1.DefaultStatusList2021Encodings).includes(options?.publishOptions?.statusListEncoding)) {
|
|
3503
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list encoding');
|
|
3504
|
-
}
|
|
3505
|
-
// validate validUntil, if provided
|
|
3506
|
-
if (options?.publishOptions?.statusListValidUntil) {
|
|
3507
|
-
// validate validUntil as string
|
|
3508
|
-
if (typeof options?.publishOptions?.statusListValidUntil !== 'string')
|
|
3509
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be string)');
|
|
3510
|
-
// validate validUntil as date
|
|
3511
|
-
if (isNaN(Date.parse(options?.publishOptions?.statusListValidUntil)))
|
|
3512
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be date)');
|
|
3513
|
-
// validate validUntil as future date
|
|
3514
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) < new Date())
|
|
3515
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be future date)');
|
|
3516
|
-
// validate validUntil towards validFrom
|
|
3517
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) <=
|
|
3518
|
-
new Date(publishedList.StatusList2021.validFrom))
|
|
3519
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be after validFrom)');
|
|
3520
|
-
}
|
|
3521
|
-
// define status list content
|
|
3522
|
-
const content = {
|
|
3523
|
-
StatusList2021: {
|
|
3524
|
-
statusPurpose: publishedList.StatusList2021.statusPurpose,
|
|
3525
|
-
encodedList: publishedList.metadata.encoding === 'base64url'
|
|
3526
|
-
? bitstring
|
|
3527
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(bitstring, 'base64url'), options.publishOptions
|
|
3528
|
-
.statusListEncoding),
|
|
3529
|
-
validFrom: publishedList.StatusList2021.validFrom,
|
|
3530
|
-
validUntil: options?.publishOptions?.statusListValidUntil ||
|
|
3531
|
-
publishedList.StatusList2021.validUntil,
|
|
3532
|
-
},
|
|
3533
|
-
metadata: {
|
|
3534
|
-
type: publishedList.metadata.type,
|
|
3535
|
-
encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
|
|
3536
|
-
encrypted: false,
|
|
3537
|
-
},
|
|
3538
|
-
};
|
|
3539
|
-
// return tuple of publish result and encryption relevant metadata
|
|
3540
|
-
return [
|
|
3541
|
-
await Cheqd.publishStatusList2021((0, uint8arrays_1.fromString)(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
|
|
3542
|
-
undefined,
|
|
3543
|
-
];
|
|
3544
|
-
})();
|
|
3545
|
-
// early exit, if publish failed
|
|
3546
|
-
if (!scoped[0])
|
|
3547
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Failed to publish status list 2021');
|
|
3548
|
-
// return publish result
|
|
3549
|
-
return scoped;
|
|
3550
|
-
})()
|
|
3551
|
-
: undefined;
|
|
3552
|
-
return {
|
|
3553
|
-
unsuspended: true,
|
|
3554
|
-
published: topArgs?.publish ? true : undefined,
|
|
3555
|
-
statusList: topArgs?.returnUpdatedStatusList
|
|
3556
|
-
? (await Cheqd.fetchStatusList2021(credential))
|
|
3557
|
-
: undefined,
|
|
3558
|
-
symmetricKey: topArgs?.returnSymmetricKey
|
|
3559
|
-
? (0, uint8arrays_1.toString)(published?.[1]?.symmetricKey, 'hex')
|
|
3560
|
-
: undefined,
|
|
3561
|
-
resourceMetadata: topArgs?.returnStatusListMetadata
|
|
3562
|
-
? await Cheqd.fetchStatusList2021Metadata(credential)
|
|
3563
|
-
: undefined,
|
|
3564
|
-
};
|
|
3565
|
-
}
|
|
3566
|
-
catch (error) {
|
|
3567
|
-
// silent fail + early exit
|
|
3568
|
-
console.error(error);
|
|
3569
|
-
return { unsuspended: false, error: error };
|
|
3570
|
-
}
|
|
3571
|
-
}
|
|
3572
|
-
static async unsuspendCredentials(credentials, options) {
|
|
3573
|
-
// validate credentials - case: empty
|
|
3574
|
-
if (!credentials.length || credentials.length === 0)
|
|
3575
|
-
throw new Error('[did-provider-cheqd]: unsuspension: No credentials provided');
|
|
3576
|
-
// validate credentials - case: consistent issuer
|
|
3577
|
-
if (credentials
|
|
3578
|
-
.map((credential) => {
|
|
3579
|
-
return credential.issuer.id
|
|
3580
|
-
? credential.issuer.id
|
|
3581
|
-
: credential.issuer;
|
|
3582
|
-
})
|
|
3583
|
-
.filter((value, _, self) => value && value !== self[0]).length > 0)
|
|
3584
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Credentials must be issued by the same issuer');
|
|
3585
|
-
// validate credentials - case: status list index
|
|
3586
|
-
if (credentials
|
|
3587
|
-
.map((credential) => credential.credentialStatus.statusListIndex)
|
|
3588
|
-
.filter((value, index, self) => self.indexOf(value) !== index).length > 0)
|
|
3589
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Credentials must have unique status list index');
|
|
3590
|
-
// validate credentials - case: status purpose
|
|
3591
|
-
if (!credentials.every((credential) => credential.credentialStatus?.statusPurpose === cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension))
|
|
3592
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status purpose');
|
|
3593
|
-
// validate credentials - case: status list id
|
|
3594
|
-
const remote = credentials[0].credentialStatus?.id
|
|
3595
|
-
? credentials[0].credentialStatus.id.split('#')[0]
|
|
3596
|
-
: (function () {
|
|
3597
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list id');
|
|
3598
|
-
})();
|
|
3599
|
-
// validate credentials - case: status list id format
|
|
3600
|
-
if (!exports.RemoteListPattern.test(remote))
|
|
3601
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list id format: expected: https://<optional_subdomain>.<sld>.<tld>/1.0/identifiers/<did:cheqd:<namespace>:<method_specific_id>>?resourceName=<resource_name>&resourceType=<resource_type>');
|
|
3602
|
-
if (!credentials.every((credential) => {
|
|
3603
|
-
return credential.credentialStatus.id.split('#')[0] === remote;
|
|
3604
|
-
}))
|
|
3605
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Credentials must belong to the same status list');
|
|
3606
|
-
// validate credentials - case: status list type
|
|
3607
|
-
if (!credentials.every((credential) => credential.credentialStatus?.type === 'StatusList2021Entry'))
|
|
3608
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list type');
|
|
3609
|
-
try {
|
|
3610
|
-
// fetch status list 2021
|
|
3611
|
-
const publishedList = (await Cheqd.fetchStatusList2021(credentials[0]));
|
|
3612
|
-
// early return, if encrypted and no decryption key provided
|
|
3613
|
-
if (publishedList.metadata.encrypted && !options?.topArgs?.symmetricKey)
|
|
3614
|
-
throw new Error('[did-provider-cheqd]: unsuspension: symmetricKey is required, if status list 2021 is encrypted');
|
|
3615
|
-
// fetch status list 2021 inscribed in credential
|
|
3616
|
-
const statusList2021 = options?.topArgs?.fetchList
|
|
3617
|
-
? await (async function () {
|
|
3618
|
-
// if not encrypted, return bitstring
|
|
3619
|
-
if (!publishedList.metadata.encrypted)
|
|
3620
|
-
return publishedList.metadata.encoding === 'base64url'
|
|
3621
|
-
? publishedList.StatusList2021.encodedList
|
|
3622
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
3623
|
-
// decrypt + return bitstring, if qualified for migration
|
|
3624
|
-
if (publishedList.metadata.encryptedSymmetricKey)
|
|
3625
|
-
return await v2_js_1.LitProtocolV2.decryptDirect(await (0, helpers_js_1.toBlob)((0, uint8arrays_1.fromString)(publishedList.StatusList2021
|
|
3626
|
-
.encodedList, 'hex')), (0, uint8arrays_1.fromString)(options?.topArgs?.symmetricKey, 'hex'));
|
|
3627
|
-
// validate encoded list
|
|
3628
|
-
if (!(0, helpers_js_1.isEncodedList)(publishedList.StatusList2021.encodedList))
|
|
3629
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid encoded list');
|
|
3630
|
-
// otherwise, decrypt and return raw bitstring
|
|
3631
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)((0, uint8arrays_1.fromString)((0, helpers_js_1.getEncodedList)(publishedList.StatusList2021.encodedList, false)[0], 'hex'));
|
|
3632
|
-
// decrypt
|
|
3633
|
-
return (0, uint8arrays_1.toString)(await v6_js_1.LitProtocol.decryptDirect(scopedRawBlob, await (0, helpers_js_1.safeDeserialise)(options?.topArgs?.symmetricKey, uint8arrays_1.fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
|
|
3634
|
-
})()
|
|
3635
|
-
: await (async function () {
|
|
3636
|
-
// transcode to base64url, if needed
|
|
3637
|
-
const publishedListTranscoded = publishedList.metadata.encoding === 'base64url'
|
|
3638
|
-
? publishedList.StatusList2021.encodedList
|
|
3639
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
3640
|
-
// if status list 2021 is not fetched, read from file
|
|
3641
|
-
if (options?.statusListFile) {
|
|
3642
|
-
// if not encrypted, return bitstring
|
|
3643
|
-
if (!publishedList.metadata.encrypted) {
|
|
3644
|
-
// construct encoded status list
|
|
3645
|
-
const encoded = new vc_status_list_1.StatusList({
|
|
3646
|
-
buffer: await Cheqd.getFile(options.statusListFile),
|
|
3647
|
-
}).encode();
|
|
3648
|
-
// validate against published list
|
|
3649
|
-
if (encoded !== publishedListTranscoded)
|
|
3650
|
-
throw new Error('[did-provider-cheqd]: unsuspension: statusListFile does not match published status list 2021');
|
|
3651
|
-
// return encoded
|
|
3652
|
-
return encoded;
|
|
3653
|
-
}
|
|
3654
|
-
// otherwise, decrypt and return bitstring
|
|
3655
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)(await Cheqd.getFile(options.statusListFile));
|
|
3656
|
-
// decrypt
|
|
3657
|
-
const decrypted = (0, uint8arrays_1.toString)(await v6_js_1.LitProtocol.decryptDirect(scopedRawBlob, await (0, helpers_js_1.safeDeserialise)(options?.topArgs?.symmetricKey, uint8arrays_1.fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
|
|
3658
|
-
// validate against published list
|
|
3659
|
-
if (decrypted !== publishedListTranscoded)
|
|
3660
|
-
throw new Error('[did-provider-cheqd]: unsuspension: statusListFile does not match published status list 2021');
|
|
3661
|
-
// return decrypted
|
|
3662
|
-
return decrypted;
|
|
3663
|
-
}
|
|
3664
|
-
if (!options?.statusListInlineBitstring)
|
|
3665
|
-
throw new Error('[did-provider-cheqd]: unsuspension: statusListInlineBitstring is required, if statusListFile is not provided');
|
|
3666
|
-
// validate against published list
|
|
3667
|
-
if (options?.statusListInlineBitstring !== publishedListTranscoded)
|
|
3668
|
-
throw new Error('[did-provider-cheqd]: unsuspension: statusListInlineBitstring does not match published status list 2021');
|
|
3669
|
-
// otherwise, read from inline bitstring
|
|
3670
|
-
return options?.statusListInlineBitstring;
|
|
3671
|
-
})();
|
|
3672
|
-
// parse status list 2021
|
|
3673
|
-
const statusList = await vc_status_list_1.StatusList.decode({ encodedList: statusList2021 });
|
|
3674
|
-
// initiate bulk unsuspension
|
|
3675
|
-
const unsuspended = (await Promise.allSettled(credentials.map((credential) => {
|
|
3676
|
-
return (async function () {
|
|
3677
|
-
// early return, if no credential status
|
|
3678
|
-
if (!credential.credentialStatus)
|
|
3679
|
-
return { unsuspended: false };
|
|
3680
|
-
// early exit, if credential is already unsuspended
|
|
3681
|
-
if (!statusList.getStatus(Number(credential.credentialStatus.statusListIndex)))
|
|
3682
|
-
return { unsuspended: true };
|
|
3683
|
-
// update unsuspension status
|
|
3684
|
-
statusList.setStatus(Number(credential.credentialStatus.statusListIndex), false);
|
|
3685
|
-
// return unsuspension status
|
|
3686
|
-
return { unsuspended: true };
|
|
3687
|
-
})();
|
|
3688
|
-
})));
|
|
3689
|
-
// revert bulk ops, if some failed
|
|
3690
|
-
if (unsuspended.some((result) => result.status === 'fulfilled' && !result.value.unsuspended))
|
|
3691
|
-
throw new Error(`[did-provider-cheqd]: unsuspension: Bulk unsuspension failed: already unsuspended credentials in unsuspension bundle: raw log: ${JSON.stringify(unsuspended.map((result) => ({
|
|
3692
|
-
unsuspended: result.status === 'fulfilled' ? result.value.unsuspended : false,
|
|
3693
|
-
})))}`);
|
|
3694
|
-
// set in-memory status list ref
|
|
3695
|
-
const bitstring = (await statusList.encode());
|
|
3696
|
-
// cast top-level args
|
|
3697
|
-
const topArgs = options?.topArgs;
|
|
3698
|
-
// write status list 2021 to file, if provided
|
|
3699
|
-
if (topArgs?.writeToFile) {
|
|
3700
|
-
await Cheqd.writeFile((0, uint8arrays_1.fromString)(bitstring, 'base64url'), options?.statusListFile);
|
|
3701
|
-
}
|
|
3702
|
-
// publish status list 2021, if provided
|
|
3703
|
-
const published = topArgs?.publish
|
|
3704
|
-
? await (async function () {
|
|
3705
|
-
// fetch status list 2021 metadata
|
|
3706
|
-
const statusListMetadata = await Cheqd.fetchStatusList2021Metadata(credentials[0]);
|
|
3707
|
-
// publish status list 2021 as new version
|
|
3708
|
-
const scoped = topArgs.publishEncrypted
|
|
3709
|
-
? await (async function () {
|
|
3710
|
-
// validate encoding, if provided
|
|
3711
|
-
if (options?.publishOptions?.statusListEncoding &&
|
|
3712
|
-
!Object.values(cheqd_did_provider_js_1.DefaultStatusList2021Encodings).includes(options?.publishOptions?.statusListEncoding)) {
|
|
3713
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list encoding');
|
|
3714
|
-
}
|
|
3715
|
-
// validate validUntil, if provided
|
|
3716
|
-
if (options?.publishOptions?.statusListValidUntil) {
|
|
3717
|
-
// validate validUntil as string
|
|
3718
|
-
if (typeof options?.publishOptions?.statusListValidUntil !== 'string')
|
|
3719
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be string)');
|
|
3720
|
-
// validate validUntil as date
|
|
3721
|
-
if (isNaN(Date.parse(options?.publishOptions?.statusListValidUntil)))
|
|
3722
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be date)');
|
|
3723
|
-
// validate validUntil as future date
|
|
3724
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) < new Date())
|
|
3725
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be future date)');
|
|
3726
|
-
// validate validUntil towards validFrom
|
|
3727
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) <=
|
|
3728
|
-
new Date(publishedList.StatusList2021.validFrom))
|
|
3729
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be after validFrom)');
|
|
3730
|
-
}
|
|
3731
|
-
// validate paymentConditions, if provided
|
|
3732
|
-
if (topArgs?.paymentConditions) {
|
|
3733
|
-
if (!topArgs?.paymentConditions?.every((condition) => condition.feePaymentAddress &&
|
|
3734
|
-
condition.feePaymentAmount &&
|
|
3735
|
-
condition.intervalInSeconds)) {
|
|
3736
|
-
throw new Error('[did-provider-cheqd]: paymentConditions must contain feePaymentAddress and feeAmount and intervalInSeconds');
|
|
3737
|
-
}
|
|
3738
|
-
if (!topArgs?.paymentConditions?.every((condition) => typeof condition.feePaymentAddress === 'string' &&
|
|
3739
|
-
typeof condition.feePaymentAmount === 'string' &&
|
|
3740
|
-
typeof condition.intervalInSeconds === 'number')) {
|
|
3741
|
-
throw new Error('[did-provider-cheqd]: feePaymentAddress and feePaymentAmount must be string and intervalInSeconds must be number');
|
|
3742
|
-
}
|
|
3743
|
-
if (!topArgs?.paymentConditions?.every((condition) => condition.type === exports.AccessControlConditionTypes.timelockPayment)) {
|
|
3744
|
-
throw new Error('[did-provider-cheqd]: paymentConditions must be of type timelockPayment');
|
|
3745
|
-
}
|
|
3746
|
-
}
|
|
3747
|
-
// validate dkgOptions
|
|
3748
|
-
if (!topArgs?.dkgOptions ||
|
|
3749
|
-
!topArgs?.dkgOptions?.chain ||
|
|
3750
|
-
!topArgs?.dkgOptions?.network) {
|
|
3751
|
-
throw new Error('[did-provider-cheqd]: dkgOptions is required');
|
|
3752
|
-
}
|
|
3753
|
-
// encrypt bitstring - case: symmetric
|
|
3754
|
-
const { encryptedString: symmetricEncryptionCiphertext, stringHash: symmetricEncryptionStringHash, symmetricKey, } = await v6_js_1.LitProtocol.encryptDirect((0, uint8arrays_1.fromString)(bitstring, 'base64url'));
|
|
3755
|
-
// instantiate dkg-threshold client, in which case lit-protocol is used
|
|
3756
|
-
const lit = (await options.publishOptions.instantiateDkgClient);
|
|
3757
|
-
// construct access control conditions and payment conditions tuple
|
|
3758
|
-
const unifiedAccessControlConditionsTuple = publishedList.metadata.encrypted
|
|
3759
|
-
? await (async function () {
|
|
3760
|
-
// define payment conditions, give precedence to top-level args
|
|
3761
|
-
const paymentConditions = topArgs?.paymentConditions ||
|
|
3762
|
-
publishedList.metadata.paymentConditions;
|
|
3763
|
-
// return access control conditions and payment conditions tuple
|
|
3764
|
-
return [
|
|
3765
|
-
await Promise.all(paymentConditions.map(async (condition) => {
|
|
3766
|
-
switch (condition.type) {
|
|
3767
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
3768
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
3769
|
-
key: '$.tx_responses.*.timestamp',
|
|
3770
|
-
comparator: '<=',
|
|
3771
|
-
value: `${condition.intervalInSeconds}`,
|
|
3772
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight, topArgs?.dkgOptions?.chain);
|
|
3773
|
-
default:
|
|
3774
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
3775
|
-
}
|
|
3776
|
-
})),
|
|
3777
|
-
paymentConditions,
|
|
3778
|
-
];
|
|
3779
|
-
})()
|
|
3780
|
-
: await (async function () {
|
|
3781
|
-
// validate paymentConditions
|
|
3782
|
-
if (!topArgs?.paymentConditions) {
|
|
3783
|
-
throw new Error('[did-provider-cheqd]: paymentConditions is required');
|
|
3784
|
-
}
|
|
3785
|
-
// return access control conditions and payment conditions tuple
|
|
3786
|
-
return [
|
|
3787
|
-
await Promise.all(topArgs.paymentConditions.map(async (condition) => {
|
|
3788
|
-
switch (condition.type) {
|
|
3789
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
3790
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
3791
|
-
key: '$.tx_responses.*.timestamp',
|
|
3792
|
-
comparator: '<=',
|
|
3793
|
-
value: `${condition.intervalInSeconds}`,
|
|
3794
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight);
|
|
3795
|
-
default:
|
|
3796
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
3797
|
-
}
|
|
3798
|
-
})),
|
|
3799
|
-
topArgs.paymentConditions,
|
|
3800
|
-
];
|
|
3801
|
-
})();
|
|
3802
|
-
// encrypt bitstring - case: threshold
|
|
3803
|
-
const { encryptedString: thresholdEncryptionCiphertext, stringHash: thresholdEncryptionStringHash, } = await lit.encrypt((0, uint8arrays_1.fromString)(bitstring, 'base64url'), unifiedAccessControlConditionsTuple[0]);
|
|
3804
|
-
// construct encoded list
|
|
3805
|
-
const encodedList = `${await (0, helpers_js_1.blobToHexString)(symmetricEncryptionCiphertext)}-${(0, uint8arrays_1.toString)(thresholdEncryptionCiphertext, 'hex')}`;
|
|
3806
|
-
// define status list content
|
|
3807
|
-
const content = {
|
|
3808
|
-
StatusList2021: {
|
|
3809
|
-
statusPurpose: publishedList.StatusList2021.statusPurpose,
|
|
3810
|
-
encodedList,
|
|
3811
|
-
validFrom: publishedList.StatusList2021.validFrom,
|
|
3812
|
-
validUntil: options?.publishOptions?.statusListValidUntil ||
|
|
3813
|
-
publishedList.StatusList2021.validUntil,
|
|
3814
|
-
},
|
|
3815
|
-
metadata: {
|
|
3816
|
-
type: publishedList.metadata.type,
|
|
3817
|
-
encrypted: true,
|
|
3818
|
-
encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
|
|
3819
|
-
statusListHash: symmetricEncryptionStringHash === thresholdEncryptionStringHash
|
|
3820
|
-
? symmetricEncryptionStringHash
|
|
3821
|
-
: (function () {
|
|
3822
|
-
throw new Error('[did-provider-cheqd]: unsuspension: symmetricEncryptionStringHash and thresholdEncryptionStringHash do not match');
|
|
3823
|
-
})(),
|
|
3824
|
-
paymentConditions: unifiedAccessControlConditionsTuple[1],
|
|
3825
|
-
},
|
|
3826
|
-
};
|
|
3827
|
-
// return tuple of publish result and encryption relevant metadata
|
|
3828
|
-
return [
|
|
3829
|
-
await Cheqd.publishStatusList2021((0, uint8arrays_1.fromString)(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
|
|
3830
|
-
{
|
|
3831
|
-
symmetricEncryptionCiphertext,
|
|
3832
|
-
thresholdEncryptionCiphertext,
|
|
3833
|
-
stringHash: symmetricEncryptionStringHash,
|
|
3834
|
-
symmetricKey,
|
|
3835
|
-
},
|
|
3836
|
-
];
|
|
3837
|
-
})()
|
|
3838
|
-
: await (async function () {
|
|
3839
|
-
// validate encoding, if provided
|
|
3840
|
-
if (options?.publishOptions?.statusListEncoding &&
|
|
3841
|
-
!Object.values(cheqd_did_provider_js_1.DefaultStatusList2021Encodings).includes(options?.publishOptions?.statusListEncoding)) {
|
|
3842
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list encoding');
|
|
3843
|
-
}
|
|
3844
|
-
// validate validUntil, if provided
|
|
3845
|
-
if (options?.publishOptions?.statusListValidUntil) {
|
|
3846
|
-
// validate validUntil as string
|
|
3847
|
-
if (typeof options?.publishOptions?.statusListValidUntil !== 'string')
|
|
3848
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be string)');
|
|
3849
|
-
// validate validUntil as date
|
|
3850
|
-
if (isNaN(Date.parse(options?.publishOptions?.statusListValidUntil)))
|
|
3851
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be date)');
|
|
3852
|
-
// validate validUntil as future date
|
|
3853
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) < new Date())
|
|
3854
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be future date)');
|
|
3855
|
-
// validate validUntil towards validFrom
|
|
3856
|
-
if (new Date(options?.publishOptions?.statusListValidUntil) <=
|
|
3857
|
-
new Date(publishedList.StatusList2021.validFrom))
|
|
3858
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Invalid status list validUntil (must be after validFrom)');
|
|
3859
|
-
}
|
|
3860
|
-
// define status list content
|
|
3861
|
-
const content = {
|
|
3862
|
-
StatusList2021: {
|
|
3863
|
-
statusPurpose: publishedList.StatusList2021.statusPurpose,
|
|
3864
|
-
encodedList: publishedList.metadata.encoding === 'base64url'
|
|
3865
|
-
? bitstring
|
|
3866
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(bitstring, 'base64url'), options.publishOptions
|
|
3867
|
-
.statusListEncoding),
|
|
3868
|
-
validFrom: publishedList.StatusList2021.validFrom,
|
|
3869
|
-
validUntil: options?.publishOptions?.statusListValidUntil ||
|
|
3870
|
-
publishedList.StatusList2021.validUntil,
|
|
3871
|
-
},
|
|
3872
|
-
metadata: {
|
|
3873
|
-
type: publishedList.metadata.type,
|
|
3874
|
-
encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
|
|
3875
|
-
encrypted: false,
|
|
3876
|
-
},
|
|
3877
|
-
};
|
|
3878
|
-
// return tuple of publish result and encryption relevant metadata
|
|
3879
|
-
return [
|
|
3880
|
-
await Cheqd.publishStatusList2021((0, uint8arrays_1.fromString)(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
|
|
3881
|
-
undefined,
|
|
3882
|
-
];
|
|
3883
|
-
})();
|
|
3884
|
-
// early exit, if publish failed
|
|
3885
|
-
if (!scoped[0])
|
|
3886
|
-
throw new Error('[did-provider-cheqd]: unsuspension: Failed to publish status list 2021');
|
|
3887
|
-
// return publish result
|
|
3888
|
-
return scoped;
|
|
3889
|
-
})()
|
|
3890
|
-
: undefined;
|
|
3891
|
-
return {
|
|
3892
|
-
unsuspended: unsuspended.map((result) => result.status === 'fulfilled' ? result.value.unsuspended : false),
|
|
3893
|
-
published: topArgs?.publish ? true : undefined,
|
|
3894
|
-
statusList: topArgs?.returnUpdatedStatusList
|
|
3895
|
-
? (await Cheqd.fetchStatusList2021(credentials[0]))
|
|
3896
|
-
: undefined,
|
|
3897
|
-
symmetricKey: topArgs?.returnSymmetricKey
|
|
3898
|
-
? (0, uint8arrays_1.toString)(published?.[1]?.symmetricKey, 'hex')
|
|
3899
|
-
: undefined,
|
|
3900
|
-
resourceMetadata: topArgs?.returnStatusListMetadata
|
|
3901
|
-
? await Cheqd.fetchStatusList2021Metadata(credentials[0])
|
|
3902
|
-
: undefined,
|
|
3903
|
-
};
|
|
3904
|
-
}
|
|
3905
|
-
catch (error) {
|
|
3906
|
-
// silent fail + early exit
|
|
3907
|
-
console.error(error);
|
|
3908
|
-
return { unsuspended: [], error: error };
|
|
3909
|
-
}
|
|
3910
|
-
}
|
|
3911
|
-
static async checkRevoked(credential, options = { fetchList: true }) {
|
|
3912
|
-
// validate status purpose
|
|
3913
|
-
if (credential.credentialStatus?.statusPurpose !== cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.revocation) {
|
|
3914
|
-
throw new Error(`[did-provider-cheqd]: check: revocation: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
|
|
3915
|
-
}
|
|
3916
|
-
// validate dkgOptions
|
|
3917
|
-
if (!options?.topArgs?.dkgOptions) {
|
|
3918
|
-
throw new Error('[did-provider-cheqd]: dkgOptions is required');
|
|
3919
|
-
}
|
|
3920
|
-
// fetch status list 2021
|
|
3921
|
-
const publishedList = (await Cheqd.fetchStatusList2021(credential));
|
|
3922
|
-
// route to non-migrated action, if applicable
|
|
3923
|
-
if (publishedList.metadata.encryptedSymmetricKey)
|
|
3924
|
-
return await this.checkRevokedNonMigrated(credential, publishedList, options);
|
|
3925
|
-
// fetch status list 2021 inscribed in credential
|
|
3926
|
-
const statusList2021 = options?.topArgs?.fetchList
|
|
3927
|
-
? await (async function () {
|
|
3928
|
-
// if not encrypted, return bitstring
|
|
3929
|
-
if (!publishedList.metadata.encrypted)
|
|
3930
|
-
return publishedList.metadata.encoding === 'base64url'
|
|
3931
|
-
? publishedList.StatusList2021.encodedList
|
|
3932
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
3933
|
-
// validate encoded list
|
|
3934
|
-
if (!(0, helpers_js_1.isEncodedList)(publishedList.StatusList2021.encodedList))
|
|
3935
|
-
throw new Error('[did-provider-cheqd]: check: revocation: Invalid encoded list');
|
|
3936
|
-
// otherwise, decrypt and return raw bitstring
|
|
3937
|
-
const thresholdEncryptionCiphertext = (0, helpers_js_1.getEncodedList)(publishedList.StatusList2021.encodedList, false)[1];
|
|
3938
|
-
// instantiate dkg-threshold client, in which case lit-protocol is used
|
|
3939
|
-
const lit = (await options.instantiateDkgClient);
|
|
3940
|
-
// construct access control conditions
|
|
3941
|
-
const unifiedAccessControlConditions = await Promise.all(publishedList.metadata.paymentConditions.map(async (condition) => {
|
|
3942
|
-
switch (condition.type) {
|
|
3943
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
3944
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
3945
|
-
key: '$.tx_responses.*.timestamp',
|
|
3946
|
-
comparator: '<=',
|
|
3947
|
-
value: `${condition.intervalInSeconds}`,
|
|
3948
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight, options?.topArgs?.dkgOptions?.chain);
|
|
3949
|
-
default:
|
|
3950
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
3951
|
-
}
|
|
3952
|
-
}));
|
|
3953
|
-
// decrypt
|
|
3954
|
-
return await lit.decrypt(thresholdEncryptionCiphertext, publishedList.metadata.statusListHash, unifiedAccessControlConditions, options?.topArgs?.dkgOptions?.capacityDelegationAuthSignature);
|
|
3955
|
-
})()
|
|
3956
|
-
: await (async function () {
|
|
3957
|
-
// transcode to base64url, if needed
|
|
3958
|
-
const publishedListTranscoded = publishedList.metadata.encoding === 'base64url'
|
|
3959
|
-
? publishedList.StatusList2021.encodedList
|
|
3960
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
3961
|
-
// if status list 2021 is not fetched, read from file
|
|
3962
|
-
if (options?.statusListFile) {
|
|
3963
|
-
// if not encrypted, return bitstring
|
|
3964
|
-
if (!publishedList.metadata.encrypted) {
|
|
3965
|
-
// construct encoded status list
|
|
3966
|
-
const encoded = new vc_status_list_1.StatusList({
|
|
3967
|
-
buffer: await Cheqd.getFile(options.statusListFile),
|
|
3968
|
-
}).encode();
|
|
3969
|
-
// validate against published list
|
|
3970
|
-
if (encoded !== publishedListTranscoded)
|
|
3971
|
-
throw new Error('[did-provider-cheqd]: check: revocation: statusListFile does not match published status list 2021');
|
|
3972
|
-
// return encoded
|
|
3973
|
-
return encoded;
|
|
3974
|
-
}
|
|
3975
|
-
// otherwise, decrypt and return bitstring
|
|
3976
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)(await Cheqd.getFile(options.statusListFile));
|
|
3977
|
-
// decrypt
|
|
3978
|
-
const decrypted = (0, uint8arrays_1.toString)(await v6_js_1.LitProtocol.decryptDirect(scopedRawBlob, await (0, helpers_js_1.safeDeserialise)(options?.topArgs?.symmetricKey, uint8arrays_1.fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
|
|
3979
|
-
// validate against published list
|
|
3980
|
-
if (decrypted !== publishedListTranscoded)
|
|
3981
|
-
throw new Error('[did-provider-cheqd]: check: revocation: statusListFile does not match published status list 2021');
|
|
3982
|
-
// return decrypted
|
|
3983
|
-
return decrypted;
|
|
3984
|
-
}
|
|
3985
|
-
if (!options?.statusListInlineBitstring)
|
|
3986
|
-
throw new Error('[did-provider-cheqd]: check: revocation: statusListInlineBitstring is required, if statusListFile is not provided');
|
|
3987
|
-
// validate against published list
|
|
3988
|
-
if (options?.statusListInlineBitstring !== publishedListTranscoded)
|
|
3989
|
-
throw new Error('[did-provider-cheqd]: check: revocation: statusListInlineBitstring does not match published status list 2021');
|
|
3990
|
-
// otherwise, read from inline bitstring
|
|
3991
|
-
return options?.statusListInlineBitstring;
|
|
3992
|
-
})();
|
|
3993
|
-
// transcode, if needed
|
|
3994
|
-
const transcodedStatusList2021 = publishedList.metadata.encoding === 'base64url'
|
|
3995
|
-
? statusList2021
|
|
3996
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(statusList2021, publishedList.metadata.encoding), 'base64url');
|
|
3997
|
-
// parse status list 2021
|
|
3998
|
-
const statusList = await vc_status_list_1.StatusList.decode({ encodedList: transcodedStatusList2021 });
|
|
3999
|
-
// get status by index
|
|
4000
|
-
return !!statusList.getStatus(Number(credential.credentialStatus.statusListIndex));
|
|
4001
|
-
}
|
|
4002
|
-
static async checkSuspended(credential, options = { fetchList: true }) {
|
|
4003
|
-
// validate status purpose
|
|
4004
|
-
if (credential.credentialStatus?.statusPurpose !== cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension) {
|
|
4005
|
-
throw new Error(`[did-provider-cheqd]: check: suspension: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
|
|
4006
|
-
}
|
|
4007
|
-
// validate dkgOptions
|
|
4008
|
-
if (!options?.topArgs?.dkgOptions) {
|
|
4009
|
-
throw new Error('[did-provider-cheqd]: dkgOptions is required');
|
|
4010
|
-
}
|
|
4011
|
-
// fetch status list 2021
|
|
4012
|
-
const publishedList = (await Cheqd.fetchStatusList2021(credential));
|
|
4013
|
-
// route to non-migrated action, if applicable
|
|
4014
|
-
if (publishedList.metadata.encryptedSymmetricKey)
|
|
4015
|
-
return await this.checkSuspendedNonMigrated(credential, publishedList, options);
|
|
4016
|
-
// fetch status list 2021 inscribed in credential
|
|
4017
|
-
const statusList2021 = options?.topArgs?.fetchList
|
|
4018
|
-
? await (async function () {
|
|
4019
|
-
// if not encrypted, return bitstring
|
|
4020
|
-
if (!publishedList.metadata.encrypted)
|
|
4021
|
-
return publishedList.metadata.encoding === 'base64url'
|
|
4022
|
-
? publishedList.StatusList2021.encodedList
|
|
4023
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
4024
|
-
// otherwise, decrypt and return bitstring
|
|
4025
|
-
const thresholdEncryptionCiphertext = (0, helpers_js_1.getEncodedList)(publishedList.StatusList2021.encodedList, false)[1];
|
|
4026
|
-
// instantiate dkg-threshold client, in which case lit-protocol is used
|
|
4027
|
-
const lit = (await options.instantiateDkgClient);
|
|
4028
|
-
// construct access control conditions
|
|
4029
|
-
const unifiedAccessControlConditions = await Promise.all(publishedList.metadata.paymentConditions.map(async (condition) => {
|
|
4030
|
-
switch (condition.type) {
|
|
4031
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
4032
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
4033
|
-
key: '$.tx_responses.*.timestamp',
|
|
4034
|
-
comparator: '<=',
|
|
4035
|
-
value: `${condition.intervalInSeconds}`,
|
|
4036
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight, options?.topArgs?.dkgOptions?.chain);
|
|
4037
|
-
default:
|
|
4038
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
4039
|
-
}
|
|
4040
|
-
}));
|
|
4041
|
-
// decrypt
|
|
4042
|
-
return await lit.decrypt(thresholdEncryptionCiphertext, publishedList.metadata.statusListHash, unifiedAccessControlConditions, options?.topArgs?.dkgOptions?.capacityDelegationAuthSignature);
|
|
4043
|
-
})()
|
|
4044
|
-
: await (async function () {
|
|
4045
|
-
// transcode to base64url, if needed
|
|
4046
|
-
const publishedListTranscoded = publishedList.metadata.encoding === 'base64url'
|
|
4047
|
-
? publishedList.StatusList2021.encodedList
|
|
4048
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
4049
|
-
// if status list 2021 is not fetched, read from file
|
|
4050
|
-
if (options?.statusListFile) {
|
|
4051
|
-
// if not encrypted, return bitstring
|
|
4052
|
-
if (!publishedList.metadata.encrypted) {
|
|
4053
|
-
// construct encoded status list
|
|
4054
|
-
const encoded = new vc_status_list_1.StatusList({
|
|
4055
|
-
buffer: await Cheqd.getFile(options.statusListFile),
|
|
4056
|
-
}).encode();
|
|
4057
|
-
// validate against published list
|
|
4058
|
-
if (encoded !== publishedListTranscoded)
|
|
4059
|
-
throw new Error('[did-provider-cheqd]: check: suspension: statusListFile does not match published status list 2021');
|
|
4060
|
-
// return encoded
|
|
4061
|
-
return encoded;
|
|
4062
|
-
}
|
|
4063
|
-
// otherwise, decrypt and return bitstring
|
|
4064
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)(await Cheqd.getFile(options.statusListFile));
|
|
4065
|
-
// decrypt
|
|
4066
|
-
const decrypted = (0, uint8arrays_1.toString)(await v6_js_1.LitProtocol.decryptDirect(scopedRawBlob, await (0, helpers_js_1.safeDeserialise)(options?.topArgs?.symmetricKey, uint8arrays_1.fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
|
|
4067
|
-
// validate against published list
|
|
4068
|
-
if (decrypted !== publishedListTranscoded)
|
|
4069
|
-
throw new Error('[did-provider-cheqd]: check: suspension: statusListFile does not match published status list 2021');
|
|
4070
|
-
// return decrypted
|
|
4071
|
-
return decrypted;
|
|
4072
|
-
}
|
|
4073
|
-
if (!options?.statusListInlineBitstring)
|
|
4074
|
-
throw new Error('[did-provider-cheqd]: check: suspension: statusListInlineBitstring is required, if statusListFile is not provided');
|
|
4075
|
-
// validate against published list
|
|
4076
|
-
if (options?.statusListInlineBitstring !== publishedListTranscoded)
|
|
4077
|
-
throw new Error('[did-provider-cheqd]: check: suspension: statusListInlineBitstring does not match published status list 2021');
|
|
4078
|
-
// otherwise, read from inline bitstring
|
|
4079
|
-
return options?.statusListInlineBitstring;
|
|
4080
|
-
})();
|
|
4081
|
-
// parse status list 2021
|
|
4082
|
-
const statusList = await vc_status_list_1.StatusList.decode({ encodedList: statusList2021 });
|
|
4083
|
-
// get status by index
|
|
4084
|
-
return !!statusList.getStatus(Number(credential.credentialStatus.statusListIndex));
|
|
4085
|
-
}
|
|
4086
|
-
static async checkRevokedNonMigrated(credential, associatedStatusList, options = { fetchList: true }) {
|
|
4087
|
-
// validate status purpose
|
|
4088
|
-
if (credential.credentialStatus?.statusPurpose !== cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.revocation) {
|
|
4089
|
-
throw new Error(`[did-provider-cheqd]: check: revocation: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
|
|
4090
|
-
}
|
|
4091
|
-
// fetch status list 2021
|
|
4092
|
-
const publishedList = associatedStatusList ||
|
|
4093
|
-
(await Cheqd.fetchStatusList2021(credential));
|
|
4094
|
-
// validate migrated
|
|
4095
|
-
if (!publishedList.metadata.encryptedSymmetricKey)
|
|
4096
|
-
throw new Error('[did-provider-cheqd]: check: revocation: Invalid migrated status list');
|
|
4097
|
-
// fetch status list 2021 inscribed in credential
|
|
4098
|
-
const statusList2021 = options?.topArgs?.fetchList
|
|
4099
|
-
? await (async function () {
|
|
4100
|
-
// if not encrypted, return bitstring
|
|
4101
|
-
if (!publishedList.metadata.encrypted)
|
|
4102
|
-
return publishedList.metadata.encoding === 'base64url'
|
|
4103
|
-
? publishedList.StatusList2021.encodedList
|
|
4104
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
4105
|
-
// otherwise, decrypt and return raw bitstring
|
|
4106
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, 'hex'));
|
|
4107
|
-
// instantiate dkg-threshold client, in which case lit-protocol is used
|
|
4108
|
-
const lit = await v2_js_1.LitProtocolV2.create({
|
|
4109
|
-
chain: options?.topArgs?.dkgOptions?.chain,
|
|
4110
|
-
litNetwork: v2_js_1.LitNetworksV2.serrano,
|
|
4111
|
-
});
|
|
4112
|
-
// construct access control conditions
|
|
4113
|
-
const unifiedAccessControlConditions = await Promise.all(publishedList.metadata.paymentConditions.map(async (condition) => {
|
|
4114
|
-
switch (condition.type) {
|
|
4115
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
4116
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
4117
|
-
key: '$.tx_responses.*.timestamp',
|
|
4118
|
-
comparator: '<=',
|
|
4119
|
-
value: `${condition.intervalInSeconds}`,
|
|
4120
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight, options?.topArgs?.dkgOptions?.chain);
|
|
4121
|
-
default:
|
|
4122
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
4123
|
-
}
|
|
4124
|
-
}));
|
|
4125
|
-
// decrypt
|
|
4126
|
-
return await lit.decrypt(scopedRawBlob, publishedList.metadata.encryptedSymmetricKey, unifiedAccessControlConditions);
|
|
4127
|
-
})()
|
|
4128
|
-
: await (async function () {
|
|
4129
|
-
// transcode to base64url, if needed
|
|
4130
|
-
const publishedListTranscoded = publishedList.metadata.encoding === 'base64url'
|
|
4131
|
-
? publishedList.StatusList2021.encodedList
|
|
4132
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
4133
|
-
// if status list 2021 is not fetched, read from file
|
|
4134
|
-
if (options?.statusListFile) {
|
|
4135
|
-
// if not encrypted, return bitstring
|
|
4136
|
-
if (!publishedList.metadata.encrypted) {
|
|
4137
|
-
// construct encoded status list
|
|
4138
|
-
const encoded = new vc_status_list_1.StatusList({
|
|
4139
|
-
buffer: await Cheqd.getFile(options.statusListFile),
|
|
4140
|
-
}).encode();
|
|
4141
|
-
// validate against published list
|
|
4142
|
-
if (encoded !== publishedListTranscoded)
|
|
4143
|
-
throw new Error('[did-provider-cheqd]: check: revocation: statusListFile does not match published status list 2021');
|
|
4144
|
-
// return encoded
|
|
4145
|
-
return encoded;
|
|
4146
|
-
}
|
|
4147
|
-
// otherwise, decrypt and return bitstring
|
|
4148
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)(await Cheqd.getFile(options.statusListFile));
|
|
4149
|
-
// decrypt
|
|
4150
|
-
const decrypted = await v2_js_1.LitProtocolV2.decryptDirect(scopedRawBlob, (0, uint8arrays_1.fromString)(options?.topArgs?.symmetricKey, 'hex'));
|
|
4151
|
-
// validate against published list
|
|
4152
|
-
if (decrypted !== publishedListTranscoded)
|
|
4153
|
-
throw new Error('[did-provider-cheqd]: check: revocation: statusListFile does not match published status list 2021');
|
|
4154
|
-
// return decrypted
|
|
4155
|
-
return decrypted;
|
|
4156
|
-
}
|
|
4157
|
-
if (!options?.statusListInlineBitstring)
|
|
4158
|
-
throw new Error('[did-provider-cheqd]: check: revocation: statusListInlineBitstring is required, if statusListFile is not provided');
|
|
4159
|
-
// validate against published list
|
|
4160
|
-
if (options?.statusListInlineBitstring !== publishedListTranscoded)
|
|
4161
|
-
throw new Error('[did-provider-cheqd]: check: revocation: statusListInlineBitstring does not match published status list 2021');
|
|
4162
|
-
// otherwise, read from inline bitstring
|
|
4163
|
-
return options?.statusListInlineBitstring;
|
|
4164
|
-
})();
|
|
4165
|
-
// transcode, if needed
|
|
4166
|
-
const transcodedStatusList2021 = publishedList.metadata.encoding === 'base64url'
|
|
4167
|
-
? statusList2021
|
|
4168
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(statusList2021, publishedList.metadata.encoding), 'base64url');
|
|
4169
|
-
// parse status list 2021
|
|
4170
|
-
const statusList = await vc_status_list_1.StatusList.decode({ encodedList: transcodedStatusList2021 });
|
|
4171
|
-
// get status by index
|
|
4172
|
-
return !!statusList.getStatus(Number(credential.credentialStatus.statusListIndex));
|
|
4173
|
-
}
|
|
4174
|
-
static async checkSuspendedNonMigrated(credential, associatedStatusList, options = { fetchList: true }) {
|
|
4175
|
-
// validate status purpose
|
|
4176
|
-
if (credential.credentialStatus?.statusPurpose !== cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension) {
|
|
4177
|
-
throw new Error(`[did-provider-cheqd]: check: suspension: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
|
|
4178
|
-
}
|
|
4179
|
-
// fetch status list 2021
|
|
4180
|
-
const publishedList = associatedStatusList ||
|
|
4181
|
-
(await Cheqd.fetchStatusList2021(credential));
|
|
4182
|
-
// validate migrated
|
|
4183
|
-
if (!publishedList.metadata.encryptedSymmetricKey)
|
|
4184
|
-
throw new Error('[did-provider-cheqd]: check: suspension: Invalid migrated status list');
|
|
4185
|
-
// fetch status list 2021 inscribed in credential
|
|
4186
|
-
const statusList2021 = options?.topArgs?.fetchList
|
|
4187
|
-
? await (async function () {
|
|
4188
|
-
// if not encrypted, return bitstring
|
|
4189
|
-
if (!publishedList.metadata.encrypted)
|
|
4190
|
-
return publishedList.metadata.encoding === 'base64url'
|
|
4191
|
-
? publishedList.StatusList2021.encodedList
|
|
4192
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
4193
|
-
// otherwise, decrypt and return raw bitstring
|
|
4194
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, 'hex'));
|
|
4195
|
-
// instantiate dkg-threshold client, in which case lit-protocol is used
|
|
4196
|
-
const lit = await v2_js_1.LitProtocolV2.create({
|
|
4197
|
-
chain: options?.topArgs?.dkgOptions?.chain,
|
|
4198
|
-
litNetwork: v2_js_1.LitNetworksV2.serrano,
|
|
4199
|
-
});
|
|
4200
|
-
// construct access control conditions
|
|
4201
|
-
const unifiedAccessControlConditions = await Promise.all(publishedList.metadata.paymentConditions.map(async (condition) => {
|
|
4202
|
-
switch (condition.type) {
|
|
4203
|
-
case exports.AccessControlConditionTypes.timelockPayment:
|
|
4204
|
-
return await v6_js_1.LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
|
|
4205
|
-
key: '$.tx_responses.*.timestamp',
|
|
4206
|
-
comparator: '<=',
|
|
4207
|
-
value: `${condition.intervalInSeconds}`,
|
|
4208
|
-
}, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight, options?.topArgs?.dkgOptions?.chain);
|
|
4209
|
-
default:
|
|
4210
|
-
throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
|
|
4211
|
-
}
|
|
4212
|
-
}));
|
|
4213
|
-
// decrypt
|
|
4214
|
-
return await lit.decrypt(scopedRawBlob, publishedList.metadata.encryptedSymmetricKey, unifiedAccessControlConditions);
|
|
4215
|
-
})()
|
|
4216
|
-
: await (async function () {
|
|
4217
|
-
// transcode to base64url, if needed
|
|
4218
|
-
const publishedListTranscoded = publishedList.metadata.encoding === 'base64url'
|
|
4219
|
-
? publishedList.StatusList2021.encodedList
|
|
4220
|
-
: (0, uint8arrays_1.toString)((0, uint8arrays_1.fromString)(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
|
|
4221
|
-
// if status list 2021 is not fetched, read from file
|
|
4222
|
-
if (options?.statusListFile) {
|
|
4223
|
-
// if not encrypted, return bitstring
|
|
4224
|
-
if (!publishedList.metadata.encrypted) {
|
|
4225
|
-
// construct encoded status list
|
|
4226
|
-
const encoded = new vc_status_list_1.StatusList({
|
|
4227
|
-
buffer: await Cheqd.getFile(options.statusListFile),
|
|
4228
|
-
}).encode();
|
|
4229
|
-
// validate against published list
|
|
4230
|
-
if (encoded !== publishedListTranscoded)
|
|
4231
|
-
throw new Error('[did-provider-cheqd]: check: suspension: statusListFile does not match published status list 2021');
|
|
4232
|
-
// return encoded
|
|
4233
|
-
return encoded;
|
|
4234
|
-
}
|
|
4235
|
-
// otherwise, decrypt and return bitstring
|
|
4236
|
-
const scopedRawBlob = await (0, helpers_js_1.toBlob)(await Cheqd.getFile(options.statusListFile));
|
|
4237
|
-
// decrypt
|
|
4238
|
-
const decrypted = (0, uint8arrays_1.toString)(await v6_js_1.LitProtocol.decryptDirect(scopedRawBlob, await (0, helpers_js_1.safeDeserialise)(options?.topArgs?.symmetricKey, uint8arrays_1.fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
|
|
4239
|
-
// validate against published list
|
|
4240
|
-
if (decrypted !== publishedListTranscoded)
|
|
4241
|
-
throw new Error('[did-provider-cheqd]: check: suspension: statusListFile does not match published status list 2021');
|
|
4242
|
-
// return decrypted
|
|
4243
|
-
return decrypted;
|
|
4244
|
-
}
|
|
4245
|
-
if (!options?.statusListInlineBitstring)
|
|
4246
|
-
throw new Error('[did-provider-cheqd]: check: suspension: statusListInlineBitstring is required, if statusListFile is not provided');
|
|
4247
|
-
// validate against published list
|
|
4248
|
-
if (options?.statusListInlineBitstring !== publishedListTranscoded)
|
|
4249
|
-
throw new Error('[did-provider-cheqd]: check: suspension: statusListInlineBitstring does not match published status list 2021');
|
|
4250
|
-
// otherwise, read from inline bitstring
|
|
4251
|
-
return options?.statusListInlineBitstring;
|
|
4252
|
-
})();
|
|
4253
|
-
// parse status list 2021
|
|
4254
|
-
const statusList = await vc_status_list_1.StatusList.decode({ encodedList: statusList2021 });
|
|
4255
|
-
// get status by index
|
|
4256
|
-
return !!statusList.getStatus(Number(credential.credentialStatus.statusListIndex));
|
|
4257
|
-
}
|
|
4258
|
-
static async publishStatusList2021(statusList2021Raw, statusList2021Metadata, options) {
|
|
4259
|
-
// construct status list 2021 payload from previous version + new version
|
|
4260
|
-
const payload = {
|
|
4261
|
-
collectionId: statusList2021Metadata.resourceCollectionId,
|
|
4262
|
-
id: options?.resourceId || (0, uuid_1.v4)(),
|
|
4263
|
-
name: statusList2021Metadata.resourceName,
|
|
4264
|
-
version: options?.resourceVersion || new Date().toISOString(),
|
|
4265
|
-
alsoKnownAs: options?.resourceAlsoKnownAs || [],
|
|
4266
|
-
resourceType: statusList2021Metadata.resourceType,
|
|
4267
|
-
data: statusList2021Raw,
|
|
4268
|
-
};
|
|
4269
|
-
return await options.context.agent[exports.BroadcastStatusList2021MethodName]({
|
|
4270
|
-
kms: (await options.context.agent.keyManagerGetKeyManagementSystems())[0],
|
|
4271
|
-
payload,
|
|
4272
|
-
network: statusList2021Metadata.resourceURI.split(':')[2],
|
|
4273
|
-
signInputs: options?.signInputs,
|
|
4274
|
-
fee: options?.fee,
|
|
4275
|
-
});
|
|
4276
|
-
}
|
|
4277
|
-
static async fetchStatusList2021(credential, returnRaw = false) {
|
|
4278
|
-
// validate credential status
|
|
4279
|
-
if (!credential.credentialStatus)
|
|
4280
|
-
throw new Error('[did-provider-cheqd]: fetch status list: Credential status is not present');
|
|
4281
|
-
// validate credential status type
|
|
4282
|
-
if (credential.credentialStatus.type !== 'StatusList2021Entry')
|
|
4283
|
-
throw new Error('[did-provider-cheqd]: fetch status list: Credential status type is not valid');
|
|
4284
|
-
// validate credential status list status purpose
|
|
4285
|
-
if (credential.credentialStatus.statusPurpose !== cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.revocation &&
|
|
4286
|
-
credential.credentialStatus.statusPurpose !== cheqd_did_provider_js_1.DefaultStatusList2021StatusPurposeTypes.suspension)
|
|
4287
|
-
throw new Error('[did-provider-cheqd]: fetch status list: Credential status purpose is not valid');
|
|
4288
|
-
// fetch status list 2021
|
|
4289
|
-
const content = (await (await fetch(credential.credentialStatus.id.split('#')[0])).json());
|
|
4290
|
-
if (!(content.StatusList2021 &&
|
|
4291
|
-
content.metadata &&
|
|
4292
|
-
content.StatusList2021.encodedList &&
|
|
4293
|
-
content.StatusList2021.statusPurpose &&
|
|
4294
|
-
content.metadata.encoding)) {
|
|
4295
|
-
throw new Error(`'[did-provider-cheqd]: fetch status list: Status List resource content is not valid'`);
|
|
4296
|
-
}
|
|
4297
|
-
// return raw if requested
|
|
4298
|
-
if (returnRaw) {
|
|
4299
|
-
return (0, uint8arrays_1.fromString)(content.StatusList2021.encodedList, content.metadata.encoding);
|
|
4300
|
-
}
|
|
4301
|
-
// otherwise, return content
|
|
4302
|
-
return content;
|
|
4303
|
-
}
|
|
4304
|
-
static async fetchStatusList2021Metadata(credential) {
|
|
4305
|
-
// get base url
|
|
4306
|
-
const baseUrl = new URL(credential.credentialStatus.id.split('#')[0]);
|
|
4307
|
-
// get resource name
|
|
4308
|
-
const resourceName = baseUrl.searchParams.get('resourceName');
|
|
4309
|
-
// get resource type
|
|
4310
|
-
const resourceType = baseUrl.searchParams.get('resourceType');
|
|
4311
|
-
// unset resource name
|
|
4312
|
-
baseUrl.searchParams.delete('resourceName');
|
|
4313
|
-
// unset resource type
|
|
4314
|
-
baseUrl.searchParams.delete('resourceType');
|
|
4315
|
-
// construct metadata url
|
|
4316
|
-
const metadataUrl = `${baseUrl.toString()}/metadata`;
|
|
4317
|
-
// fetch collection metadata
|
|
4318
|
-
const collectionMetadata = (await (await fetch(metadataUrl)).json());
|
|
4319
|
-
// early exit if no linked resources
|
|
4320
|
-
if (!collectionMetadata?.contentStream?.linkedResourceMetadata)
|
|
4321
|
-
throw new Error('[did-provider-cheqd]: fetch status list metadata: No linked resources found');
|
|
4322
|
-
// find relevant resources by resource name
|
|
4323
|
-
const resourceVersioning = collectionMetadata.contentStream.linkedResourceMetadata.filter((resource) => resource.resourceName === resourceName && resource.resourceType === resourceType);
|
|
4324
|
-
// early exit if no relevant resources
|
|
4325
|
-
if (!resourceVersioning.length || resourceVersioning.length === 0)
|
|
4326
|
-
throw new Error(`[did-provider-cheqd]: fetch status list metadata: No relevant resources found by resource name ${resourceName}`);
|
|
4327
|
-
// get latest resource version by nextVersionId null pointer, or by latest created date as fallback
|
|
4328
|
-
return (resourceVersioning.find((resource) => !resource.nextVersionId) ||
|
|
4329
|
-
resourceVersioning.sort((a, b) => new Date(b.created).getTime() - new Date(a.created).getTime())[0]);
|
|
4330
|
-
}
|
|
4331
|
-
static async getProviderFromDidUrl(didUrl, providers, message) {
|
|
4332
|
-
const provider = providers.find((provider) => didUrl.includes(`${exports.DidPrefix}:${exports.CheqdDidMethod}:${provider.network}:`));
|
|
4333
|
-
if (!provider) {
|
|
4334
|
-
throw new Error(message ||
|
|
4335
|
-
`[did-provider-cheqd]: no relevant providers found for did url ${didUrl}: loaded providers: ${providers.map((provider) => `${exports.DidPrefix}:${exports.CheqdDidMethod}:${provider.network}`).join(', ')}`);
|
|
4336
|
-
}
|
|
4337
|
-
return provider;
|
|
4338
|
-
}
|
|
4339
|
-
static async getProviderFromNetwork(network, providers, message) {
|
|
4340
|
-
const provider = providers.find((provider) => provider.network === network);
|
|
4341
|
-
if (!provider) {
|
|
4342
|
-
throw new Error(message ||
|
|
4343
|
-
`[did-provider-cheqd]: no relevant providers found for network ${network}: loaded providers: ${providers.map((provider) => `${exports.DidPrefix}:${exports.CheqdDidMethod}:${provider.network}`).join(', ')}`);
|
|
4344
|
-
}
|
|
4345
|
-
return provider;
|
|
4346
|
-
}
|
|
4347
|
-
static generateProviderId(namespace) {
|
|
4348
|
-
return `${exports.DidPrefix}:${exports.CheqdDidMethod}:${namespace}`;
|
|
4349
|
-
}
|
|
4350
|
-
static async getFile(filename) {
|
|
4351
|
-
if (typeof filename !== 'string') {
|
|
4352
|
-
throw new Error('[did-provider-cheqd]: filename is required');
|
|
4353
|
-
}
|
|
4354
|
-
if (!fs_1.default.existsSync(filename)) {
|
|
4355
|
-
debug(`[did-provider-cheqd]: File ${filename} not found`);
|
|
4356
|
-
throw new Error(`[did-provider-cheqd]: File ${filename} not found`);
|
|
4357
|
-
}
|
|
4358
|
-
return new Promise((resolve, reject) => {
|
|
4359
|
-
const content = fs_1.default.readFileSync(filename);
|
|
4360
|
-
if (!content) {
|
|
4361
|
-
reject(new Error(`[did-provider-cheqd]: File ${filename} is empty`));
|
|
4362
|
-
}
|
|
4363
|
-
resolve(new Uint8Array(content));
|
|
4364
|
-
});
|
|
4365
|
-
}
|
|
4366
|
-
static async writeFile(content, filename) {
|
|
4367
|
-
if (!filename) {
|
|
4368
|
-
filename = `statusList2021-${(0, uuid_1.v4)()}`;
|
|
4369
|
-
}
|
|
4370
|
-
// alert if file exists
|
|
4371
|
-
if (fs_1.default.existsSync(filename)) {
|
|
4372
|
-
debug(`[did-provider-cheqd]: File ${filename} already exists`);
|
|
4373
|
-
console.warn(`[did-provider-cheqd]: File ${filename} already exists. Overwriting...`);
|
|
4374
|
-
}
|
|
4375
|
-
return new Promise((resolve, reject) => {
|
|
4376
|
-
fs_1.default.writeFile(filename, content, (err) => {
|
|
4377
|
-
if (err) {
|
|
4378
|
-
reject(new Error(`[did-provider-cheqd]: Error writing file ${filename}: reason: ${err}`));
|
|
4379
|
-
}
|
|
4380
|
-
resolve();
|
|
4381
|
-
});
|
|
4382
|
-
});
|
|
4383
|
-
}
|
|
4384
|
-
static async decodeCredentialJWT(jwt) {
|
|
4385
|
-
const decodedCredential = (0, did_jwt_1.decodeJWT)(jwt);
|
|
4386
|
-
// validate credential payload
|
|
4387
|
-
if (!decodedCredential.payload)
|
|
4388
|
-
throw new Error('[did-provider-cheqd]: decode jwt: decodedCredential.payload is required');
|
|
4389
|
-
// validate credential payload vc property as VerifiableCredential
|
|
4390
|
-
if (!decodedCredential.payload.vc)
|
|
4391
|
-
throw new Error('[did-provider-cheqd]: decode jwt: decodedCredential.payload.vc is required');
|
|
4392
|
-
return {
|
|
4393
|
-
...decodedCredential.payload.vc,
|
|
4394
|
-
issuer: decodedCredential.payload.iss,
|
|
4395
|
-
};
|
|
4396
|
-
}
|
|
4397
|
-
}
|
|
4398
|
-
exports.Cheqd = Cheqd;
|
|
4399
|
-
//# sourceMappingURL=ICheqd.js.map
|