@cheqd/did-provider-cheqd 4.5.5-develop.1 → 4.6.0
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/agent/ICheqd.d.ts +291 -82
- package/build/esm/agent/ICheqd.d.ts.map +1 -1
- package/build/esm/agent/ICheqd.js +1567 -87
- package/build/esm/agent/ICheqd.js.map +1 -1
- package/build/esm/did-manager/cheqd-did-provider.d.ts +13 -2
- package/build/esm/did-manager/cheqd-did-provider.d.ts.map +1 -1
- package/build/esm/did-manager/cheqd-did-provider.js +10 -2
- package/build/esm/did-manager/cheqd-did-provider.js.map +1 -1
- package/build/esm/dkg-threshold/lit-protocol/v6.d.ts.map +1 -1
- package/build/esm/dkg-threshold/lit-protocol/v6.js +63 -33
- package/build/esm/dkg-threshold/lit-protocol/v6.js.map +1 -1
- package/build/esm/utils/helpers.d.ts +28 -7
- package/build/esm/utils/helpers.d.ts.map +1 -1
- package/build/esm/utils/helpers.js +120 -29
- package/build/esm/utils/helpers.js.map +1 -1
- package/build/tsconfig.esm.tsbuildinfo +1 -1
- package/build/tsconfig.types.tsbuildinfo +1 -1
- package/build/types/agent/ICheqd.d.ts +291 -82
- package/build/types/agent/ICheqd.d.ts.map +1 -1
- package/build/types/did-manager/cheqd-did-provider.d.ts +13 -2
- package/build/types/did-manager/cheqd-did-provider.d.ts.map +1 -1
- package/build/types/dkg-threshold/lit-protocol/v6.d.ts.map +1 -1
- package/build/types/utils/helpers.d.ts +28 -7
- package/build/types/utils/helpers.d.ts.map +1 -1
- package/package.json +6 -4
- package/src/agent/ICheqd.ts +2425 -372
- package/src/did-manager/cheqd-did-provider.ts +19 -4
- package/src/dkg-threshold/lit-protocol/v6.ts +65 -34
- package/src/utils/helpers.ts +172 -34
- package/tsconfig.json +2 -0
package/src/agent/ICheqd.ts
CHANGED
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
W3CVerifiableCredential,
|
|
40
40
|
ICredentialVerifier,
|
|
41
41
|
DIDResolutionResult,
|
|
42
|
+
CredentialStatusReference,
|
|
42
43
|
} from '@veramo/core';
|
|
43
44
|
import {
|
|
44
45
|
CheqdDIDProvider,
|
|
@@ -47,17 +48,22 @@ import {
|
|
|
47
48
|
ResourcePayload,
|
|
48
49
|
StatusList2021ResourcePayload,
|
|
49
50
|
DefaultRESTUrls,
|
|
50
|
-
|
|
51
|
+
DefaultStatusListEncodings,
|
|
51
52
|
DefaultStatusList2021ResourceTypes,
|
|
52
53
|
DefaultStatusList2021StatusPurposeTypes,
|
|
53
|
-
|
|
54
|
+
DefaultStatusListEncoding,
|
|
54
55
|
DefaultStatusList2021ResourceType,
|
|
55
56
|
DefaultStatusList2021StatusPurposeType,
|
|
57
|
+
BitstringStatusPurposeTypes,
|
|
56
58
|
TPublicKeyEd25519,
|
|
59
|
+
BitstringStatusListResourceType,
|
|
60
|
+
BitstringStatusListPurposeType,
|
|
61
|
+
BitstringStatusListResourcePayload,
|
|
57
62
|
} from '../did-manager/cheqd-did-provider.js';
|
|
58
63
|
import { fromString, toString } from 'uint8arrays';
|
|
59
64
|
import { decodeJWT } from 'did-jwt';
|
|
60
65
|
import { StatusList } from '@digitalbazaar/vc-status-list';
|
|
66
|
+
import { Bitstring as DBBitstring } from '@digitalbazaar/bitstring';
|
|
61
67
|
import { v4 } from 'uuid';
|
|
62
68
|
import fs from 'fs';
|
|
63
69
|
import Debug from 'debug';
|
|
@@ -72,8 +78,12 @@ import {
|
|
|
72
78
|
} from '../dkg-threshold/lit-protocol/v6.js';
|
|
73
79
|
import {
|
|
74
80
|
blobToHexString,
|
|
81
|
+
decodeWithMetadata,
|
|
82
|
+
encodeWithMetadata,
|
|
83
|
+
generateRandomStatusListIndex,
|
|
75
84
|
getEncodedList,
|
|
76
85
|
isEncodedList,
|
|
86
|
+
isValidEncodedBitstring,
|
|
77
87
|
randomFromRange,
|
|
78
88
|
safeDeserialise,
|
|
79
89
|
toBlob,
|
|
@@ -185,6 +195,13 @@ export type VerificationResult = {
|
|
|
185
195
|
suspended?: boolean;
|
|
186
196
|
error?: IVerifyResult['error'];
|
|
187
197
|
};
|
|
198
|
+
export interface BitstringValidationResult {
|
|
199
|
+
status: number; // e.g., 0x0, 0x1, 0x2
|
|
200
|
+
purpose: string; // e.g., 'revocation', 'suspension'
|
|
201
|
+
valid: boolean;
|
|
202
|
+
message?: string;
|
|
203
|
+
}
|
|
204
|
+
export type BitstringVerificationResult = VerificationResult & BitstringValidationResult;
|
|
188
205
|
export type EncryptionResult = {
|
|
189
206
|
symmetricEncryptionCiphertext: string;
|
|
190
207
|
thresholdEncryptionCiphertext: string;
|
|
@@ -192,6 +209,28 @@ export type EncryptionResult = {
|
|
|
192
209
|
symmetricKey: string;
|
|
193
210
|
};
|
|
194
211
|
export type StatusCheckResult = { revoked?: boolean; suspended?: boolean; error?: IError };
|
|
212
|
+
export type BitstringUpdateResult = {
|
|
213
|
+
updated: boolean;
|
|
214
|
+
statusValue: BitstringStatusValue;
|
|
215
|
+
previousStatusValue?: BitstringStatusValue;
|
|
216
|
+
statusMessage?: string; // Human-readable status message
|
|
217
|
+
error?: IError;
|
|
218
|
+
statusList?: BitstringStatusList;
|
|
219
|
+
symmetricKey?: string;
|
|
220
|
+
published?: boolean;
|
|
221
|
+
resourceMetadata?: LinkedResourceMetadataResolutionResult;
|
|
222
|
+
};
|
|
223
|
+
export type BulkBitstringUpdateResult = {
|
|
224
|
+
updated: boolean[];
|
|
225
|
+
statusValues: BitstringStatusValue[];
|
|
226
|
+
previousStatusValues?: BitstringStatusValue[];
|
|
227
|
+
statusMessages?: string[]; // Human-readable status message
|
|
228
|
+
error?: IError;
|
|
229
|
+
statusList?: BitstringStatusList;
|
|
230
|
+
symmetricKey?: string;
|
|
231
|
+
published?: boolean;
|
|
232
|
+
resourceMetadata?: LinkedResourceMetadataResolutionResult;
|
|
233
|
+
};
|
|
195
234
|
export type RevocationResult = {
|
|
196
235
|
revoked: boolean;
|
|
197
236
|
error?: IError;
|
|
@@ -255,7 +294,7 @@ export type StatusList2021Revocation = {
|
|
|
255
294
|
metadata: {
|
|
256
295
|
type: typeof DefaultStatusList2021ResourceTypes.revocation;
|
|
257
296
|
encrypted: boolean;
|
|
258
|
-
encoding:
|
|
297
|
+
encoding: DefaultStatusListEncoding;
|
|
259
298
|
statusListHash?: string;
|
|
260
299
|
paymentConditions?: PaymentCondition[];
|
|
261
300
|
};
|
|
@@ -270,7 +309,7 @@ export type StatusList2021Suspension = {
|
|
|
270
309
|
metadata: {
|
|
271
310
|
type: typeof DefaultStatusList2021ResourceTypes.suspension;
|
|
272
311
|
encrypted: boolean;
|
|
273
|
-
encoding:
|
|
312
|
+
encoding: DefaultStatusListEncoding;
|
|
274
313
|
statusListHash?: string;
|
|
275
314
|
paymentConditions?: PaymentCondition[];
|
|
276
315
|
};
|
|
@@ -285,7 +324,7 @@ export type StatusList2021RevocationNonMigrated = {
|
|
|
285
324
|
metadata: {
|
|
286
325
|
type: typeof DefaultStatusList2021ResourceTypes.revocation;
|
|
287
326
|
encrypted: boolean;
|
|
288
|
-
encoding:
|
|
327
|
+
encoding: DefaultStatusListEncoding;
|
|
289
328
|
encryptedSymmetricKey?: string;
|
|
290
329
|
paymentConditions?: PaymentCondition[];
|
|
291
330
|
};
|
|
@@ -300,11 +339,52 @@ export type StatusList2021SuspensionNonMigrated = {
|
|
|
300
339
|
metadata: {
|
|
301
340
|
type: typeof DefaultStatusList2021ResourceTypes.suspension;
|
|
302
341
|
encrypted: boolean;
|
|
303
|
-
encoding:
|
|
342
|
+
encoding: DefaultStatusListEncoding;
|
|
304
343
|
encryptedSymmetricKey?: string;
|
|
305
344
|
paymentConditions?: PaymentCondition[];
|
|
306
345
|
};
|
|
307
346
|
};
|
|
347
|
+
export interface BitstringStatusListEntry extends CredentialStatusReference {
|
|
348
|
+
id: string;
|
|
349
|
+
type: 'BitstringStatusListEntry';
|
|
350
|
+
statusPurpose: BitstringStatusListPurposeType;
|
|
351
|
+
statusListIndex: string; // must be string representation of integer
|
|
352
|
+
statusListCredential: string; // DID URL of the status list credential
|
|
353
|
+
statusSize?: number | 1; // bits per credential (1, 2, 4, 8)
|
|
354
|
+
statusMessage?: BitstringStatusMessage[]; // status value meanings
|
|
355
|
+
statusReference?: string | string[]; // reference to status meanings
|
|
356
|
+
}
|
|
357
|
+
export interface BitstringStatusMessage {
|
|
358
|
+
status: string; // hex value prefixed with 0x (e.g., "0x0", "0x1")
|
|
359
|
+
message: string; // human-readable explanation
|
|
360
|
+
[key: string]: any; // additional properties can be added
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export interface EncodedListMetadata {
|
|
364
|
+
encrypted: boolean;
|
|
365
|
+
encoding: DefaultStatusListEncoding;
|
|
366
|
+
length: number;
|
|
367
|
+
statusSize?: number; // bits per credential (1, 2, 4, 8)
|
|
368
|
+
statusMessages?: BitstringStatusMessage[]; // status value meanings
|
|
369
|
+
statusListHash?: string;
|
|
370
|
+
symmetricLength?: number; // length of symmetric encryption ciphertext in bytes
|
|
371
|
+
paymentConditions?: PaymentCondition[];
|
|
372
|
+
}
|
|
373
|
+
export type BitstringVerifiableCredential = VerifiableCredential & {
|
|
374
|
+
credentialStatus: BitstringStatusListEntry;
|
|
375
|
+
};
|
|
376
|
+
export type BitstringStatusListCredential = VerifiableCredential & {
|
|
377
|
+
credentialSubject: {
|
|
378
|
+
type: string;
|
|
379
|
+
statusPurpose: BitstringStatusListPurposeType;
|
|
380
|
+
encodedList: EncodedList;
|
|
381
|
+
ttl?: number; // time to live in milliseconds
|
|
382
|
+
};
|
|
383
|
+
};
|
|
384
|
+
export interface BitstringStatusList {
|
|
385
|
+
bitstringStatusListCredential: BitstringStatusListCredential;
|
|
386
|
+
metadata: EncodedListMetadata;
|
|
387
|
+
}
|
|
308
388
|
export type AccessControlConditionType = (typeof AccessControlConditionTypes)[keyof typeof AccessControlConditionTypes];
|
|
309
389
|
export type AccessControlConditionReturnValueComparator =
|
|
310
390
|
(typeof AccessControlConditionReturnValueComparators)[keyof typeof AccessControlConditionReturnValueComparators];
|
|
@@ -327,6 +407,14 @@ export type CreateStatusList2021Result = {
|
|
|
327
407
|
encrypted?: boolean;
|
|
328
408
|
symmetricKey?: string;
|
|
329
409
|
};
|
|
410
|
+
export type CreateStatusListResult = {
|
|
411
|
+
created: boolean;
|
|
412
|
+
error?: Error;
|
|
413
|
+
resource: BitstringStatusList;
|
|
414
|
+
resourceMetadata: LinkedResourceMetadataResolutionResult;
|
|
415
|
+
encrypted?: boolean;
|
|
416
|
+
symmetricKey?: string;
|
|
417
|
+
};
|
|
330
418
|
export type TransactionResult = {
|
|
331
419
|
successful: boolean;
|
|
332
420
|
transactionHash?: string;
|
|
@@ -385,6 +473,17 @@ export const GenerateStatusList2021MethodName = 'cheqdGenerateStatusList2021';
|
|
|
385
473
|
export const IssueRevocableCredentialWithStatusList2021MethodName = 'cheqdIssueRevocableCredentialWithStatusList2021';
|
|
386
474
|
export const IssueSuspendableCredentialWithStatusList2021MethodName =
|
|
387
475
|
'cheqdIssueSuspendableCredentialWithStatusList2021';
|
|
476
|
+
|
|
477
|
+
export const CreateStatusListMethodName = 'cheqdCreateStatusList';
|
|
478
|
+
export const BroadcastStatusListMethodName = 'cheqdBroadcastStatusList';
|
|
479
|
+
export const GenerateStatusListMethodName = 'cheqdGenerateStatusList';
|
|
480
|
+
export const VerifyStatusListCredentialMethodName = 'cheqdVerifyStatusListCredential';
|
|
481
|
+
export const IssueCredentialWithStatusListMethodName = 'cheqdIssueCredentialWithStatusList';
|
|
482
|
+
export const VerifyCredentialWithStatusListMethodName = 'cheqdVerifyCredentialWithStatusList';
|
|
483
|
+
export const UpdateCredentialWithStatusListMethodName = 'cheqdUpdateCredentialWithStatusList';
|
|
484
|
+
export const BulkUpdateCredentialsWithStatusListMethodName = 'cheqdBulkUpdateCredentialsWithStatusList';
|
|
485
|
+
export const VerifyPresentationWithStatusListMethodName = 'cheqdVerifyPresentationWithStatusList';
|
|
486
|
+
// END: TODO, start Remove or update with status list 2021
|
|
388
487
|
export const VerifyCredentialMethodName = 'cheqdVerifyCredential';
|
|
389
488
|
export const VerifyPresentationMethodName = 'cheqdVerifyPresentation';
|
|
390
489
|
export const CheckCredentialStatusMethodName = 'cheqdCheckCredentialStatus';
|
|
@@ -394,6 +493,7 @@ export const SuspendCredentialMethodName = 'cheqdSuspendCredential';
|
|
|
394
493
|
export const SuspendCredentialsMethodName = 'cheqdSuspendCredentials';
|
|
395
494
|
export const UnsuspendCredentialMethodName = 'cheqdUnsuspendCredential';
|
|
396
495
|
export const UnsuspendCredentialsMethodName = 'cheqdUnsuspendCredentials';
|
|
496
|
+
// END: Remove or update with status list 2021
|
|
397
497
|
export const TransactSendTokensMethodName = 'cheqdTransactSendTokens';
|
|
398
498
|
export const ObservePaymentConditionMethodName = 'cheqdObservePaymentCondition';
|
|
399
499
|
export const MintCapacityCreditMethodName = 'cheqdMintCapacityCredit';
|
|
@@ -446,7 +546,7 @@ export interface ICheqdCreateStatusList2021Args {
|
|
|
446
546
|
resourceVersion?: ResourcePayload['version'];
|
|
447
547
|
alsoKnownAs?: ResourcePayload['alsoKnownAs'];
|
|
448
548
|
statusListLength?: number;
|
|
449
|
-
statusListEncoding?:
|
|
549
|
+
statusListEncoding?: DefaultStatusListEncoding;
|
|
450
550
|
validUntil?: string;
|
|
451
551
|
returnSymmetricKey?: boolean;
|
|
452
552
|
}
|
|
@@ -460,15 +560,34 @@ export interface ICheqdCreateUnencryptedStatusList2021Args {
|
|
|
460
560
|
fee?: DidStdFee | 'auto' | number;
|
|
461
561
|
}
|
|
462
562
|
|
|
463
|
-
export interface
|
|
563
|
+
export interface ICheqdBroadcastStatusListArgs {
|
|
464
564
|
kms: string;
|
|
465
|
-
payload: StatusList2021ResourcePayload;
|
|
565
|
+
payload: StatusList2021ResourcePayload | BitstringStatusListResourcePayload;
|
|
466
566
|
network: CheqdNetwork;
|
|
467
567
|
file?: string;
|
|
468
568
|
signInputs?: ISignInputs[];
|
|
469
569
|
fee?: DidStdFee | 'auto' | number;
|
|
470
570
|
}
|
|
471
571
|
|
|
572
|
+
export interface ICheqdCreateBitstringStatusListArgs {
|
|
573
|
+
kms: string;
|
|
574
|
+
issuerDid: string;
|
|
575
|
+
statusListName: string;
|
|
576
|
+
statusPurpose: BitstringStatusListPurposeType | BitstringStatusListPurposeType[];
|
|
577
|
+
statusSize?: number; // bits per credential
|
|
578
|
+
statusMessages?: BitstringStatusMessage[];
|
|
579
|
+
ttl?: number; // time to live in milliseconds
|
|
580
|
+
encrypted: boolean;
|
|
581
|
+
paymentConditions?: PaymentCondition[];
|
|
582
|
+
dkgOptions?: DkgOptions;
|
|
583
|
+
resourceVersion?: ResourcePayload['version'];
|
|
584
|
+
alsoKnownAs?: ResourcePayload['alsoKnownAs'];
|
|
585
|
+
statusListLength?: number;
|
|
586
|
+
statusListEncoding?: DefaultStatusListEncoding;
|
|
587
|
+
validUntil?: string;
|
|
588
|
+
returnSymmetricKey?: boolean;
|
|
589
|
+
}
|
|
590
|
+
|
|
472
591
|
export interface ICheqdGenerateDidDocArgs {
|
|
473
592
|
verificationMethod: VerificationMethods;
|
|
474
593
|
methodSpecificIdAlgo: MethodSpecificIdAlgo;
|
|
@@ -490,9 +609,33 @@ export interface ICheqdGenerateVersionIdArgs {
|
|
|
490
609
|
export interface ICheqdGenerateStatusList2021Args {
|
|
491
610
|
length?: number;
|
|
492
611
|
buffer?: Uint8Array;
|
|
493
|
-
bitstringEncoding?:
|
|
612
|
+
bitstringEncoding?: DefaultStatusListEncoding;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
export interface ICheqdGenerateStatusListArgs {
|
|
616
|
+
length?: number; // Number of entries
|
|
617
|
+
statusSize?: number; // Bits per entry
|
|
618
|
+
buffer?: Buffer;
|
|
619
|
+
bitstringEncoding?: DefaultStatusListEncoding;
|
|
494
620
|
}
|
|
495
621
|
|
|
622
|
+
export interface ICheqdVerifyStatusListCredentialArgs {
|
|
623
|
+
credential: BitstringStatusListCredential;
|
|
624
|
+
verificationArgs?: IVerifyCredentialArgs;
|
|
625
|
+
}
|
|
626
|
+
export interface StatusOptions {
|
|
627
|
+
statusPurpose: BitstringStatusListPurposeType;
|
|
628
|
+
statusListName: string;
|
|
629
|
+
statusListIndex?: number;
|
|
630
|
+
statusListVersion?: string;
|
|
631
|
+
statusListRangeStart?: number;
|
|
632
|
+
statusListRangeEnd?: number;
|
|
633
|
+
indexNotIn?: number[];
|
|
634
|
+
}
|
|
635
|
+
export interface ICheqdIssueCredentialWithStatusListArgs {
|
|
636
|
+
issuanceOptions: ICreateVerifiableCredentialArgs;
|
|
637
|
+
statusOptions: StatusOptions;
|
|
638
|
+
}
|
|
496
639
|
export interface ICheqdIssueRevocableCredentialWithStatusList2021Args {
|
|
497
640
|
issuanceOptions: ICreateVerifiableCredentialArgs;
|
|
498
641
|
statusOptions: {
|
|
@@ -519,34 +662,78 @@ export interface ICheqdIssueSuspendableCredentialWithStatusList2021Args {
|
|
|
519
662
|
};
|
|
520
663
|
}
|
|
521
664
|
|
|
522
|
-
export interface
|
|
665
|
+
export interface ICheqdVerifyCredentialWithStatusListArgs {
|
|
523
666
|
credential: W3CVerifiableCredential;
|
|
524
667
|
verificationArgs?: IVerifyCredentialArgs;
|
|
525
668
|
fetchList?: boolean;
|
|
526
669
|
dkgOptions?: DkgOptions;
|
|
527
|
-
options?:
|
|
670
|
+
options?: ICheqdStatusListOptions;
|
|
671
|
+
}
|
|
672
|
+
export interface ICheqdVerifyCredentialWithBitstringArgs {
|
|
673
|
+
credential: BitstringVerifiableCredential;
|
|
674
|
+
verificationArgs?: IVerifyCredentialArgs;
|
|
675
|
+
fetchList?: boolean;
|
|
676
|
+
dkgOptions?: DkgOptions;
|
|
677
|
+
options?: ICheqdStatusListOptions;
|
|
528
678
|
}
|
|
529
679
|
|
|
530
|
-
export interface
|
|
680
|
+
export interface ICheqdVerifyPresentationWithStatusListArgs {
|
|
531
681
|
presentation: VerifiablePresentation;
|
|
532
682
|
verificationArgs?: IVerifyPresentationArgs;
|
|
533
683
|
fetchList?: boolean;
|
|
534
684
|
dkgOptions?: DkgOptions;
|
|
535
|
-
options?:
|
|
685
|
+
options?: ICheqdStatusListOptions;
|
|
536
686
|
}
|
|
537
687
|
|
|
538
|
-
export interface
|
|
688
|
+
export interface ICheqdCheckCredentialStatusWithStatusListArgs {
|
|
539
689
|
credential?: W3CVerifiableCredential;
|
|
540
|
-
statusOptions?:
|
|
690
|
+
statusOptions?: ICheqdCheckCredentialStatusOptions;
|
|
691
|
+
verificationOptions?: IVerifyCredentialArgs;
|
|
692
|
+
fetchList?: boolean;
|
|
693
|
+
dkgOptions?: DkgOptions;
|
|
694
|
+
options?: ICheqdStatusListOptions;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
export interface ICheqdUpdateCredentialWithStatusListArgs {
|
|
698
|
+
credential?: W3CVerifiableCredential;
|
|
699
|
+
newStatus: BitstringStatusValue; // 0=valid, 1=revoked, 2=suspended, 3=unknown
|
|
700
|
+
updateOptions?: ICheqdCredentialStatusUpdateOptions;
|
|
701
|
+
verificationOptions?: IVerifyCredentialArgs;
|
|
702
|
+
fetchList?: boolean;
|
|
703
|
+
publish?: boolean;
|
|
704
|
+
publishEncrypted?: boolean;
|
|
705
|
+
symmetricKey?: string;
|
|
706
|
+
paymentConditions?: PaymentCondition[];
|
|
707
|
+
writeToFile?: boolean;
|
|
708
|
+
returnUpdatedStatusList?: boolean;
|
|
709
|
+
returnSymmetricKey?: boolean;
|
|
710
|
+
returnStatusListMetadata?: boolean;
|
|
711
|
+
dkgOptions?: DkgOptions;
|
|
712
|
+
options?: ICheqdStatusListOptions;
|
|
713
|
+
fee?: DidStdFee | 'auto' | number;
|
|
714
|
+
}
|
|
715
|
+
export interface ICheqdBulkUpdateCredentialWithStatusListArgs {
|
|
716
|
+
credentials?: W3CVerifiableCredential[];
|
|
717
|
+
newStatus: BitstringStatusValue; // 0=valid, 1=revoked, 2=suspended, 3=unknown
|
|
718
|
+
updateOptions?: ICheqdBulkCredentialStatusUpdateOptions;
|
|
541
719
|
verificationOptions?: IVerifyCredentialArgs;
|
|
542
720
|
fetchList?: boolean;
|
|
721
|
+
publish?: boolean;
|
|
722
|
+
publishEncrypted?: boolean;
|
|
723
|
+
symmetricKey?: string;
|
|
724
|
+
paymentConditions?: PaymentCondition[];
|
|
725
|
+
writeToFile?: boolean;
|
|
726
|
+
returnUpdatedStatusList?: boolean;
|
|
727
|
+
returnSymmetricKey?: boolean;
|
|
728
|
+
returnStatusListMetadata?: boolean;
|
|
543
729
|
dkgOptions?: DkgOptions;
|
|
544
|
-
options?:
|
|
730
|
+
options?: ICheqdStatusListOptions;
|
|
731
|
+
fee?: DidStdFee | 'auto' | number;
|
|
545
732
|
}
|
|
546
733
|
|
|
547
|
-
export interface
|
|
734
|
+
export interface ICheqdRevokeCredentialWithStatusListArgs {
|
|
548
735
|
credential?: W3CVerifiableCredential;
|
|
549
|
-
revocationOptions?:
|
|
736
|
+
revocationOptions?: ICheqdCredentialStatusUpdateOptions;
|
|
550
737
|
verificationOptions?: IVerifyCredentialArgs;
|
|
551
738
|
fetchList?: boolean;
|
|
552
739
|
publish?: boolean;
|
|
@@ -558,12 +745,12 @@ export interface ICheqdRevokeCredentialWithStatusList2021Args {
|
|
|
558
745
|
returnSymmetricKey?: boolean;
|
|
559
746
|
returnStatusListMetadata?: boolean;
|
|
560
747
|
dkgOptions?: DkgOptions;
|
|
561
|
-
options?:
|
|
748
|
+
options?: ICheqdStatusListOptions;
|
|
562
749
|
}
|
|
563
750
|
|
|
564
|
-
export interface
|
|
751
|
+
export interface ICheqdRevokeBulkCredentialsWithStatusListArgs {
|
|
565
752
|
credentials?: W3CVerifiableCredential[];
|
|
566
|
-
revocationOptions?:
|
|
753
|
+
revocationOptions?: ICheqdBulkCredentialStatusUpdateOptions;
|
|
567
754
|
verificationOptions?: IVerifyCredentialArgs;
|
|
568
755
|
fetchList?: boolean;
|
|
569
756
|
publish?: boolean;
|
|
@@ -575,13 +762,13 @@ export interface ICheqdRevokeBulkCredentialsWithStatusList2021Args {
|
|
|
575
762
|
returnSymmetricKey?: boolean;
|
|
576
763
|
returnStatusListMetadata?: boolean;
|
|
577
764
|
dkgOptions?: DkgOptions;
|
|
578
|
-
options?:
|
|
765
|
+
options?: ICheqdStatusListOptions;
|
|
579
766
|
fee?: DidStdFee | 'auto' | number;
|
|
580
767
|
}
|
|
581
768
|
|
|
582
|
-
export interface
|
|
769
|
+
export interface ICheqdSuspendCredentialWithStatusListArgs {
|
|
583
770
|
credential?: W3CVerifiableCredential;
|
|
584
|
-
suspensionOptions?:
|
|
771
|
+
suspensionOptions?: ICheqdCredentialStatusUpdateOptions;
|
|
585
772
|
verificationOptions?: IVerifyCredentialArgs;
|
|
586
773
|
fetchList?: boolean;
|
|
587
774
|
publish?: boolean;
|
|
@@ -593,13 +780,13 @@ export interface ICheqdSuspendCredentialWithStatusList2021Args {
|
|
|
593
780
|
returnSymmetricKey?: boolean;
|
|
594
781
|
returnStatusListMetadata?: boolean;
|
|
595
782
|
dkgOptions?: DkgOptions;
|
|
596
|
-
options?:
|
|
783
|
+
options?: ICheqdStatusListOptions;
|
|
597
784
|
fee?: DidStdFee | 'auto' | number;
|
|
598
785
|
}
|
|
599
786
|
|
|
600
|
-
export interface
|
|
787
|
+
export interface ICheqdSuspendBulkCredentialsWithStatusListArgs {
|
|
601
788
|
credentials?: W3CVerifiableCredential[];
|
|
602
|
-
suspensionOptions?:
|
|
789
|
+
suspensionOptions?: ICheqdBulkCredentialStatusUpdateOptions;
|
|
603
790
|
verificationOptions?: IVerifyCredentialArgs;
|
|
604
791
|
fetchList?: boolean;
|
|
605
792
|
publish?: boolean;
|
|
@@ -611,13 +798,13 @@ export interface ICheqdSuspendBulkCredentialsWithStatusList2021Args {
|
|
|
611
798
|
returnSymmetricKey?: boolean;
|
|
612
799
|
returnStatusListMetadata?: boolean;
|
|
613
800
|
dkgOptions?: DkgOptions;
|
|
614
|
-
options?:
|
|
801
|
+
options?: ICheqdStatusListOptions;
|
|
615
802
|
fee?: DidStdFee | 'auto' | number;
|
|
616
803
|
}
|
|
617
804
|
|
|
618
|
-
export interface
|
|
805
|
+
export interface ICheqdUnsuspendCredentialWithStatusListArgs {
|
|
619
806
|
credential?: W3CVerifiableCredential;
|
|
620
|
-
unsuspensionOptions?:
|
|
807
|
+
unsuspensionOptions?: ICheqdCredentialStatusUpdateOptions;
|
|
621
808
|
verificationOptions?: IVerifyCredentialArgs;
|
|
622
809
|
fetchList?: boolean;
|
|
623
810
|
publish?: boolean;
|
|
@@ -629,13 +816,13 @@ export interface ICheqdUnsuspendCredentialWithStatusList2021Args {
|
|
|
629
816
|
returnSymmetricKey?: boolean;
|
|
630
817
|
returnStatusListMetadata?: boolean;
|
|
631
818
|
dkgOptions?: DkgOptions;
|
|
632
|
-
options?:
|
|
819
|
+
options?: ICheqdStatusListOptions;
|
|
633
820
|
fee?: DidStdFee | 'auto' | number;
|
|
634
821
|
}
|
|
635
822
|
|
|
636
|
-
export interface
|
|
823
|
+
export interface ICheqdUnsuspendBulkCredentialsWithStatusListArgs {
|
|
637
824
|
credentials?: W3CVerifiableCredential[];
|
|
638
|
-
unsuspensionOptions?:
|
|
825
|
+
unsuspensionOptions?: ICheqdBulkCredentialStatusUpdateOptions;
|
|
639
826
|
verificationOptions?: IVerifyCredentialArgs;
|
|
640
827
|
fetchList?: boolean;
|
|
641
828
|
publish?: boolean;
|
|
@@ -647,7 +834,7 @@ export interface ICheqdUnsuspendBulkCredentialsWithStatusList2021Args {
|
|
|
647
834
|
returnSymmetricKey?: boolean;
|
|
648
835
|
returnStatusListMetadata?: boolean;
|
|
649
836
|
dkgOptions?: DkgOptions;
|
|
650
|
-
options?:
|
|
837
|
+
options?: ICheqdStatusListOptions;
|
|
651
838
|
fee?: DidStdFee | 'auto' | number;
|
|
652
839
|
}
|
|
653
840
|
|
|
@@ -688,7 +875,7 @@ export interface ICheqdDelegateCapacityCreditArgs {
|
|
|
688
875
|
statement?: string;
|
|
689
876
|
}
|
|
690
877
|
|
|
691
|
-
export interface
|
|
878
|
+
export interface ICheqdStatusListOptions {
|
|
692
879
|
statusListFile?: string;
|
|
693
880
|
statusListInlineBitstring?: string;
|
|
694
881
|
fee?: DidStdFee | 'auto' | number;
|
|
@@ -697,53 +884,32 @@ export interface ICheqdStatusList2021Options {
|
|
|
697
884
|
[key: string]: any;
|
|
698
885
|
}
|
|
699
886
|
|
|
700
|
-
export interface
|
|
701
|
-
issuerDid: string;
|
|
702
|
-
statusListName: string;
|
|
703
|
-
statusListIndex: number;
|
|
704
|
-
statusListVersion?: string;
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
export interface ICheqdRevokeBulkCredentialsWithStatusList2021Options {
|
|
708
|
-
issuerDid: string;
|
|
709
|
-
statusListName: string;
|
|
710
|
-
statusListIndices: number[];
|
|
711
|
-
statusListVersion?: string;
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
export interface ICheqdSuspendCredentialWithStatusList2021Options {
|
|
887
|
+
export interface ICheqdCredentialStatusUpdateOptions {
|
|
715
888
|
issuerDid: string;
|
|
716
889
|
statusListName: string;
|
|
717
890
|
statusListIndex: number;
|
|
718
891
|
statusListVersion?: string;
|
|
719
892
|
}
|
|
720
893
|
|
|
721
|
-
export interface
|
|
894
|
+
export interface ICheqdBulkCredentialStatusUpdateOptions {
|
|
722
895
|
issuerDid: string;
|
|
723
896
|
statusListName: string;
|
|
724
897
|
statusListIndices: number[];
|
|
725
898
|
statusListVersion?: string;
|
|
726
899
|
}
|
|
727
900
|
|
|
728
|
-
export
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
export interface ICheqdUnsuspendBulkCredentialsWithStatusList2021Options {
|
|
736
|
-
issuerDid: string;
|
|
737
|
-
statusListName: string;
|
|
738
|
-
statusListIndices: number[];
|
|
739
|
-
statusListVersion?: string;
|
|
901
|
+
export enum BitstringStatusValue {
|
|
902
|
+
VALID = 0, // 0x0 - valid
|
|
903
|
+
REVOKED = 1, // 0x1 - revoked
|
|
904
|
+
SUSPENDED = 2, // 0x2 - suspended
|
|
905
|
+
UNKNOWN = 3, // 0x3 - unknown
|
|
740
906
|
}
|
|
741
907
|
|
|
742
|
-
export interface
|
|
908
|
+
export interface ICheqdCheckCredentialStatusOptions {
|
|
743
909
|
issuerDid: string;
|
|
744
910
|
statusListName: string;
|
|
745
911
|
statusListIndex: number;
|
|
746
|
-
statusPurpose: DefaultStatusList2021StatusPurposeType;
|
|
912
|
+
statusPurpose: DefaultStatusList2021StatusPurposeType | BitstringStatusListPurposeType;
|
|
747
913
|
statusListVersion?: string;
|
|
748
914
|
}
|
|
749
915
|
|
|
@@ -762,10 +928,7 @@ export interface ICheqd extends IPluginMethodMap {
|
|
|
762
928
|
args: ICheqdCreateStatusList2021Args,
|
|
763
929
|
context: IContext
|
|
764
930
|
) => Promise<CreateStatusList2021Result>;
|
|
765
|
-
[BroadcastStatusList2021MethodName]: (
|
|
766
|
-
args: ICheqdBroadcastStatusList2021Args,
|
|
767
|
-
context: IContext
|
|
768
|
-
) => Promise<boolean>;
|
|
931
|
+
[BroadcastStatusList2021MethodName]: (args: ICheqdBroadcastStatusListArgs, context: IContext) => Promise<boolean>;
|
|
769
932
|
[GenerateDidDocMethodName]: (args: ICheqdGenerateDidDocArgs, context: IContext) => Promise<TExportedDIDDocWithKeys>;
|
|
770
933
|
[GenerateDidDocWithLinkedResourceMethodName]: (
|
|
771
934
|
args: ICheqdGenerateDidDocWithLinkedResourceArgs,
|
|
@@ -773,6 +936,20 @@ export interface ICheqd extends IPluginMethodMap {
|
|
|
773
936
|
) => Promise<TExportedDIDDocWithLinkedResourceWithKeys>;
|
|
774
937
|
[GenerateKeyPairMethodName]: (args: ICheqdGenerateKeyPairArgs, context: IContext) => Promise<TImportableEd25519Key>;
|
|
775
938
|
[GenerateVersionIdMethodName]: (args: ICheqdGenerateVersionIdArgs, context: IContext) => Promise<string>;
|
|
939
|
+
[CreateStatusListMethodName]: (
|
|
940
|
+
args: ICheqdCreateBitstringStatusListArgs,
|
|
941
|
+
context: IContext
|
|
942
|
+
) => Promise<CreateStatusListResult>;
|
|
943
|
+
[BroadcastStatusListMethodName]: (args: ICheqdBroadcastStatusListArgs, context: IContext) => Promise<boolean>;
|
|
944
|
+
[GenerateStatusListMethodName]: (args: ICheqdGenerateStatusListArgs, context: IContext) => Promise<string>;
|
|
945
|
+
[VerifyStatusListCredentialMethodName]: (
|
|
946
|
+
args: ICheqdVerifyStatusListCredentialArgs,
|
|
947
|
+
context: IContext
|
|
948
|
+
) => Promise<VerificationResult>;
|
|
949
|
+
[IssueCredentialWithStatusListMethodName]: (
|
|
950
|
+
args: ICheqdIssueCredentialWithStatusListArgs,
|
|
951
|
+
context: IContext
|
|
952
|
+
) => Promise<BitstringVerifiableCredential>;
|
|
776
953
|
[GenerateStatusList2021MethodName]: (args: ICheqdGenerateStatusList2021Args, context: IContext) => Promise<string>;
|
|
777
954
|
[IssueRevocableCredentialWithStatusList2021MethodName]: (
|
|
778
955
|
args: ICheqdIssueRevocableCredentialWithStatusList2021Args,
|
|
@@ -783,39 +960,55 @@ export interface ICheqd extends IPluginMethodMap {
|
|
|
783
960
|
context: IContext
|
|
784
961
|
) => Promise<VerifiableCredential>;
|
|
785
962
|
[VerifyCredentialMethodName]: (
|
|
786
|
-
args:
|
|
963
|
+
args: ICheqdVerifyCredentialWithStatusListArgs,
|
|
964
|
+
context: IContext
|
|
965
|
+
) => Promise<VerificationResult>;
|
|
966
|
+
[VerifyCredentialWithStatusListMethodName]: (
|
|
967
|
+
args: ICheqdVerifyCredentialWithBitstringArgs,
|
|
787
968
|
context: IContext
|
|
788
969
|
) => Promise<VerificationResult>;
|
|
789
970
|
[VerifyPresentationMethodName]: (
|
|
790
|
-
args:
|
|
971
|
+
args: ICheqdVerifyPresentationWithStatusListArgs,
|
|
791
972
|
context: IContext
|
|
792
973
|
) => Promise<VerificationResult>;
|
|
793
974
|
[CheckCredentialStatusMethodName]: (
|
|
794
|
-
args:
|
|
975
|
+
args: ICheqdCheckCredentialStatusWithStatusListArgs,
|
|
795
976
|
context: IContext
|
|
796
977
|
) => Promise<StatusCheckResult>;
|
|
978
|
+
[VerifyPresentationWithStatusListMethodName]: (
|
|
979
|
+
args: ICheqdVerifyPresentationWithStatusListArgs,
|
|
980
|
+
context: IContext
|
|
981
|
+
) => Promise<BitstringVerificationResult>;
|
|
982
|
+
[UpdateCredentialWithStatusListMethodName]: (
|
|
983
|
+
args: ICheqdUpdateCredentialWithStatusListArgs,
|
|
984
|
+
context: IContext
|
|
985
|
+
) => Promise<BitstringUpdateResult>;
|
|
986
|
+
[BulkUpdateCredentialsWithStatusListMethodName]: (
|
|
987
|
+
args: ICheqdBulkUpdateCredentialWithStatusListArgs,
|
|
988
|
+
context: IContext
|
|
989
|
+
) => Promise<BulkBitstringUpdateResult>;
|
|
797
990
|
[RevokeCredentialMethodName]: (
|
|
798
|
-
args:
|
|
991
|
+
args: ICheqdRevokeCredentialWithStatusListArgs,
|
|
799
992
|
context: IContext
|
|
800
993
|
) => Promise<RevocationResult>;
|
|
801
994
|
[RevokeCredentialsMethodName]: (
|
|
802
|
-
args:
|
|
995
|
+
args: ICheqdRevokeBulkCredentialsWithStatusListArgs,
|
|
803
996
|
context: IContext
|
|
804
997
|
) => Promise<BulkRevocationResult>;
|
|
805
998
|
[SuspendCredentialMethodName]: (
|
|
806
|
-
args:
|
|
999
|
+
args: ICheqdSuspendCredentialWithStatusListArgs,
|
|
807
1000
|
context: IContext
|
|
808
1001
|
) => Promise<SuspensionResult>;
|
|
809
1002
|
[SuspendCredentialsMethodName]: (
|
|
810
|
-
args:
|
|
1003
|
+
args: ICheqdSuspendBulkCredentialsWithStatusListArgs,
|
|
811
1004
|
context: IContext
|
|
812
1005
|
) => Promise<BulkSuspensionResult>;
|
|
813
1006
|
[UnsuspendCredentialMethodName]: (
|
|
814
|
-
args:
|
|
1007
|
+
args: ICheqdUnsuspendCredentialWithStatusListArgs,
|
|
815
1008
|
context: IContext
|
|
816
1009
|
) => Promise<UnsuspensionResult>;
|
|
817
1010
|
[UnsuspendCredentialsMethodName]: (
|
|
818
|
-
args:
|
|
1011
|
+
args: ICheqdUnsuspendBulkCredentialsWithStatusListArgs,
|
|
819
1012
|
context: IContext
|
|
820
1013
|
) => Promise<BulkUnsuspensionResult>;
|
|
821
1014
|
[TransactSendTokensMethodName]: (
|
|
@@ -922,6 +1115,22 @@ export class Cheqd implements IAgentPlugin {
|
|
|
922
1115
|
type: 'object',
|
|
923
1116
|
},
|
|
924
1117
|
},
|
|
1118
|
+
cheqdCreateStatusList: {
|
|
1119
|
+
description: 'Create a new Bitstring Status List',
|
|
1120
|
+
arguments: {
|
|
1121
|
+
type: 'object',
|
|
1122
|
+
properties: {
|
|
1123
|
+
args: {
|
|
1124
|
+
type: 'object',
|
|
1125
|
+
description: 'A cheqdCreateBitstringStatusListArgs object as any for extensibility',
|
|
1126
|
+
},
|
|
1127
|
+
},
|
|
1128
|
+
required: ['args'],
|
|
1129
|
+
},
|
|
1130
|
+
returnType: {
|
|
1131
|
+
type: 'object',
|
|
1132
|
+
},
|
|
1133
|
+
},
|
|
925
1134
|
cheqdBroadcastStatusList2021: {
|
|
926
1135
|
description: 'Broadcast a Status List 2021 to cheqd ledger',
|
|
927
1136
|
arguments: {
|
|
@@ -929,7 +1138,23 @@ export class Cheqd implements IAgentPlugin {
|
|
|
929
1138
|
properties: {
|
|
930
1139
|
args: {
|
|
931
1140
|
type: 'object',
|
|
932
|
-
description: 'A
|
|
1141
|
+
description: 'A cheqdBroadcastStatusListArgs object as any for extensibility',
|
|
1142
|
+
},
|
|
1143
|
+
},
|
|
1144
|
+
required: ['args'],
|
|
1145
|
+
},
|
|
1146
|
+
returnType: {
|
|
1147
|
+
type: 'object',
|
|
1148
|
+
},
|
|
1149
|
+
},
|
|
1150
|
+
cheqdBroadcastStatusList: {
|
|
1151
|
+
description: 'Broadcast a Bitstring Status List to cheqd ledger',
|
|
1152
|
+
arguments: {
|
|
1153
|
+
type: 'object',
|
|
1154
|
+
properties: {
|
|
1155
|
+
args: {
|
|
1156
|
+
type: 'object',
|
|
1157
|
+
description: 'A cheqdBroadcastStatusListArgs object as any for extensibility',
|
|
933
1158
|
},
|
|
934
1159
|
},
|
|
935
1160
|
required: ['args'],
|
|
@@ -1016,6 +1241,38 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1016
1241
|
type: 'string',
|
|
1017
1242
|
},
|
|
1018
1243
|
},
|
|
1244
|
+
cheqdGenerateStatusList: {
|
|
1245
|
+
description: 'Generate a new Bitstring Status List',
|
|
1246
|
+
arguments: {
|
|
1247
|
+
type: 'object',
|
|
1248
|
+
properties: {
|
|
1249
|
+
args: {
|
|
1250
|
+
type: 'object',
|
|
1251
|
+
description: 'A cheqdGenerateStatusListArgs object as any for extensibility',
|
|
1252
|
+
},
|
|
1253
|
+
},
|
|
1254
|
+
},
|
|
1255
|
+
returnType: {
|
|
1256
|
+
type: 'string',
|
|
1257
|
+
},
|
|
1258
|
+
},
|
|
1259
|
+
cheqdIssueCredentialWithStatusList: {
|
|
1260
|
+
description:
|
|
1261
|
+
'Issue a revocable or suspendable credential with a Bitstring Status List as credential status registry',
|
|
1262
|
+
arguments: {
|
|
1263
|
+
type: 'object',
|
|
1264
|
+
properties: {
|
|
1265
|
+
args: {
|
|
1266
|
+
type: 'object',
|
|
1267
|
+
description: 'A cheqdIssueCredentialWithStatusListArgs object as any for extensibility',
|
|
1268
|
+
},
|
|
1269
|
+
},
|
|
1270
|
+
required: ['args'],
|
|
1271
|
+
},
|
|
1272
|
+
returnType: {
|
|
1273
|
+
type: 'object',
|
|
1274
|
+
},
|
|
1275
|
+
},
|
|
1019
1276
|
cheqdIssueRevocableCredentialWithStatusList2021: {
|
|
1020
1277
|
description: 'Issue a revocable credential with a Status List 2021 as credential status registry',
|
|
1021
1278
|
arguments: {
|
|
@@ -1024,7 +1281,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1024
1281
|
args: {
|
|
1025
1282
|
type: 'object',
|
|
1026
1283
|
description:
|
|
1027
|
-
'A
|
|
1284
|
+
'A cheqdIssueRevocableCredentialWithStatusList2021Args object as any for extensibility',
|
|
1028
1285
|
},
|
|
1029
1286
|
},
|
|
1030
1287
|
required: ['args'],
|
|
@@ -1041,7 +1298,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1041
1298
|
args: {
|
|
1042
1299
|
type: 'object',
|
|
1043
1300
|
description:
|
|
1044
|
-
'A
|
|
1301
|
+
'A cheqdIssueSuspendableCredentialWithStatusList2021Args object as any for extensibility',
|
|
1045
1302
|
},
|
|
1046
1303
|
},
|
|
1047
1304
|
required: ['args'],
|
|
@@ -1059,7 +1316,25 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1059
1316
|
args: {
|
|
1060
1317
|
type: 'object',
|
|
1061
1318
|
description:
|
|
1062
|
-
'A
|
|
1319
|
+
'A cheqdVerifyCredentialWithStatusListArgs object as any for extensibility',
|
|
1320
|
+
},
|
|
1321
|
+
},
|
|
1322
|
+
required: ['args'],
|
|
1323
|
+
},
|
|
1324
|
+
returnType: {
|
|
1325
|
+
type: 'object',
|
|
1326
|
+
},
|
|
1327
|
+
},
|
|
1328
|
+
cheqdVerifyCredentialWithStatusList: {
|
|
1329
|
+
description:
|
|
1330
|
+
'Verify a credential, enhanced by revocation / suspension check with a Bitstring Status List as credential status registry',
|
|
1331
|
+
arguments: {
|
|
1332
|
+
type: 'object',
|
|
1333
|
+
properties: {
|
|
1334
|
+
args: {
|
|
1335
|
+
type: 'object',
|
|
1336
|
+
description:
|
|
1337
|
+
'A cheqdVerifyCredentialWithStatusListArgs object as any for extensibility',
|
|
1063
1338
|
},
|
|
1064
1339
|
},
|
|
1065
1340
|
required: ['args'],
|
|
@@ -1077,7 +1352,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1077
1352
|
args: {
|
|
1078
1353
|
type: 'object',
|
|
1079
1354
|
description:
|
|
1080
|
-
'A
|
|
1355
|
+
'A cheqdVerifyPresentationWithStatusListArgs object as any for extensibility',
|
|
1081
1356
|
},
|
|
1082
1357
|
},
|
|
1083
1358
|
required: ['args'],
|
|
@@ -1095,7 +1370,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1095
1370
|
args: {
|
|
1096
1371
|
type: 'object',
|
|
1097
1372
|
description:
|
|
1098
|
-
'A
|
|
1373
|
+
'A cheqdCheckCredentialStatusWithStatusListArgs object as any for extensibility',
|
|
1099
1374
|
},
|
|
1100
1375
|
},
|
|
1101
1376
|
required: ['args'],
|
|
@@ -1112,7 +1387,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1112
1387
|
args: {
|
|
1113
1388
|
type: 'object',
|
|
1114
1389
|
description:
|
|
1115
|
-
'A
|
|
1390
|
+
'A cheqdRevokeCredentialWithStatusListArgs object as any for extensibility',
|
|
1116
1391
|
},
|
|
1117
1392
|
},
|
|
1118
1393
|
required: ['args'],
|
|
@@ -1129,7 +1404,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1129
1404
|
args: {
|
|
1130
1405
|
type: 'object',
|
|
1131
1406
|
description:
|
|
1132
|
-
'A
|
|
1407
|
+
'A cheqdRevokeBulkCredentialsWithStatusListArgs object as any for extensibility',
|
|
1133
1408
|
},
|
|
1134
1409
|
},
|
|
1135
1410
|
required: ['args'],
|
|
@@ -1146,7 +1421,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1146
1421
|
args: {
|
|
1147
1422
|
type: 'object',
|
|
1148
1423
|
description:
|
|
1149
|
-
'A
|
|
1424
|
+
'A cheqdSuspendCredentialWithStatusListArgs object as any for extensibility',
|
|
1150
1425
|
},
|
|
1151
1426
|
},
|
|
1152
1427
|
required: ['args'],
|
|
@@ -1164,7 +1439,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1164
1439
|
args: {
|
|
1165
1440
|
type: 'object',
|
|
1166
1441
|
description:
|
|
1167
|
-
'A
|
|
1442
|
+
'A cheqdSuspendBulkCredentialsWithStatusListArgs object as any for extensibility',
|
|
1168
1443
|
},
|
|
1169
1444
|
},
|
|
1170
1445
|
required: ['args'],
|
|
@@ -1181,7 +1456,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1181
1456
|
args: {
|
|
1182
1457
|
type: 'object',
|
|
1183
1458
|
description:
|
|
1184
|
-
'
|
|
1459
|
+
'cheqdUnsuspendCredentialWithStatusListArgs object as any for extensibility',
|
|
1185
1460
|
},
|
|
1186
1461
|
},
|
|
1187
1462
|
required: ['args'],
|
|
@@ -1199,7 +1474,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1199
1474
|
args: {
|
|
1200
1475
|
type: 'object',
|
|
1201
1476
|
description:
|
|
1202
|
-
'A
|
|
1477
|
+
'A cheqdUnsuspendBulkCredentialsWithStatusListArgs object as any for extensibility',
|
|
1203
1478
|
},
|
|
1204
1479
|
},
|
|
1205
1480
|
required: ['args'],
|
|
@@ -1246,9 +1521,19 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1246
1521
|
private readonly supportedDidProviders: CheqdDIDProvider[];
|
|
1247
1522
|
private didProvider: CheqdDIDProvider;
|
|
1248
1523
|
private providerId: string;
|
|
1524
|
+
// Deprecate below constants in future versions
|
|
1249
1525
|
static readonly defaultStatusList2021Length: number = 16 * 1024 * 8; // 16KB in bits or 131072 bits / entries
|
|
1250
1526
|
static readonly defaultContextV1 = 'https://www.w3.org/2018/credentials/v1';
|
|
1251
1527
|
static readonly statusList2021Context = 'https://w3id.org/vc-status-list-2021/v1';
|
|
1528
|
+
// END: Deprecate
|
|
1529
|
+
static readonly DefaultBitstringContexts = {
|
|
1530
|
+
v2: 'https://www.w3.org/ns/credentials/v2',
|
|
1531
|
+
statusList: 'https://www.w3.org/ns/credentials/status/v1',
|
|
1532
|
+
};
|
|
1533
|
+
// Default bitstring status list size in bits
|
|
1534
|
+
static readonly DefaultBitstringStatusSize: number = 2; // 2 bits per credential (0, 1, 2, 3)
|
|
1535
|
+
// Minimum bitstring length for compliance
|
|
1536
|
+
static readonly DefaultBitstringLength: number = 16 * 1024 * 8; // 16KB in bits or 131072 bits (spec minimum)
|
|
1252
1537
|
|
|
1253
1538
|
constructor(args: { providers: CheqdDIDProvider[] }) {
|
|
1254
1539
|
if (typeof args.providers !== 'object') {
|
|
@@ -1266,18 +1551,27 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1266
1551
|
[CreateResourceMethodName]: this.CreateResource.bind(this),
|
|
1267
1552
|
[CreateStatusList2021MethodName]: this.CreateStatusList2021.bind(this),
|
|
1268
1553
|
[BroadcastStatusList2021MethodName]: this.BroadcastStatusList2021.bind(this),
|
|
1554
|
+
[CreateStatusListMethodName]: this.CreateBitstringStatusList.bind(this),
|
|
1555
|
+
[BroadcastStatusListMethodName]: this.BroadcastBitstringStatusList.bind(this),
|
|
1269
1556
|
[GenerateDidDocMethodName]: this.GenerateDidDoc.bind(this),
|
|
1270
1557
|
[GenerateDidDocWithLinkedResourceMethodName]: this.GenerateDidDocWithLinkedResource.bind(this),
|
|
1271
1558
|
[GenerateKeyPairMethodName]: this.GenerateIdentityKeys.bind(this),
|
|
1272
1559
|
[GenerateVersionIdMethodName]: this.GenerateVersionId.bind(this),
|
|
1273
1560
|
[GenerateStatusList2021MethodName]: this.GenerateStatusList2021.bind(this),
|
|
1561
|
+
[GenerateStatusListMethodName]: this.GenerateBitstringStatusList.bind(this),
|
|
1562
|
+
[VerifyStatusListCredentialMethodName]: this.VerifyStatusListCredential.bind(this),
|
|
1563
|
+
[IssueCredentialWithStatusListMethodName]: this.IssueCredentialWithBitstringStatusList.bind(this),
|
|
1274
1564
|
[IssueRevocableCredentialWithStatusList2021MethodName]:
|
|
1275
1565
|
this.IssueRevocableCredentialWithStatusList2021.bind(this),
|
|
1276
1566
|
[IssueSuspendableCredentialWithStatusList2021MethodName]:
|
|
1277
1567
|
this.IssueSuspendableCredentialWithStatusList2021.bind(this),
|
|
1278
1568
|
[VerifyCredentialMethodName]: this.VerifyCredentialWithStatusList2021.bind(this),
|
|
1569
|
+
[VerifyCredentialWithStatusListMethodName]: this.VerifyCredentialWithBitstringStatusList.bind(this),
|
|
1279
1570
|
[VerifyPresentationMethodName]: this.VerifyPresentationWithStatusList2021.bind(this),
|
|
1280
1571
|
[CheckCredentialStatusMethodName]: this.CheckCredentialStatusWithStatusList2021.bind(this),
|
|
1572
|
+
[VerifyPresentationWithStatusListMethodName]: this.VerifyPresentationWithBitstringStatusList.bind(this),
|
|
1573
|
+
[UpdateCredentialWithStatusListMethodName]: this.UpdateCredentialWithStatusList.bind(this),
|
|
1574
|
+
[BulkUpdateCredentialsWithStatusListMethodName]: this.BulkUpdateCredentialsWithStatusList.bind(this),
|
|
1281
1575
|
[RevokeCredentialMethodName]: this.RevokeCredentialWithStatusList2021.bind(this),
|
|
1282
1576
|
[RevokeCredentialsMethodName]: this.RevokeBulkCredentialsWithStatusList2021.bind(this),
|
|
1283
1577
|
[SuspendCredentialMethodName]: this.SuspendCredentialWithStatusList2021.bind(this),
|
|
@@ -1467,10 +1761,10 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1467
1761
|
throw new Error('[did-provider-cheqd]: statusListEncoding must be string');
|
|
1468
1762
|
}
|
|
1469
1763
|
|
|
1470
|
-
if (!Object.values(
|
|
1764
|
+
if (!Object.values(DefaultStatusListEncodings).includes(args.statusListEncoding)) {
|
|
1471
1765
|
throw new Error(
|
|
1472
1766
|
`[did-provider-cheqd]: statusListEncoding must be one of ${Object.values(
|
|
1473
|
-
|
|
1767
|
+
DefaultStatusListEncodings
|
|
1474
1768
|
).join(', ')}`
|
|
1475
1769
|
);
|
|
1476
1770
|
}
|
|
@@ -1549,7 +1843,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1549
1843
|
// generate bitstring
|
|
1550
1844
|
const bitstring = await context.agent[GenerateStatusList2021MethodName]({
|
|
1551
1845
|
length: args?.statusListLength || Cheqd.defaultStatusList2021Length,
|
|
1552
|
-
bitstringEncoding: args?.statusListEncoding ||
|
|
1846
|
+
bitstringEncoding: args?.statusListEncoding || DefaultStatusListEncodings.base64url,
|
|
1553
1847
|
});
|
|
1554
1848
|
|
|
1555
1849
|
// construct data and metadata tuple
|
|
@@ -1558,7 +1852,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1558
1852
|
// encrypt bitstring - case: symmetric
|
|
1559
1853
|
const { encryptedString: symmetricEncryptionCiphertext, symmetricKey } =
|
|
1560
1854
|
await LitProtocol.encryptDirect(
|
|
1561
|
-
fromString(bitstring, args?.statusListEncoding ||
|
|
1855
|
+
fromString(bitstring, args?.statusListEncoding || DefaultStatusListEncodings.base64url)
|
|
1562
1856
|
);
|
|
1563
1857
|
|
|
1564
1858
|
// instantiate dkg-threshold client, in which case lit-protocol is used
|
|
@@ -1590,7 +1884,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1590
1884
|
|
|
1591
1885
|
// encrypt bitstring - case: threshold
|
|
1592
1886
|
const { encryptedString: thresholdEncryptionCiphertext, stringHash } = await lit.encrypt(
|
|
1593
|
-
fromString(bitstring, args?.statusListEncoding ||
|
|
1887
|
+
fromString(bitstring, args?.statusListEncoding || DefaultStatusListEncodings.base64url),
|
|
1594
1888
|
unifiedAccessControlConditions
|
|
1595
1889
|
);
|
|
1596
1890
|
|
|
@@ -1614,7 +1908,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1614
1908
|
metadata: {
|
|
1615
1909
|
type: DefaultStatusList2021ResourceTypes.revocation,
|
|
1616
1910
|
encrypted: true,
|
|
1617
|
-
encoding: args?.statusListEncoding ||
|
|
1911
|
+
encoding: args?.statusListEncoding || DefaultStatusListEncodings.base64url,
|
|
1618
1912
|
statusListHash: stringHash,
|
|
1619
1913
|
paymentConditions: args.paymentConditions,
|
|
1620
1914
|
},
|
|
@@ -1638,7 +1932,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1638
1932
|
metadata: {
|
|
1639
1933
|
type: DefaultStatusList2021ResourceTypes.suspension,
|
|
1640
1934
|
encrypted: true,
|
|
1641
|
-
encoding: args?.statusListEncoding ||
|
|
1935
|
+
encoding: args?.statusListEncoding || DefaultStatusListEncodings.base64url,
|
|
1642
1936
|
statusListHash: stringHash,
|
|
1643
1937
|
paymentConditions: args.paymentConditions,
|
|
1644
1938
|
},
|
|
@@ -1668,7 +1962,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1668
1962
|
metadata: {
|
|
1669
1963
|
type: DefaultStatusList2021ResourceTypes.revocation,
|
|
1670
1964
|
encrypted: false,
|
|
1671
|
-
encoding: args?.statusListEncoding ||
|
|
1965
|
+
encoding: args?.statusListEncoding || DefaultStatusListEncodings.base64url,
|
|
1672
1966
|
},
|
|
1673
1967
|
} satisfies StatusList2021Revocation,
|
|
1674
1968
|
undefined,
|
|
@@ -1685,7 +1979,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1685
1979
|
metadata: {
|
|
1686
1980
|
type: DefaultStatusList2021ResourceTypes.suspension,
|
|
1687
1981
|
encrypted: false,
|
|
1688
|
-
encoding: args?.statusListEncoding ||
|
|
1982
|
+
encoding: args?.statusListEncoding || DefaultStatusListEncodings.base64url,
|
|
1689
1983
|
},
|
|
1690
1984
|
} satisfies StatusList2021Suspension,
|
|
1691
1985
|
undefined,
|
|
@@ -1714,7 +2008,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1714
2008
|
network: network as CheqdNetwork,
|
|
1715
2009
|
}),
|
|
1716
2010
|
resource: data[0],
|
|
1717
|
-
resourceMetadata: await Cheqd.
|
|
2011
|
+
resourceMetadata: await Cheqd.fetchStatusListMetadata({
|
|
1718
2012
|
credentialStatus: {
|
|
1719
2013
|
id: `${DefaultResolverUrl}${args.issuerDid}?resourceName=${args.statusListName}&resourceType=${
|
|
1720
2014
|
DefaultStatusList2021ResourceTypes[args.statusPurpose]
|
|
@@ -1727,7 +2021,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1727
2021
|
} satisfies CreateStatusList2021Result;
|
|
1728
2022
|
}
|
|
1729
2023
|
|
|
1730
|
-
private async BroadcastStatusList2021(args:
|
|
2024
|
+
private async BroadcastStatusList2021(args: ICheqdBroadcastStatusListArgs, context: IContext) {
|
|
1731
2025
|
if (typeof args.kms !== 'string') {
|
|
1732
2026
|
throw new Error('[did-provider-cheqd]: kms is required');
|
|
1733
2027
|
}
|
|
@@ -1751,11 +2045,10 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1751
2045
|
// TODO: validate data as per bitstring
|
|
1752
2046
|
|
|
1753
2047
|
// validate resource type
|
|
1754
|
-
|
|
2048
|
+
const allowedTypes = [...Object.values(DefaultStatusList2021ResourceTypes), 'BitstringStatusListCredential'];
|
|
2049
|
+
if (!Object.values(allowedTypes).includes(args?.payload?.resourceType)) {
|
|
1755
2050
|
throw new Error(
|
|
1756
|
-
`[did-provider-cheqd]: resourceType must be one of ${Object.values(
|
|
1757
|
-
DefaultStatusList2021ResourceTypes
|
|
1758
|
-
).join(', ')}`
|
|
2051
|
+
`[did-provider-cheqd]: resourceType must be one of ${Object.values(allowedTypes).join(', ')}`
|
|
1759
2052
|
);
|
|
1760
2053
|
}
|
|
1761
2054
|
|
|
@@ -1779,69 +2072,527 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1779
2072
|
);
|
|
1780
2073
|
}
|
|
1781
2074
|
|
|
1782
|
-
private async
|
|
1783
|
-
if (typeof args.
|
|
1784
|
-
throw new Error('[did-provider-cheqd]:
|
|
2075
|
+
private async CreateBitstringStatusList(args: ICheqdCreateBitstringStatusListArgs, context: IContext) {
|
|
2076
|
+
if (typeof args.kms !== 'string') {
|
|
2077
|
+
throw new Error('[did-provider-cheqd]: kms is required');
|
|
1785
2078
|
}
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
throw new Error('[did-provider-cheqd]: methodSpecificIdAlgo is required');
|
|
2079
|
+
if (typeof args.issuerDid !== 'string' || !args.issuerDid) {
|
|
2080
|
+
throw new Error('[did-provider-cheqd]: issuerDid is required');
|
|
1789
2081
|
}
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
throw new Error('[did-provider-cheqd]: network is required');
|
|
2082
|
+
if (typeof args.statusListName !== 'string' || !args.statusListName) {
|
|
2083
|
+
throw new Error('[did-provider-cheqd]: statusListName is required');
|
|
1793
2084
|
}
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
const keyPairHex: IKeyPair = {
|
|
1797
|
-
publicKey: toString(fromString(keyPair.publicKey, 'base64'), 'hex'),
|
|
1798
|
-
privateKey: toString(fromString(keyPair.privateKey, 'base64'), 'hex'),
|
|
1799
|
-
};
|
|
1800
|
-
const verificationKeys = createVerificationKeys(
|
|
1801
|
-
keyPair.publicKey,
|
|
1802
|
-
args.methodSpecificIdAlgo,
|
|
1803
|
-
'key-1',
|
|
1804
|
-
args.network
|
|
1805
|
-
);
|
|
1806
|
-
const verificationMethods = createDidVerificationMethod([args.verificationMethod], [verificationKeys]);
|
|
1807
|
-
|
|
1808
|
-
return {
|
|
1809
|
-
didDoc: createDidPayload(verificationMethods, [verificationKeys]),
|
|
1810
|
-
versionId: v4(),
|
|
1811
|
-
keys: [
|
|
1812
|
-
{
|
|
1813
|
-
publicKeyHex: keyPairHex.publicKey,
|
|
1814
|
-
privateKeyHex: keyPairHex.privateKey,
|
|
1815
|
-
kid: keyPairHex.publicKey,
|
|
1816
|
-
type: 'Ed25519',
|
|
1817
|
-
},
|
|
1818
|
-
],
|
|
1819
|
-
};
|
|
1820
|
-
}
|
|
1821
|
-
|
|
1822
|
-
private async GenerateDidDocWithLinkedResource(
|
|
1823
|
-
args: any,
|
|
1824
|
-
context: IContext
|
|
1825
|
-
): Promise<TExportedDIDDocWithLinkedResourceWithKeys> {
|
|
1826
|
-
if (typeof args.verificationMethod !== 'string') {
|
|
1827
|
-
throw new Error('[did-provider-cheqd]: verificationMethod is required');
|
|
2085
|
+
if (!args.statusPurpose) {
|
|
2086
|
+
throw new Error('[did-provider-cheqd]: statusPurpose is required');
|
|
1828
2087
|
}
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
throw new Error('[did-provider-cheqd]: methodSpecificIdAlgo is required');
|
|
2088
|
+
if (typeof args.encrypted === 'undefined') {
|
|
2089
|
+
throw new Error('[did-provider-cheqd]: encrypted is required');
|
|
1832
2090
|
}
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
2091
|
+
// validate statusPurpose
|
|
2092
|
+
const statusPurpose = Array.isArray(args.statusPurpose) ? args.statusPurpose[0] : args.statusPurpose;
|
|
2093
|
+
if (!Object.values(BitstringStatusPurposeTypes).includes(statusPurpose)) {
|
|
2094
|
+
throw new Error(
|
|
2095
|
+
`[did-provider-cheqd]: statusPurpose must be in ${Object.values(BitstringStatusPurposeTypes).join(
|
|
2096
|
+
', '
|
|
2097
|
+
)}`
|
|
2098
|
+
);
|
|
1836
2099
|
}
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
2100
|
+
// validate statusListLength
|
|
2101
|
+
if (args?.statusListLength) {
|
|
2102
|
+
if (typeof args.statusListLength !== 'number') {
|
|
2103
|
+
throw new Error('[did-provider-cheqd]: statusListLength must be number');
|
|
2104
|
+
}
|
|
2105
|
+
if (args.statusListLength < Cheqd.DefaultBitstringLength) {
|
|
2106
|
+
throw new Error(
|
|
2107
|
+
`[did-provider-cheqd]: statusListLength must be greater than or equal to ${Cheqd.DefaultBitstringLength} number of entries`
|
|
2108
|
+
);
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
// validate statusListEncoding, W3C spec only supports base64url encoding
|
|
2112
|
+
if (args?.statusListEncoding) {
|
|
2113
|
+
if (typeof args.statusListEncoding !== 'string') {
|
|
2114
|
+
throw new Error('[did-provider-cheqd]: statusListEncoding must be string');
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
if (args.statusListEncoding !== DefaultStatusListEncodings.base64url) {
|
|
2118
|
+
throw new Error(
|
|
2119
|
+
`[did-provider-cheqd]: statusListEncoding must be ${DefaultStatusListEncodings.base64url}`
|
|
2120
|
+
);
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
// validate validUntil
|
|
2124
|
+
if (args?.validUntil) {
|
|
2125
|
+
if (typeof args.validUntil !== 'string') {
|
|
2126
|
+
throw new Error('[did-provider-cheqd]: validUntil must be string');
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
if (new Date() <= new Date(args.validUntil)) {
|
|
2130
|
+
throw new Error('[did-provider-cheqd]: validUntil must be greater than current date');
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
// validate args in pairs - case: encrypted
|
|
2134
|
+
if (args.encrypted) {
|
|
2135
|
+
// validate paymentConditions
|
|
2136
|
+
if (
|
|
2137
|
+
!args?.paymentConditions ||
|
|
2138
|
+
!args?.paymentConditions?.length ||
|
|
2139
|
+
!Array.isArray(args?.paymentConditions) ||
|
|
2140
|
+
args?.paymentConditions.length === 0
|
|
2141
|
+
) {
|
|
2142
|
+
throw new Error('[did-provider-cheqd]: paymentConditions is required');
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2145
|
+
if (
|
|
2146
|
+
!args?.paymentConditions?.every(
|
|
2147
|
+
(condition) =>
|
|
2148
|
+
condition.feePaymentAddress && condition.feePaymentAmount && condition.intervalInSeconds
|
|
2149
|
+
)
|
|
2150
|
+
) {
|
|
2151
|
+
throw new Error(
|
|
2152
|
+
'[did-provider-cheqd]: paymentConditions must contain feePaymentAddress and feeAmount and intervalInSeconds'
|
|
2153
|
+
);
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
if (
|
|
2157
|
+
!args?.paymentConditions?.every(
|
|
2158
|
+
(condition) =>
|
|
2159
|
+
typeof condition.feePaymentAddress === 'string' &&
|
|
2160
|
+
typeof condition.feePaymentAmount === 'string' &&
|
|
2161
|
+
typeof condition.intervalInSeconds === 'number'
|
|
2162
|
+
)
|
|
2163
|
+
) {
|
|
2164
|
+
throw new Error(
|
|
2165
|
+
'[did-provider-cheqd]: feePaymentAddress and feePaymentAmount must be string and intervalInSeconds must be number'
|
|
2166
|
+
);
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
if (
|
|
2170
|
+
!args?.paymentConditions?.every(
|
|
2171
|
+
(condition) => condition.type === AccessControlConditionTypes.timelockPayment
|
|
2172
|
+
)
|
|
2173
|
+
) {
|
|
2174
|
+
throw new Error('[did-provider-cheqd]: paymentConditions must be of type timelockPayment');
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
// get network
|
|
2178
|
+
const network = args.issuerDid.split(':')[2];
|
|
2179
|
+
// define provider
|
|
2180
|
+
const provider = (function (that) {
|
|
2181
|
+
// switch on network
|
|
2182
|
+
return (
|
|
2183
|
+
that.supportedDidProviders.find((provider) => provider.network === network) ||
|
|
2184
|
+
(function () {
|
|
2185
|
+
throw new Error(`[did-provider-cheqd]: no relevant providers found`);
|
|
2186
|
+
})()
|
|
2187
|
+
);
|
|
2188
|
+
})(this);
|
|
2189
|
+
// generate bitstring
|
|
2190
|
+
const bitstring = await context.agent[GenerateStatusListMethodName]({
|
|
2191
|
+
statusSize: args?.statusSize,
|
|
2192
|
+
length: args?.statusListLength,
|
|
2193
|
+
bitstringEncoding: args?.statusListEncoding || DefaultStatusListEncodings.base64url,
|
|
2194
|
+
});
|
|
2195
|
+
// Generate proof without credentialSubject.encodedList property
|
|
2196
|
+
const issuanceOptions = {
|
|
2197
|
+
credential: {
|
|
2198
|
+
'@context': [Cheqd.defaultContextV1], // TODO: use v2 context when v2 credential support enabled
|
|
2199
|
+
type: ['VerifiableCredential', BitstringStatusListResourceType],
|
|
2200
|
+
issuer: args.issuerDid,
|
|
2201
|
+
issuanceDate: new Date().toISOString(),
|
|
2202
|
+
expirationDate: args?.validUntil,
|
|
2203
|
+
credentialSubject: {
|
|
2204
|
+
type: 'BitstringStatusList',
|
|
2205
|
+
statusPurpose: args.statusPurpose,
|
|
2206
|
+
ttl: args?.ttl,
|
|
2207
|
+
},
|
|
2208
|
+
},
|
|
2209
|
+
proofFormat: 'jwt',
|
|
2210
|
+
} as ICreateVerifiableCredentialArgs;
|
|
2211
|
+
const issued = await context.agent.createVerifiableCredential(issuanceOptions);
|
|
2212
|
+
// construct data and metadata tuple
|
|
2213
|
+
const data = args.encrypted
|
|
2214
|
+
? await (async function (that: Cheqd) {
|
|
2215
|
+
// encrypt bitstring - case: symmetric
|
|
2216
|
+
const { encryptedString: symmetricEncryptionCiphertext, symmetricKey } =
|
|
2217
|
+
await LitProtocol.encryptDirect(
|
|
2218
|
+
fromString(bitstring, args?.statusListEncoding || DefaultStatusListEncodings.base64url)
|
|
2219
|
+
);
|
|
2220
|
+
|
|
2221
|
+
// instantiate dkg-threshold client, in which case lit-protocol is used
|
|
2222
|
+
const lit = await provider.instantiateDkgThresholdProtocolClient({});
|
|
2223
|
+
|
|
2224
|
+
// construct access control conditions
|
|
2225
|
+
const unifiedAccessControlConditions = await Promise.all(
|
|
2226
|
+
args.paymentConditions!.map(async (condition) => {
|
|
2227
|
+
switch (condition.type) {
|
|
2228
|
+
case AccessControlConditionTypes.timelockPayment:
|
|
2229
|
+
return await LitProtocol.generateCosmosAccessControlConditionInverseTimelock(
|
|
2230
|
+
{
|
|
2231
|
+
key: '$.tx_responses.*.timestamp',
|
|
2232
|
+
comparator: '<=',
|
|
2233
|
+
value: `${condition.intervalInSeconds}`,
|
|
2234
|
+
},
|
|
2235
|
+
condition.feePaymentAmount,
|
|
2236
|
+
condition.feePaymentAddress,
|
|
2237
|
+
condition?.blockHeight,
|
|
2238
|
+
args?.dkgOptions?.chain || that.didProvider.dkgOptions.chain
|
|
2239
|
+
);
|
|
2240
|
+
default:
|
|
2241
|
+
throw new Error(
|
|
2242
|
+
`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`
|
|
2243
|
+
);
|
|
2244
|
+
}
|
|
2245
|
+
})
|
|
2246
|
+
);
|
|
2247
|
+
// encrypt bitstring - case: threshold
|
|
2248
|
+
const { encryptedString: thresholdEncryptionCiphertext, stringHash } = await lit.encrypt(
|
|
2249
|
+
fromString(bitstring, args?.statusListEncoding || DefaultStatusListEncodings.base64url),
|
|
2250
|
+
unifiedAccessControlConditions
|
|
2251
|
+
);
|
|
2252
|
+
// construct encoded list
|
|
2253
|
+
const { encodedList, symmetricLength } = await encodeWithMetadata(
|
|
2254
|
+
symmetricEncryptionCiphertext,
|
|
2255
|
+
thresholdEncryptionCiphertext
|
|
2256
|
+
);
|
|
2257
|
+
issued.credentialSubject = {
|
|
2258
|
+
type: 'BitstringStatusList',
|
|
2259
|
+
statusPurpose: args.statusPurpose,
|
|
2260
|
+
encodedList,
|
|
2261
|
+
ttl: args?.ttl,
|
|
2262
|
+
};
|
|
2263
|
+
|
|
2264
|
+
// return result tuple
|
|
2265
|
+
return [
|
|
2266
|
+
{
|
|
2267
|
+
bitstringStatusListCredential: issued as BitstringStatusListCredential,
|
|
2268
|
+
metadata: {
|
|
2269
|
+
encrypted: true,
|
|
2270
|
+
encoding: args?.statusListEncoding || DefaultStatusListEncodings.base64url,
|
|
2271
|
+
length: args?.statusListLength || Cheqd.DefaultBitstringLength,
|
|
2272
|
+
statusSize: args?.statusSize,
|
|
2273
|
+
statusMessages: args?.statusMessages || [],
|
|
2274
|
+
statusListHash: stringHash,
|
|
2275
|
+
symmetricLength,
|
|
2276
|
+
paymentConditions: args.paymentConditions,
|
|
2277
|
+
},
|
|
2278
|
+
} satisfies BitstringStatusList,
|
|
2279
|
+
{
|
|
2280
|
+
symmetricEncryptionCiphertext: await blobToHexString(symmetricEncryptionCiphertext),
|
|
2281
|
+
thresholdEncryptionCiphertext: toString(thresholdEncryptionCiphertext, 'hex'),
|
|
2282
|
+
stringHash,
|
|
2283
|
+
symmetricKey: toString(symmetricKey, 'hex'),
|
|
2284
|
+
},
|
|
2285
|
+
] satisfies [BitstringStatusList, EncryptionResult];
|
|
2286
|
+
})(this)
|
|
2287
|
+
: await (async function () {
|
|
2288
|
+
issued.credentialSubject = {
|
|
2289
|
+
type: 'BitstringStatusList',
|
|
2290
|
+
statusPurpose: args.statusPurpose,
|
|
2291
|
+
encodedList: bitstring,
|
|
2292
|
+
ttl: args?.ttl,
|
|
2293
|
+
};
|
|
2294
|
+
return [
|
|
2295
|
+
{
|
|
2296
|
+
bitstringStatusListCredential: issued as BitstringStatusListCredential,
|
|
2297
|
+
metadata: {
|
|
2298
|
+
encrypted: false,
|
|
2299
|
+
encoding: args?.statusListEncoding || DefaultStatusListEncodings.base64url,
|
|
2300
|
+
length: args?.statusListLength || Cheqd.DefaultBitstringLength,
|
|
2301
|
+
statusSize: args?.statusSize,
|
|
2302
|
+
statusMessages: args?.statusMessages || [],
|
|
2303
|
+
},
|
|
2304
|
+
} satisfies BitstringStatusList,
|
|
2305
|
+
undefined,
|
|
2306
|
+
] satisfies [BitstringStatusList, undefined];
|
|
2307
|
+
})();
|
|
2308
|
+
|
|
2309
|
+
// construct payload
|
|
2310
|
+
const payload = {
|
|
2311
|
+
id: v4(),
|
|
2312
|
+
collectionId: args.issuerDid.split(':').reverse()[0],
|
|
2313
|
+
name: args.statusListName,
|
|
2314
|
+
resourceType: BitstringStatusListResourceType,
|
|
2315
|
+
version: args?.resourceVersion || new Date().toISOString(),
|
|
2316
|
+
alsoKnownAs: args?.alsoKnownAs || [],
|
|
2317
|
+
data: fromString(JSON.stringify(data[0]), 'utf-8'),
|
|
2318
|
+
} satisfies BitstringStatusListResourcePayload;
|
|
2319
|
+
|
|
2320
|
+
// return result
|
|
2321
|
+
return {
|
|
2322
|
+
created: await context.agent[BroadcastStatusListMethodName]({
|
|
2323
|
+
kms: args.kms,
|
|
2324
|
+
payload,
|
|
2325
|
+
network: network as CheqdNetwork,
|
|
2326
|
+
}),
|
|
2327
|
+
resource: data[0],
|
|
2328
|
+
resourceMetadata: await Cheqd.fetchStatusListMetadata({
|
|
2329
|
+
credentialStatus: {
|
|
2330
|
+
id: `${DefaultResolverUrl}${args.issuerDid}?resourceName=${args.statusListName}&resourceType=${
|
|
2331
|
+
BitstringStatusListResourceType
|
|
2332
|
+
}`,
|
|
2333
|
+
},
|
|
2334
|
+
} as VerifiableCredential),
|
|
2335
|
+
encrypted: args.encrypted,
|
|
2336
|
+
symmetricKey: args.encrypted && args.returnSymmetricKey ? data[1]?.symmetricKey : undefined,
|
|
2337
|
+
} satisfies CreateStatusListResult;
|
|
2338
|
+
}
|
|
2339
|
+
private async BroadcastBitstringStatusList(args: ICheqdBroadcastStatusListArgs, context: IContext) {
|
|
2340
|
+
if (typeof args.kms !== 'string') {
|
|
2341
|
+
throw new Error('[did-provider-cheqd]: kms is required');
|
|
2342
|
+
}
|
|
2343
|
+
|
|
2344
|
+
if (typeof args.payload !== 'object') {
|
|
2345
|
+
throw new Error('[did-provider-cheqd]: payload object is required');
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
if (typeof args.network !== 'string') {
|
|
2349
|
+
throw new Error('[did-provider-cheqd]: network is required');
|
|
2350
|
+
}
|
|
2351
|
+
|
|
2352
|
+
if (args?.file) {
|
|
2353
|
+
args.payload.data = await Cheqd.getFile(args.file);
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2356
|
+
if (typeof args?.payload?.data === 'string') {
|
|
2357
|
+
args.payload.data = fromString(args.payload.data, 'base64');
|
|
2358
|
+
}
|
|
2359
|
+
// Validate that data is present
|
|
2360
|
+
if (!args.payload.data) {
|
|
2361
|
+
throw new Error('[did-provider-cheqd]: payload.data is required for Bitstring Status List');
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
// Validate and parse the Bitstring Status List data
|
|
2365
|
+
await this.validateBitstringStatusListPayload(args.payload as BitstringStatusListResourcePayload);
|
|
2366
|
+
|
|
2367
|
+
// Validate against resource type
|
|
2368
|
+
if (args?.payload?.resourceType !== BitstringStatusListResourceType) {
|
|
2369
|
+
throw new Error(`[did-provider-cheqd]: resourceType must be ${BitstringStatusListResourceType}`);
|
|
2370
|
+
}
|
|
2371
|
+
|
|
2372
|
+
this.providerId = Cheqd.generateProviderId(args.network);
|
|
2373
|
+
this.didProvider = await Cheqd.getProviderFromNetwork(args.network, this.supportedDidProviders);
|
|
2374
|
+
|
|
2375
|
+
return await this.didProvider.createResource(
|
|
2376
|
+
{
|
|
2377
|
+
options: {
|
|
2378
|
+
kms: args.kms,
|
|
2379
|
+
payload: args.payload,
|
|
2380
|
+
signInputs: args.signInputs,
|
|
2381
|
+
fee:
|
|
2382
|
+
args?.fee ||
|
|
2383
|
+
(await ResourceModule.generateCreateResourceJsonFees(
|
|
2384
|
+
(await this.didProvider.getWalletAccounts())[0].address
|
|
2385
|
+
)),
|
|
2386
|
+
},
|
|
2387
|
+
},
|
|
2388
|
+
context
|
|
2389
|
+
);
|
|
2390
|
+
}
|
|
2391
|
+
/**
|
|
2392
|
+
* Validate Bitstring Status List payload structure and content
|
|
2393
|
+
*/
|
|
2394
|
+
private async validateBitstringStatusListPayload(payload: BitstringStatusListResourcePayload): Promise<void> {
|
|
2395
|
+
if (!payload.data) {
|
|
2396
|
+
throw new Error('[did-provider-cheqd]: payload.data is required');
|
|
2397
|
+
}
|
|
2398
|
+
let bitstringData: BitstringStatusList;
|
|
2399
|
+
try {
|
|
2400
|
+
// Parse the data as BitstringStatusList
|
|
2401
|
+
const dataString = typeof payload.data === 'string' ? payload.data : toString(payload.data, 'utf-8');
|
|
2402
|
+
bitstringData = JSON.parse(dataString) as BitstringStatusList;
|
|
2403
|
+
} catch (error) {
|
|
2404
|
+
throw new Error(
|
|
2405
|
+
`[did-provider-cheqd]: Invalid BitstringStatusList data format: ${(error as Error).message}`
|
|
2406
|
+
);
|
|
2407
|
+
}
|
|
2408
|
+
const metadata = bitstringData.metadata;
|
|
2409
|
+
const bitstringCredential = bitstringData.bitstringStatusListCredential;
|
|
2410
|
+
// Validate required properties
|
|
2411
|
+
if (!bitstringCredential.credentialSubject.statusPurpose) {
|
|
2412
|
+
throw new Error('[did-provider-cheqd]: statusPurpose is required');
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
if (!bitstringCredential.credentialSubject.encodedList) {
|
|
2416
|
+
throw new Error('[did-provider-cheqd]: encodedList is required');
|
|
2417
|
+
}
|
|
2418
|
+
|
|
2419
|
+
if (!bitstringCredential.issuanceDate) {
|
|
2420
|
+
throw new Error('[did-provider-cheqd]: issuanceDate is required');
|
|
2421
|
+
}
|
|
2422
|
+
// Validate status purpose
|
|
2423
|
+
const statusPurpose = Array.isArray(bitstringCredential.credentialSubject.statusPurpose)
|
|
2424
|
+
? bitstringCredential.credentialSubject.statusPurpose[0]
|
|
2425
|
+
: bitstringCredential.credentialSubject.statusPurpose;
|
|
2426
|
+
if (!Object.values(BitstringStatusPurposeTypes).includes(statusPurpose)) {
|
|
2427
|
+
throw new Error(
|
|
2428
|
+
`[did-provider-cheqd]: Invalid statusPurpose. Must be in: ${Object.values(
|
|
2429
|
+
BitstringStatusPurposeTypes
|
|
2430
|
+
).join(', ')}`
|
|
2431
|
+
);
|
|
2432
|
+
}
|
|
2433
|
+
// Validate encoded list format (should be base64url encoded)
|
|
2434
|
+
if (!isValidEncodedBitstring(bitstringCredential.credentialSubject.encodedList)) {
|
|
2435
|
+
throw new Error(
|
|
2436
|
+
'[did-provider-cheqd]: Invalid encodedList format. Must be base64url encoded GZIP compressed bitstring'
|
|
2437
|
+
);
|
|
2438
|
+
}
|
|
2439
|
+
// Validate dates
|
|
2440
|
+
try {
|
|
2441
|
+
new Date(bitstringCredential.issuanceDate);
|
|
2442
|
+
if (bitstringCredential.expirationDate) {
|
|
2443
|
+
const validUntil = new Date(bitstringCredential.expirationDate);
|
|
2444
|
+
const validFrom = new Date(bitstringCredential.issuanceDate);
|
|
2445
|
+
if (validUntil <= validFrom) {
|
|
2446
|
+
throw new Error('[did-provider-cheqd]: expirationDate must be after issuanceDate');
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
} catch (error) {
|
|
2450
|
+
throw new Error(`[did-provider-cheqd]: Invalid date format: ${(error as Error).message}`);
|
|
2451
|
+
}
|
|
2452
|
+
// Validate status size if present
|
|
2453
|
+
if (metadata.statusSize !== undefined) {
|
|
2454
|
+
if (![1, 2, 4, 8].includes(metadata.statusSize)) {
|
|
2455
|
+
throw new Error('[did-provider-cheqd]: statusSize must be 1, 2, 4, or 8 bits');
|
|
2456
|
+
}
|
|
2457
|
+
|
|
2458
|
+
// Validate status messages for multi-bit status
|
|
2459
|
+
if (metadata.statusSize > 1) {
|
|
2460
|
+
await this.validateStatusMessagesInPayload(metadata.statusMessages, metadata.statusSize);
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
|
|
2464
|
+
// Validate TTL if present
|
|
2465
|
+
if (bitstringCredential.credentialSubject.ttl !== undefined) {
|
|
2466
|
+
if (
|
|
2467
|
+
typeof bitstringCredential.credentialSubject.ttl !== 'number' ||
|
|
2468
|
+
bitstringCredential.credentialSubject.ttl < 0
|
|
2469
|
+
) {
|
|
2470
|
+
throw new Error('[did-provider-cheqd]: ttl must be a non-negative number');
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
|
|
2475
|
+
/**
|
|
2476
|
+
* Validate status messages for multi-bit status
|
|
2477
|
+
*/
|
|
2478
|
+
private async validateStatusMessagesInPayload(
|
|
2479
|
+
statusMessages: BitstringStatusMessage[] | undefined,
|
|
2480
|
+
statusSize: number
|
|
2481
|
+
): Promise<void> {
|
|
2482
|
+
if (statusSize <= 1) {
|
|
2483
|
+
return; // No validation needed for single-bit status
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
const expectedMessageCount = Math.pow(2, statusSize);
|
|
2487
|
+
|
|
2488
|
+
if (!statusMessages || statusMessages.length === 0) {
|
|
2489
|
+
throw new Error(
|
|
2490
|
+
`[did-provider-cheqd]: statusMessages is required for ${statusSize}-bit status (expected ${expectedMessageCount} messages)`
|
|
2491
|
+
);
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2494
|
+
if (statusMessages.length !== expectedMessageCount) {
|
|
2495
|
+
throw new Error(
|
|
2496
|
+
`[did-provider-cheqd]: statusMessages must have exactly ${expectedMessageCount} entries for ${statusSize}-bit status`
|
|
2497
|
+
);
|
|
2498
|
+
}
|
|
2499
|
+
|
|
2500
|
+
// Validate each status message
|
|
2501
|
+
const expectedStatuses = new Set<string>();
|
|
2502
|
+
for (let i = 0; i < expectedMessageCount; i++) {
|
|
2503
|
+
expectedStatuses.add(`0x${i.toString(16).toLowerCase()}`);
|
|
2504
|
+
}
|
|
2505
|
+
|
|
2506
|
+
const actualStatuses = new Set(statusMessages.map((msg) => msg.status));
|
|
2507
|
+
|
|
2508
|
+
for (const expected of expectedStatuses) {
|
|
2509
|
+
if (!actualStatuses.has(expected)) {
|
|
2510
|
+
throw new Error(`[did-provider-cheqd]: Missing status message for value ${expected}`);
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
|
|
2514
|
+
// Validate message format
|
|
2515
|
+
for (const statusMsg of statusMessages) {
|
|
2516
|
+
if (!statusMsg.status || !statusMsg.message) {
|
|
2517
|
+
throw new Error(
|
|
2518
|
+
'[did-provider-cheqd]: Each status message must have both status and message properties'
|
|
2519
|
+
);
|
|
2520
|
+
}
|
|
2521
|
+
|
|
2522
|
+
if (typeof statusMsg.status !== 'string' || typeof statusMsg.message !== 'string') {
|
|
2523
|
+
throw new Error('[did-provider-cheqd]: status and message must be strings');
|
|
2524
|
+
}
|
|
2525
|
+
|
|
2526
|
+
if (!statusMsg.status.match(/^0x[0-9a-f]+$/i)) {
|
|
2527
|
+
throw new Error(
|
|
2528
|
+
`[did-provider-cheqd]: Invalid status format ${statusMsg.status}. Must be hex prefixed with 0x`
|
|
2529
|
+
);
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
private async GenerateDidDoc(args: ICheqdGenerateDidDocArgs, context: IContext): Promise<TExportedDIDDocWithKeys> {
|
|
2534
|
+
if (typeof args.verificationMethod !== 'string') {
|
|
2535
|
+
throw new Error('[did-provider-cheqd]: verificationMethod is required');
|
|
2536
|
+
}
|
|
2537
|
+
|
|
2538
|
+
if (typeof args.methodSpecificIdAlgo !== 'string') {
|
|
2539
|
+
throw new Error('[did-provider-cheqd]: methodSpecificIdAlgo is required');
|
|
2540
|
+
}
|
|
2541
|
+
|
|
2542
|
+
if (typeof args.network !== 'string') {
|
|
2543
|
+
throw new Error('[did-provider-cheqd]: network is required');
|
|
2544
|
+
}
|
|
2545
|
+
|
|
2546
|
+
const keyPair = createKeyPairBase64();
|
|
2547
|
+
const keyPairHex: IKeyPair = {
|
|
2548
|
+
publicKey: toString(fromString(keyPair.publicKey, 'base64'), 'hex'),
|
|
2549
|
+
privateKey: toString(fromString(keyPair.privateKey, 'base64'), 'hex'),
|
|
2550
|
+
};
|
|
2551
|
+
const verificationKeys = createVerificationKeys(
|
|
2552
|
+
keyPair.publicKey,
|
|
2553
|
+
args.methodSpecificIdAlgo,
|
|
2554
|
+
'key-1',
|
|
2555
|
+
args.network
|
|
2556
|
+
);
|
|
2557
|
+
const verificationMethods = createDidVerificationMethod([args.verificationMethod], [verificationKeys]);
|
|
2558
|
+
|
|
2559
|
+
return {
|
|
2560
|
+
didDoc: createDidPayload(verificationMethods, [verificationKeys]),
|
|
2561
|
+
versionId: v4(),
|
|
2562
|
+
keys: [
|
|
2563
|
+
{
|
|
2564
|
+
publicKeyHex: keyPairHex.publicKey,
|
|
2565
|
+
privateKeyHex: keyPairHex.privateKey,
|
|
2566
|
+
kid: keyPairHex.publicKey,
|
|
2567
|
+
type: 'Ed25519',
|
|
2568
|
+
},
|
|
2569
|
+
],
|
|
2570
|
+
};
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
private async GenerateDidDocWithLinkedResource(
|
|
2574
|
+
args: any,
|
|
2575
|
+
context: IContext
|
|
2576
|
+
): Promise<TExportedDIDDocWithLinkedResourceWithKeys> {
|
|
2577
|
+
if (typeof args.verificationMethod !== 'string') {
|
|
2578
|
+
throw new Error('[did-provider-cheqd]: verificationMethod is required');
|
|
2579
|
+
}
|
|
2580
|
+
|
|
2581
|
+
if (typeof args.methodSpecificIdAlgo !== 'string') {
|
|
2582
|
+
throw new Error('[did-provider-cheqd]: methodSpecificIdAlgo is required');
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
if (typeof args.network !== 'string') {
|
|
2586
|
+
throw new Error('[did-provider-cheqd]: network is required');
|
|
2587
|
+
}
|
|
2588
|
+
|
|
2589
|
+
const keyPair = createKeyPairBase64();
|
|
2590
|
+
const keyPairHex: IKeyPair = {
|
|
2591
|
+
publicKey: toString(fromString(keyPair.publicKey, 'base64'), 'hex'),
|
|
2592
|
+
privateKey: toString(fromString(keyPair.privateKey, 'base64'), 'hex'),
|
|
2593
|
+
};
|
|
2594
|
+
const verificationKeys = createVerificationKeys(
|
|
2595
|
+
keyPair.publicKey,
|
|
1845
2596
|
args.methodSpecificIdAlgo,
|
|
1846
2597
|
'key-1',
|
|
1847
2598
|
args.network
|
|
@@ -1905,6 +2656,187 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1905
2656
|
return encoded;
|
|
1906
2657
|
}
|
|
1907
2658
|
}
|
|
2659
|
+
private async GenerateBitstringStatusList(args: ICheqdGenerateStatusListArgs, context: IContext): Promise<string> {
|
|
2660
|
+
const statusSize = args?.statusSize || 1; // default to 1 bit per entry // TODO change to 2 bits per entry after StatusList2021 is removed
|
|
2661
|
+
const length = args?.length || Cheqd.DefaultBitstringLength; // default to 131072
|
|
2662
|
+
// Total number of bits = entries * bits per entry
|
|
2663
|
+
const totalBits = length * statusSize;
|
|
2664
|
+
// Ensure bitstring is byte-aligned (i.e., multiple of 8 bits)
|
|
2665
|
+
const alignedLength = Math.ceil(totalBits / 8) * 8;
|
|
2666
|
+
|
|
2667
|
+
const bitstring: DBBitstring = args?.buffer
|
|
2668
|
+
? new DBBitstring({ buffer: args.buffer })
|
|
2669
|
+
: new DBBitstring({ length: alignedLength });
|
|
2670
|
+
|
|
2671
|
+
// get compressed bits
|
|
2672
|
+
const compressed = await bitstring.compressBits();
|
|
2673
|
+
switch (args?.bitstringEncoding) {
|
|
2674
|
+
case 'hex':
|
|
2675
|
+
return toString(compressed, 'hex');
|
|
2676
|
+
case 'base64url':
|
|
2677
|
+
default:
|
|
2678
|
+
return toString(compressed, 'base64url');
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
|
|
2682
|
+
private async VerifyStatusListCredential(
|
|
2683
|
+
args: ICheqdVerifyStatusListCredentialArgs,
|
|
2684
|
+
context: IContext
|
|
2685
|
+
): Promise<VerificationResult> {
|
|
2686
|
+
// if jwt credential, decode it
|
|
2687
|
+
const credentialObj =
|
|
2688
|
+
typeof args.credential === 'string' ? await Cheqd.decodeCredentialJWT(args.credential) : args.credential;
|
|
2689
|
+
// Validate required fields
|
|
2690
|
+
if (!credentialObj || typeof credentialObj !== 'object') {
|
|
2691
|
+
return {
|
|
2692
|
+
verified: false,
|
|
2693
|
+
error: { message: 'Invalid credential format' },
|
|
2694
|
+
};
|
|
2695
|
+
}
|
|
2696
|
+
const { credentialSubject, ...rest } = credentialObj;
|
|
2697
|
+
// Validate credentialSubject and encodedList
|
|
2698
|
+
if (!credentialSubject?.encodedList) {
|
|
2699
|
+
return {
|
|
2700
|
+
verified: false,
|
|
2701
|
+
error: { message: 'Missing encodedList in credentialSubject' },
|
|
2702
|
+
};
|
|
2703
|
+
}
|
|
2704
|
+
// Validate that this is indeed a status list credential
|
|
2705
|
+
if (!credentialObj.type || !credentialObj.type.includes('BitstringStatusListCredential')) {
|
|
2706
|
+
return {
|
|
2707
|
+
verified: false,
|
|
2708
|
+
error: { message: 'Credential is not a BitstringStatusListCredential' },
|
|
2709
|
+
};
|
|
2710
|
+
}
|
|
2711
|
+
// Extract encodedList and create credential without it for verification
|
|
2712
|
+
const { encodedList, ...restCredentialSubject } = credentialSubject || {};
|
|
2713
|
+
// Create formatted credential for verification without encodedList
|
|
2714
|
+
const formattedCredential: VerifiableCredential = {
|
|
2715
|
+
credentialSubject: restCredentialSubject,
|
|
2716
|
+
...rest,
|
|
2717
|
+
};
|
|
2718
|
+
// verify default policies
|
|
2719
|
+
const verificationResult = await context.agent.verifyCredential({
|
|
2720
|
+
...args?.verificationArgs,
|
|
2721
|
+
credential: formattedCredential,
|
|
2722
|
+
policies: {
|
|
2723
|
+
...args?.verificationArgs?.policies,
|
|
2724
|
+
// Disable credentialStatus check for status list credentials to avoid circular dependency
|
|
2725
|
+
credentialStatus: false,
|
|
2726
|
+
},
|
|
2727
|
+
} satisfies IVerifyCredentialArgs);
|
|
2728
|
+
// Additional validation for BitstringStatusListCredential
|
|
2729
|
+
if (verificationResult.verified) {
|
|
2730
|
+
// Basic validation that encodedList is properly formatted
|
|
2731
|
+
if (typeof encodedList !== 'string' || !encodedList) {
|
|
2732
|
+
return {
|
|
2733
|
+
verified: false,
|
|
2734
|
+
error: { message: 'Invalid encodedList format' },
|
|
2735
|
+
};
|
|
2736
|
+
}
|
|
2737
|
+
// Validate encodedList format (should be base64url encoded)
|
|
2738
|
+
if (!isValidEncodedBitstring(encodedList)) {
|
|
2739
|
+
return {
|
|
2740
|
+
verified: false,
|
|
2741
|
+
error: { message: 'EncodedList validation failed' },
|
|
2742
|
+
};
|
|
2743
|
+
}
|
|
2744
|
+
|
|
2745
|
+
// Validate statusPurpose is a valid value
|
|
2746
|
+
const statusPurpose = Array.isArray(credentialObj.credentialSubject.statusPurpose)
|
|
2747
|
+
? credentialObj.credentialSubject.statusPurpose[0]
|
|
2748
|
+
: credentialObj.credentialSubject.statusPurpose;
|
|
2749
|
+
if (!Object.values(BitstringStatusPurposeTypes).includes(statusPurpose)) {
|
|
2750
|
+
return {
|
|
2751
|
+
verified: false,
|
|
2752
|
+
error: { message: `Invalid statusPurpose: ${credentialObj.credentialSubject.statusPurpose}` },
|
|
2753
|
+
};
|
|
2754
|
+
}
|
|
2755
|
+
|
|
2756
|
+
// If ttl is provided, validate it's a positive number
|
|
2757
|
+
if (
|
|
2758
|
+
restCredentialSubject.ttl !== undefined &&
|
|
2759
|
+
(typeof restCredentialSubject.ttl !== 'number' || restCredentialSubject.ttl <= 0)
|
|
2760
|
+
) {
|
|
2761
|
+
return {
|
|
2762
|
+
verified: false,
|
|
2763
|
+
error: { message: 'Invalid ttl value' },
|
|
2764
|
+
};
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
|
|
2768
|
+
return { verified: verificationResult.verified, error: verificationResult.error };
|
|
2769
|
+
}
|
|
2770
|
+
|
|
2771
|
+
private async IssueCredentialWithBitstringStatusList(
|
|
2772
|
+
args: ICheqdIssueCredentialWithStatusListArgs,
|
|
2773
|
+
context: IContext
|
|
2774
|
+
): Promise<BitstringVerifiableCredential> {
|
|
2775
|
+
// validate resource type
|
|
2776
|
+
const allowedTypes: Array<'refresh' | 'message'> = ['refresh', 'message'];
|
|
2777
|
+
if (!allowedTypes.includes(args.statusOptions.statusPurpose as 'refresh' | 'message')) {
|
|
2778
|
+
throw new Error(
|
|
2779
|
+
`[did-provider-cheqd]: statusPurpose while issuance must be one of ${allowedTypes.join(', ')}`
|
|
2780
|
+
);
|
|
2781
|
+
}
|
|
2782
|
+
// construct issuer
|
|
2783
|
+
const issuer = (args.issuanceOptions.credential.issuer as { id: string }).id
|
|
2784
|
+
? (args.issuanceOptions.credential.issuer as { id: string }).id
|
|
2785
|
+
: (args.issuanceOptions.credential.issuer as string);
|
|
2786
|
+
// generate status list credential
|
|
2787
|
+
const statusListCredential = `${DefaultResolverUrl}${issuer}?resourceName=${args.statusOptions.statusListName}&resourceType=${BitstringStatusListResourceType}`;
|
|
2788
|
+
// get latest status list
|
|
2789
|
+
const statuslist = await Cheqd.fetchBitstringStatusList({
|
|
2790
|
+
credentialStatus: {
|
|
2791
|
+
id: statusListCredential,
|
|
2792
|
+
},
|
|
2793
|
+
} as VerifiableCredential);
|
|
2794
|
+
// Validate statusPurpose with statusList.statusPurpose
|
|
2795
|
+
const sl_statusPurpose = statuslist.bitstringStatusListCredential.credentialSubject.statusPurpose;
|
|
2796
|
+
if (!Object.values(sl_statusPurpose).includes(args.statusOptions.statusPurpose)) {
|
|
2797
|
+
throw new Error(
|
|
2798
|
+
`[did-provider-cheqd]: statusPurpose must be one of ${Object.values(sl_statusPurpose).join(', ')}`
|
|
2799
|
+
);
|
|
2800
|
+
}
|
|
2801
|
+
// If statusPurpose is 'message', statusMessages and statusSize MUST be present in Credential
|
|
2802
|
+
if (args.statusOptions.statusPurpose === BitstringStatusPurposeTypes.message) {
|
|
2803
|
+
if (!statuslist.metadata.statusSize || !statuslist.metadata.statusMessages) {
|
|
2804
|
+
throw new Error(
|
|
2805
|
+
'[did-provider-cheqd]: statusMessages and statusSize must be present for statusPurpose="message"'
|
|
2806
|
+
);
|
|
2807
|
+
}
|
|
2808
|
+
}
|
|
2809
|
+
|
|
2810
|
+
// generate index
|
|
2811
|
+
const statusListIndex = await generateRandomStatusListIndex(args.statusOptions, {
|
|
2812
|
+
statusSize: statuslist.metadata.statusSize,
|
|
2813
|
+
length: statuslist.metadata.length,
|
|
2814
|
+
});
|
|
2815
|
+
|
|
2816
|
+
// construct credential status
|
|
2817
|
+
const credentialStatus: BitstringStatusListEntry = {
|
|
2818
|
+
id: `${statusListCredential}#${statusListIndex}`,
|
|
2819
|
+
type: 'BitstringStatusListEntry',
|
|
2820
|
+
statusPurpose: args.statusOptions.statusPurpose || BitstringStatusPurposeTypes.message,
|
|
2821
|
+
statusListIndex: `${statusListIndex}`,
|
|
2822
|
+
statusListCredential,
|
|
2823
|
+
statusSize: statuslist.metadata.statusSize || 1,
|
|
2824
|
+
statusMessage: statuslist.metadata.statusMessages || [],
|
|
2825
|
+
};
|
|
2826
|
+
|
|
2827
|
+
// add credential status to credential
|
|
2828
|
+
args.issuanceOptions.credential.credentialStatus = credentialStatus;
|
|
2829
|
+
|
|
2830
|
+
// add relevant context
|
|
2831
|
+
args.issuanceOptions.credential['@context'] = this.addBitstringStatusListContexts(
|
|
2832
|
+
args.issuanceOptions.credential
|
|
2833
|
+
);
|
|
2834
|
+
// TODO: update Veramo so that default "https://www.w3.org/2018/credentials/v1" is not added in context
|
|
2835
|
+
// create a credential
|
|
2836
|
+
const credential = await context.agent.createVerifiableCredential(args.issuanceOptions);
|
|
2837
|
+
|
|
2838
|
+
return credential as BitstringVerifiableCredential;
|
|
2839
|
+
}
|
|
1908
2840
|
|
|
1909
2841
|
private async IssueRevocableCredentialWithStatusList2021(
|
|
1910
2842
|
args: ICheqdIssueRevocableCredentialWithStatusList2021Args,
|
|
@@ -1939,27 +2871,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
1939
2871
|
args.issuanceOptions.credential.credentialStatus = credentialStatus;
|
|
1940
2872
|
|
|
1941
2873
|
// add relevant context
|
|
1942
|
-
args.issuanceOptions.credential['@context'] = (
|
|
1943
|
-
// if no context is provided, add default context
|
|
1944
|
-
if (!args.issuanceOptions.credential['@context']) {
|
|
1945
|
-
return [Cheqd.defaultContextV1, Cheqd.statusList2021Context];
|
|
1946
|
-
}
|
|
1947
|
-
|
|
1948
|
-
// if context is provided as an array, add default context if it is not already present
|
|
1949
|
-
if (Array.isArray(args.issuanceOptions.credential['@context'])) {
|
|
1950
|
-
if (args.issuanceOptions.credential['@context'].length === 0) {
|
|
1951
|
-
return [Cheqd.defaultContextV1, Cheqd.statusList2021Context];
|
|
1952
|
-
}
|
|
1953
|
-
|
|
1954
|
-
if (!args.issuanceOptions.credential['@context'].includes(Cheqd.statusList2021Context)) {
|
|
1955
|
-
return [...args.issuanceOptions.credential['@context'], Cheqd.statusList2021Context];
|
|
1956
|
-
}
|
|
1957
|
-
}
|
|
1958
|
-
|
|
1959
|
-
// if context is provided as a string, add default context if it is not already present
|
|
1960
|
-
if (typeof args.issuanceOptions.credential['@context'] === 'string')
|
|
1961
|
-
return [Cheqd.defaultContextV1, Cheqd.statusList2021Context];
|
|
1962
|
-
})();
|
|
2874
|
+
args.issuanceOptions.credential['@context'] = this.addStatusList2021Contexts(args.issuanceOptions.credential);
|
|
1963
2875
|
|
|
1964
2876
|
// create a credential
|
|
1965
2877
|
const credential = await context.agent.createVerifiableCredential(args.issuanceOptions);
|
|
@@ -2000,36 +2912,39 @@ export class Cheqd implements IAgentPlugin {
|
|
|
2000
2912
|
args.issuanceOptions.credential.credentialStatus = credentialStatus;
|
|
2001
2913
|
|
|
2002
2914
|
// add relevant context
|
|
2003
|
-
args.issuanceOptions.credential['@context'] = (
|
|
2004
|
-
// if no context is provided, add default context
|
|
2005
|
-
if (!args.issuanceOptions.credential['@context']) {
|
|
2006
|
-
return [Cheqd.defaultContextV1, Cheqd.statusList2021Context];
|
|
2007
|
-
}
|
|
2008
|
-
|
|
2009
|
-
// if context is provided as an array, add default context if it is not already present
|
|
2010
|
-
if (Array.isArray(args.issuanceOptions.credential['@context'])) {
|
|
2011
|
-
if (args.issuanceOptions.credential['@context'].length === 0) {
|
|
2012
|
-
return [Cheqd.defaultContextV1, Cheqd.statusList2021Context];
|
|
2013
|
-
}
|
|
2014
|
-
|
|
2015
|
-
if (!args.issuanceOptions.credential['@context'].includes(Cheqd.statusList2021Context)) {
|
|
2016
|
-
return [...args.issuanceOptions.credential['@context'], Cheqd.statusList2021Context];
|
|
2017
|
-
}
|
|
2018
|
-
}
|
|
2019
|
-
|
|
2020
|
-
// if context is provided as a string, add default context if it is not already present
|
|
2021
|
-
if (typeof args.issuanceOptions.credential['@context'] === 'string')
|
|
2022
|
-
return [Cheqd.defaultContextV1, Cheqd.statusList2021Context];
|
|
2023
|
-
})();
|
|
2915
|
+
args.issuanceOptions.credential['@context'] = this.addStatusList2021Contexts(args.issuanceOptions.credential);
|
|
2024
2916
|
|
|
2025
2917
|
// create a credential
|
|
2026
2918
|
const credential = await context.agent.createVerifiableCredential(args.issuanceOptions);
|
|
2027
2919
|
|
|
2028
2920
|
return credential;
|
|
2029
2921
|
}
|
|
2922
|
+
private addStatusList2021Contexts(credential: any): string[] {
|
|
2923
|
+
const contexts = credential['@context'] || [];
|
|
2924
|
+
// if context is provided as an array, add default context if it is not already present
|
|
2925
|
+
if (Array.isArray(contexts)) {
|
|
2926
|
+
const requiredContexts = [Cheqd.defaultContextV1, Cheqd.statusList2021Context];
|
|
2927
|
+
const missingContexts = requiredContexts.filter((ctx) => !contexts.includes(ctx));
|
|
2928
|
+
return [...contexts, ...missingContexts];
|
|
2929
|
+
}
|
|
2930
|
+
// if no context return default context
|
|
2931
|
+
return [Cheqd.defaultContextV1, Cheqd.statusList2021Context];
|
|
2932
|
+
}
|
|
2933
|
+
private addBitstringStatusListContexts(credential: any): string[] {
|
|
2934
|
+
const contexts = credential['@context'] || [];
|
|
2935
|
+
// if context is provided as an array, add default context if it is not already present
|
|
2936
|
+
if (Array.isArray(contexts)) {
|
|
2937
|
+
// TODO: Credential V1 context is used now, replace when V2 is implemented
|
|
2938
|
+
const requiredContexts = [Cheqd.defaultContextV1, Cheqd.DefaultBitstringContexts.statusList];
|
|
2939
|
+
const missingContexts = requiredContexts.filter((ctx) => !contexts.includes(ctx));
|
|
2940
|
+
return [...contexts, ...missingContexts];
|
|
2941
|
+
}
|
|
2942
|
+
// if no context return default context
|
|
2943
|
+
return [Cheqd.DefaultBitstringContexts.v2, Cheqd.DefaultBitstringContexts.statusList];
|
|
2944
|
+
}
|
|
2030
2945
|
|
|
2031
2946
|
private async VerifyCredentialWithStatusList2021(
|
|
2032
|
-
args:
|
|
2947
|
+
args: ICheqdVerifyCredentialWithStatusListArgs,
|
|
2033
2948
|
context: IContext
|
|
2034
2949
|
): Promise<VerificationResult> {
|
|
2035
2950
|
// verify default policies
|
|
@@ -2041,7 +2956,6 @@ export class Cheqd implements IAgentPlugin {
|
|
|
2041
2956
|
credentialStatus: false,
|
|
2042
2957
|
},
|
|
2043
2958
|
} satisfies IVerifyCredentialArgs);
|
|
2044
|
-
|
|
2045
2959
|
// early return if verification failed
|
|
2046
2960
|
if (!verificationResult.verified) {
|
|
2047
2961
|
return { verified: false, error: verificationResult.error };
|
|
@@ -2058,33 +2972,345 @@ export class Cheqd implements IAgentPlugin {
|
|
|
2058
2972
|
// define provider, if applicable
|
|
2059
2973
|
this.didProvider = await Cheqd.getProviderFromDidUrl(issuer, this.supportedDidProviders);
|
|
2060
2974
|
|
|
2061
|
-
// define provider id, if applicable
|
|
2062
|
-
this.providerId = Cheqd.generateProviderId(issuer);
|
|
2975
|
+
// define provider id, if applicable
|
|
2976
|
+
this.providerId = Cheqd.generateProviderId(issuer);
|
|
2977
|
+
|
|
2978
|
+
// define dkg options, if provided
|
|
2979
|
+
args.dkgOptions ||= this.didProvider.dkgOptions;
|
|
2980
|
+
|
|
2981
|
+
// verify credential status
|
|
2982
|
+
switch (credential.credentialStatus?.statusPurpose) {
|
|
2983
|
+
case DefaultStatusList2021StatusPurposeTypes.revocation:
|
|
2984
|
+
return {
|
|
2985
|
+
...verificationResult,
|
|
2986
|
+
revoked: await Cheqd.checkRevoked(credential, { ...args.options, topArgs: args }),
|
|
2987
|
+
};
|
|
2988
|
+
case DefaultStatusList2021StatusPurposeTypes.suspension:
|
|
2989
|
+
return {
|
|
2990
|
+
...verificationResult,
|
|
2991
|
+
suspended: await Cheqd.checkSuspended(credential, { ...args.options, topArgs: args }),
|
|
2992
|
+
};
|
|
2993
|
+
default:
|
|
2994
|
+
throw new Error(
|
|
2995
|
+
`[did-provider-cheqd]: verify credential: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`
|
|
2996
|
+
);
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
private async VerifyCredentialWithBitstringStatusList(
|
|
3000
|
+
args: ICheqdVerifyCredentialWithBitstringArgs,
|
|
3001
|
+
context: IContext
|
|
3002
|
+
): Promise<BitstringVerificationResult> {
|
|
3003
|
+
// verify default policies
|
|
3004
|
+
const verificationResult = await context.agent.verifyCredential({
|
|
3005
|
+
...args?.verificationArgs,
|
|
3006
|
+
credential: args.credential,
|
|
3007
|
+
policies: {
|
|
3008
|
+
...args?.verificationArgs?.policies,
|
|
3009
|
+
credentialStatus: false,
|
|
3010
|
+
},
|
|
3011
|
+
} satisfies IVerifyCredentialArgs);
|
|
3012
|
+
// if jwt credential, decode it
|
|
3013
|
+
const credential =
|
|
3014
|
+
typeof args.credential === 'string' ? await Cheqd.decodeCredentialJWT(args.credential) : args.credential;
|
|
3015
|
+
// early return if verification failed
|
|
3016
|
+
if (!verificationResult.verified) {
|
|
3017
|
+
return {
|
|
3018
|
+
verified: false,
|
|
3019
|
+
status: 1,
|
|
3020
|
+
purpose: credential.credentialStatus?.statusPurpose,
|
|
3021
|
+
valid: false,
|
|
3022
|
+
error: verificationResult.error,
|
|
3023
|
+
};
|
|
3024
|
+
}
|
|
3025
|
+
|
|
3026
|
+
// define issuer
|
|
3027
|
+
const issuer =
|
|
3028
|
+
typeof credential.issuer === 'string' ? credential.issuer : (credential.issuer as { id: string }).id;
|
|
3029
|
+
|
|
3030
|
+
// define provider, if applicable
|
|
3031
|
+
this.didProvider = await Cheqd.getProviderFromDidUrl(issuer, this.supportedDidProviders);
|
|
3032
|
+
|
|
3033
|
+
// define provider id, if applicable
|
|
3034
|
+
this.providerId = Cheqd.generateProviderId(issuer);
|
|
3035
|
+
|
|
3036
|
+
// define dkg options, if provided
|
|
3037
|
+
args.dkgOptions ||= this.didProvider.dkgOptions;
|
|
3038
|
+
|
|
3039
|
+
// Fetch and verify the Bitstring status list VC
|
|
3040
|
+
let publishedList: BitstringStatusList;
|
|
3041
|
+
try {
|
|
3042
|
+
publishedList = await Cheqd.fetchBitstringStatusList({
|
|
3043
|
+
credentialStatus: {
|
|
3044
|
+
id: credential.credentialStatus?.statusListCredential,
|
|
3045
|
+
},
|
|
3046
|
+
} as VerifiableCredential);
|
|
3047
|
+
} catch {
|
|
3048
|
+
throw new Error('[did-provider-cheqd]: STATUS_RETRIEVAL_ERROR');
|
|
3049
|
+
}
|
|
3050
|
+
// Validate proof on the Bitstring status list VC
|
|
3051
|
+
const checkCredential = await this.VerifyStatusListCredential(
|
|
3052
|
+
{ credential: publishedList.bitstringStatusListCredential },
|
|
3053
|
+
context
|
|
3054
|
+
);
|
|
3055
|
+
if (!checkCredential.verified) {
|
|
3056
|
+
throw new Error('[did-provider-cheqd]: STATUS_VERIFICATION_ERROR');
|
|
3057
|
+
}
|
|
3058
|
+
const validationResult = await Cheqd.validateBitstringStatus(
|
|
3059
|
+
credential as BitstringVerifiableCredential,
|
|
3060
|
+
publishedList,
|
|
3061
|
+
{
|
|
3062
|
+
...args.options,
|
|
3063
|
+
topArgs: args,
|
|
3064
|
+
instantiateDkgClient: () => this.didProvider.instantiateDkgThresholdProtocolClient(),
|
|
3065
|
+
}
|
|
3066
|
+
);
|
|
3067
|
+
|
|
3068
|
+
// verify credential status
|
|
3069
|
+
switch (credential.credentialStatus?.statusPurpose) {
|
|
3070
|
+
case BitstringStatusPurposeTypes.revocation:
|
|
3071
|
+
return {
|
|
3072
|
+
...verificationResult,
|
|
3073
|
+
revoked: !validationResult.valid,
|
|
3074
|
+
...validationResult,
|
|
3075
|
+
};
|
|
3076
|
+
case BitstringStatusPurposeTypes.suspension:
|
|
3077
|
+
return {
|
|
3078
|
+
...verificationResult,
|
|
3079
|
+
suspended: !validationResult.valid,
|
|
3080
|
+
...validationResult,
|
|
3081
|
+
};
|
|
3082
|
+
case BitstringStatusPurposeTypes.message:
|
|
3083
|
+
case BitstringStatusPurposeTypes.refresh:
|
|
3084
|
+
return { ...verificationResult, ...validationResult };
|
|
3085
|
+
default:
|
|
3086
|
+
throw new Error(
|
|
3087
|
+
`[did-provider-cheqd]: verify credential: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`
|
|
3088
|
+
);
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3091
|
+
|
|
3092
|
+
static async validateBitstringStatus(
|
|
3093
|
+
vcToValidate: BitstringVerifiableCredential,
|
|
3094
|
+
publishedList: BitstringStatusList,
|
|
3095
|
+
options: ICheqdStatusListOptions = { fetchList: true }
|
|
3096
|
+
): Promise<BitstringValidationResult> {
|
|
3097
|
+
if (!vcToValidate?.credentialStatus) {
|
|
3098
|
+
throw new Error('[did-provider-cheqd]: CREDENTIAL_STATUS_MISSING');
|
|
3099
|
+
}
|
|
3100
|
+
|
|
3101
|
+
// validate dkgOptions
|
|
3102
|
+
if (!options?.topArgs?.dkgOptions) {
|
|
3103
|
+
throw new Error('[did-provider-cheqd]: dkgOptions is required');
|
|
3104
|
+
}
|
|
3105
|
+
|
|
3106
|
+
const statusEntry = vcToValidate.credentialStatus;
|
|
3107
|
+
const {
|
|
3108
|
+
statusPurpose,
|
|
3109
|
+
statusListIndex,
|
|
3110
|
+
statusSize = 1, // default to 1 if not given
|
|
3111
|
+
} = statusEntry;
|
|
3112
|
+
|
|
3113
|
+
// Validate statusPurpose match in Bitstring statuslist VC
|
|
3114
|
+
const listSubject = publishedList?.bitstringStatusListCredential.credentialSubject;
|
|
3115
|
+
const purposesDeclared = Array.isArray(listSubject?.statusPurpose)
|
|
3116
|
+
? listSubject.statusPurpose
|
|
3117
|
+
: [listSubject?.statusPurpose];
|
|
3118
|
+
if (!purposesDeclared.includes(statusPurpose)) {
|
|
3119
|
+
throw new Error(
|
|
3120
|
+
"[did-provider-cheqd]: STATUS_VERIFICATION_ERROR 'statusPurpose' does not match Bitstring Status List 'statusPurpose'"
|
|
3121
|
+
);
|
|
3122
|
+
}
|
|
3123
|
+
|
|
3124
|
+
// Extract and decompress the bitstring
|
|
3125
|
+
const encoded = listSubject?.encodedList;
|
|
3126
|
+
if (!encoded) {
|
|
3127
|
+
throw new Error('[did-provider-cheqd]: STATUS_LIST_MISSING_ENCODED');
|
|
3128
|
+
}
|
|
3129
|
+
// validate encoded list
|
|
3130
|
+
if (!isValidEncodedBitstring(encoded))
|
|
3131
|
+
throw new Error(
|
|
3132
|
+
'[did-provider-cheqd]: Invalid encodedList format. Must be base64url encoded GZIP compressed bitstring'
|
|
3133
|
+
);
|
|
3134
|
+
|
|
3135
|
+
// fetch bitstring status list inscribed in credential
|
|
3136
|
+
const bitstringStatusList: string = await Cheqd.fetchAndDecryptBitstring(publishedList, options);
|
|
3137
|
+
|
|
3138
|
+
// Expand bitstring and validate size
|
|
3139
|
+
const decompressedBuffer = await DBBitstring.decodeBits({ encoded: bitstringStatusList });
|
|
3140
|
+
const decompressedBitstring = new DBBitstring({ buffer: decompressedBuffer });
|
|
3141
|
+
const totalBits = decompressedBitstring.length;
|
|
3142
|
+
const numEntries = Math.floor(totalBits / statusSize);
|
|
3143
|
+
|
|
3144
|
+
if (numEntries < Cheqd.DefaultBitstringLength) {
|
|
3145
|
+
throw new Error('[did-provider-cheqd]: STATUS_LIST_LENGTH_ERROR');
|
|
3146
|
+
}
|
|
3147
|
+
|
|
3148
|
+
// Compute index
|
|
3149
|
+
const index = parseInt(statusListIndex, 10);
|
|
3150
|
+
const bitPosition = index * statusSize;
|
|
3151
|
+
|
|
3152
|
+
if (bitPosition + statusSize > totalBits) {
|
|
3153
|
+
throw new Error('[did-provider-cheqd]: RANGE_ERROR');
|
|
3154
|
+
}
|
|
3155
|
+
|
|
3156
|
+
const value = Cheqd.getBitValue(decompressedBitstring, bitPosition, statusSize);
|
|
3157
|
+
|
|
3158
|
+
const result: BitstringValidationResult = {
|
|
3159
|
+
status: value,
|
|
3160
|
+
purpose: statusPurpose,
|
|
3161
|
+
valid: value === 0,
|
|
3162
|
+
};
|
|
3163
|
+
|
|
3164
|
+
// Lookup statusMessage. if statusSize > 1
|
|
3165
|
+
const statusMessages = statusEntry.statusMessage;
|
|
3166
|
+
if (statusPurpose === BitstringStatusPurposeTypes.message && Array.isArray(statusMessages)) {
|
|
3167
|
+
const messageEntry = statusMessages.find((msg: any) => msg.status === `0x${value.toString(16)}`);
|
|
3168
|
+
if (messageEntry) {
|
|
3169
|
+
result.message = messageEntry.message;
|
|
3170
|
+
}
|
|
3171
|
+
}
|
|
3172
|
+
return result;
|
|
3173
|
+
}
|
|
3174
|
+
private async VerifyPresentationWithBitstringStatusList(
|
|
3175
|
+
args: ICheqdVerifyPresentationWithStatusListArgs,
|
|
3176
|
+
context: IContext
|
|
3177
|
+
): Promise<BitstringVerificationResult> {
|
|
3178
|
+
// Verify default presentation policies first
|
|
3179
|
+
const verificationResult = await context.agent.verifyPresentation({
|
|
3180
|
+
...args?.verificationArgs,
|
|
3181
|
+
presentation: args.presentation,
|
|
3182
|
+
policies: {
|
|
3183
|
+
...args?.verificationArgs?.policies,
|
|
3184
|
+
audience: false,
|
|
3185
|
+
credentialStatus: false, // We'll handle status verification separately
|
|
3186
|
+
},
|
|
3187
|
+
} satisfies IVerifyPresentationArgs);
|
|
3188
|
+
// Early return if basic presentation verification failed
|
|
3189
|
+
if (!verificationResult.verified) {
|
|
3190
|
+
return {
|
|
3191
|
+
verified: false,
|
|
3192
|
+
status: 1,
|
|
3193
|
+
purpose: 'unknown',
|
|
3194
|
+
valid: false,
|
|
3195
|
+
error: verificationResult.error,
|
|
3196
|
+
};
|
|
3197
|
+
}
|
|
3198
|
+
// Early return if no verifiable credentials are provided
|
|
3199
|
+
if (!args.presentation.verifiableCredential || !Array.isArray(args.presentation.verifiableCredential)) {
|
|
3200
|
+
throw new Error(
|
|
3201
|
+
'[did-provider-cheqd]: verify presentation: presentation.verifiableCredential is required and must be an array'
|
|
3202
|
+
);
|
|
3203
|
+
}
|
|
3204
|
+
if (args.presentation.verifiableCredential.length === 0) {
|
|
3205
|
+
throw new Error(
|
|
3206
|
+
'[did-provider-cheqd]: verify presentation: presentation must contain at least one verifiable credential'
|
|
3207
|
+
);
|
|
3208
|
+
}
|
|
3209
|
+
|
|
3210
|
+
// Verify each credential's status
|
|
3211
|
+
const credentialResults: BitstringVerificationResult[] = [];
|
|
3212
|
+
let overallValid = true;
|
|
3213
|
+
let hasRevoked = false;
|
|
3214
|
+
let hasSuspended = false;
|
|
2063
3215
|
|
|
2064
|
-
|
|
2065
|
-
|
|
3216
|
+
for (let credential of args.presentation.verifiableCredential) {
|
|
3217
|
+
// If JWT credential, decode it
|
|
3218
|
+
if (typeof credential === 'string') {
|
|
3219
|
+
credential = await Cheqd.decodeCredentialJWT(credential);
|
|
3220
|
+
}
|
|
2066
3221
|
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
3222
|
+
// Skip credentials without status (they're considered valid)
|
|
3223
|
+
if (!credential.credentialStatus || credential.credentialStatus.type !== 'BitstringStatusListEntry') {
|
|
3224
|
+
credentialResults.push({
|
|
3225
|
+
verified: true,
|
|
3226
|
+
status: 0,
|
|
3227
|
+
purpose: 'none',
|
|
3228
|
+
valid: true,
|
|
3229
|
+
});
|
|
3230
|
+
continue;
|
|
3231
|
+
}
|
|
3232
|
+
try {
|
|
3233
|
+
// Define issuer for provider selection
|
|
3234
|
+
const issuer =
|
|
3235
|
+
typeof credential.issuer === 'string'
|
|
3236
|
+
? credential.issuer
|
|
3237
|
+
: (credential.issuer as { id: string }).id;
|
|
3238
|
+
// Define provider, if applicable
|
|
3239
|
+
this.didProvider = await Cheqd.getProviderFromDidUrl(issuer, this.supportedDidProviders);
|
|
3240
|
+
this.providerId = Cheqd.generateProviderId(issuer);
|
|
3241
|
+
args.dkgOptions ||= this.didProvider.dkgOptions;
|
|
3242
|
+
// Verify credential with Bitstring status list
|
|
3243
|
+
const credentialVerificationResult = await this.VerifyCredentialWithBitstringStatusList(
|
|
3244
|
+
{
|
|
3245
|
+
credential: credential as BitstringVerifiableCredential,
|
|
3246
|
+
verificationArgs: {
|
|
3247
|
+
...args?.verificationArgs,
|
|
3248
|
+
policies: {
|
|
3249
|
+
...args?.verificationArgs?.policies,
|
|
3250
|
+
credentialStatus: false, // We handle this manually
|
|
3251
|
+
},
|
|
3252
|
+
credential: '',
|
|
3253
|
+
},
|
|
3254
|
+
fetchList: args?.fetchList ?? true,
|
|
3255
|
+
dkgOptions: args.dkgOptions,
|
|
3256
|
+
options: args.options,
|
|
3257
|
+
},
|
|
3258
|
+
context
|
|
2082
3259
|
);
|
|
3260
|
+
credentialResults.push(credentialVerificationResult);
|
|
3261
|
+
|
|
3262
|
+
// Track overall status
|
|
3263
|
+
if (!credentialVerificationResult.verified || !credentialVerificationResult.valid) {
|
|
3264
|
+
overallValid = false;
|
|
3265
|
+
}
|
|
3266
|
+
switch (credentialVerificationResult.status) {
|
|
3267
|
+
case BitstringStatusValue.REVOKED:
|
|
3268
|
+
hasRevoked = true;
|
|
3269
|
+
overallValid = false;
|
|
3270
|
+
break;
|
|
3271
|
+
case BitstringStatusValue.SUSPENDED:
|
|
3272
|
+
hasSuspended = true;
|
|
3273
|
+
overallValid = false;
|
|
3274
|
+
break;
|
|
3275
|
+
default:
|
|
3276
|
+
hasSuspended = false;
|
|
3277
|
+
hasRevoked = false;
|
|
3278
|
+
overallValid = true;
|
|
3279
|
+
}
|
|
3280
|
+
} catch (error) {
|
|
3281
|
+
credentialResults.push({
|
|
3282
|
+
verified: false,
|
|
3283
|
+
status: 1,
|
|
3284
|
+
purpose: credential.credentialStatus?.statusPurpose || 'unknown',
|
|
3285
|
+
valid: false,
|
|
3286
|
+
error: error as IError,
|
|
3287
|
+
});
|
|
3288
|
+
overallValid = false;
|
|
3289
|
+
}
|
|
2083
3290
|
}
|
|
2084
|
-
}
|
|
2085
3291
|
|
|
3292
|
+
// Determine overall verification result
|
|
3293
|
+
const allCredentialsVerified = credentialResults.every((result) => result.verified);
|
|
3294
|
+
const overallVerified = verificationResult.verified && allCredentialsVerified;
|
|
3295
|
+
|
|
3296
|
+
// Find the most significant status issue for reporting
|
|
3297
|
+
const firstFailedResult = credentialResults.find((result) => !result.verified || !result.valid);
|
|
3298
|
+
const resultStatus = firstFailedResult?.status ?? 0;
|
|
3299
|
+
const resultPurpose = firstFailedResult?.purpose ?? credentialResults[0]?.purpose ?? 'unknown';
|
|
3300
|
+
|
|
3301
|
+
return {
|
|
3302
|
+
verified: overallVerified,
|
|
3303
|
+
status: resultStatus,
|
|
3304
|
+
purpose: resultPurpose,
|
|
3305
|
+
valid: overallValid,
|
|
3306
|
+
revoked: hasRevoked,
|
|
3307
|
+
suspended: hasSuspended,
|
|
3308
|
+
message: firstFailedResult?.message,
|
|
3309
|
+
error: firstFailedResult?.error,
|
|
3310
|
+
};
|
|
3311
|
+
}
|
|
2086
3312
|
private async VerifyPresentationWithStatusList2021(
|
|
2087
|
-
args:
|
|
3313
|
+
args: ICheqdVerifyPresentationWithStatusListArgs,
|
|
2088
3314
|
context: IContext
|
|
2089
3315
|
): Promise<VerificationResult> {
|
|
2090
3316
|
// verify default policies
|
|
@@ -2146,7 +3372,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
2146
3372
|
}
|
|
2147
3373
|
|
|
2148
3374
|
private async CheckCredentialStatusWithStatusList2021(
|
|
2149
|
-
args:
|
|
3375
|
+
args: ICheqdCheckCredentialStatusWithStatusListArgs,
|
|
2150
3376
|
context: IContext
|
|
2151
3377
|
): Promise<StatusCheckResult> {
|
|
2152
3378
|
// verify credential, if provided and status options are not
|
|
@@ -2171,77 +3397,553 @@ export class Cheqd implements IAgentPlugin {
|
|
|
2171
3397
|
if (!args.statusOptions.issuerDid)
|
|
2172
3398
|
throw new Error('[did-provider-cheqd]: check status: statusOptions.issuerDid is required');
|
|
2173
3399
|
|
|
2174
|
-
// validate status options - case: statusOptions.statusListName
|
|
2175
|
-
if (!args.statusOptions.statusListName)
|
|
2176
|
-
throw new Error('[did-provider-cheqd]: check status: statusOptions.statusListName is required');
|
|
3400
|
+
// validate status options - case: statusOptions.statusListName
|
|
3401
|
+
if (!args.statusOptions.statusListName)
|
|
3402
|
+
throw new Error('[did-provider-cheqd]: check status: statusOptions.statusListName is required');
|
|
3403
|
+
|
|
3404
|
+
// validate status options - case: statusOptions.statusListIndex
|
|
3405
|
+
if (!args.statusOptions.statusPurpose)
|
|
3406
|
+
throw new Error('[did-provider-cheqd]: check status: statusOptions.statusListIndex is required');
|
|
3407
|
+
|
|
3408
|
+
// validate status options - case: statusOptions.statusListIndex
|
|
3409
|
+
if (!args.statusOptions.statusListIndex)
|
|
3410
|
+
throw new Error('[did-provider-cheqd]: check status: statusOptions.statusListIndex is required');
|
|
3411
|
+
|
|
3412
|
+
// generate resource type
|
|
3413
|
+
const resourceType =
|
|
3414
|
+
args.statusOptions.statusPurpose === DefaultStatusList2021StatusPurposeTypes.revocation
|
|
3415
|
+
? DefaultStatusList2021ResourceTypes.revocation
|
|
3416
|
+
: DefaultStatusList2021ResourceTypes.suspension;
|
|
3417
|
+
|
|
3418
|
+
// construct status list credential
|
|
3419
|
+
const statusListCredential = `${DefaultResolverUrl}${args.statusOptions.issuerDid}?resourceName=${args.statusOptions.statusListName}&resourceType=${resourceType}`;
|
|
3420
|
+
|
|
3421
|
+
// construct credential status
|
|
3422
|
+
args.credential = {
|
|
3423
|
+
'@context': [],
|
|
3424
|
+
issuer: args.statusOptions.issuerDid,
|
|
3425
|
+
credentialSubject: {},
|
|
3426
|
+
credentialStatus: {
|
|
3427
|
+
id: `${statusListCredential}#${args.statusOptions.statusListIndex}`,
|
|
3428
|
+
type: 'StatusList2021Entry',
|
|
3429
|
+
statusPurpose: `${args.statusOptions.statusPurpose}`,
|
|
3430
|
+
statusListIndex: `${args.statusOptions.statusListIndex}`,
|
|
3431
|
+
},
|
|
3432
|
+
issuanceDate: '',
|
|
3433
|
+
proof: {},
|
|
3434
|
+
};
|
|
3435
|
+
}
|
|
3436
|
+
|
|
3437
|
+
// validate args - case: credential
|
|
3438
|
+
if (!args.credential) throw new Error('[did-provider-cheqd]: revocation: credential is required');
|
|
3439
|
+
|
|
3440
|
+
// if jwt credential, decode it
|
|
3441
|
+
const credential =
|
|
3442
|
+
typeof args.credential === 'string' ? await Cheqd.decodeCredentialJWT(args.credential) : args.credential;
|
|
3443
|
+
|
|
3444
|
+
// define issuer
|
|
3445
|
+
const issuer =
|
|
3446
|
+
typeof credential.issuer === 'string' ? credential.issuer : (credential.issuer as { id: string }).id;
|
|
3447
|
+
|
|
3448
|
+
// define provider, if applicable
|
|
3449
|
+
this.didProvider = await Cheqd.getProviderFromDidUrl(issuer, this.supportedDidProviders);
|
|
3450
|
+
|
|
3451
|
+
// define provider id, if applicable
|
|
3452
|
+
this.providerId = Cheqd.generateProviderId(issuer);
|
|
3453
|
+
|
|
3454
|
+
// define dkg options, if provided
|
|
3455
|
+
args.dkgOptions ||= this.didProvider.dkgOptions;
|
|
3456
|
+
|
|
3457
|
+
switch (credential.credentialStatus?.statusPurpose) {
|
|
3458
|
+
case DefaultStatusList2021StatusPurposeTypes.revocation:
|
|
3459
|
+
return { revoked: await Cheqd.checkRevoked(credential, { ...args.options, topArgs: args }) };
|
|
3460
|
+
case DefaultStatusList2021StatusPurposeTypes.suspension:
|
|
3461
|
+
return { suspended: await Cheqd.checkSuspended(credential, { ...args.options, topArgs: args }) };
|
|
3462
|
+
default:
|
|
3463
|
+
throw new Error(
|
|
3464
|
+
`[did-provider-cheqd]: check status: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`
|
|
3465
|
+
);
|
|
3466
|
+
}
|
|
3467
|
+
}
|
|
3468
|
+
private async UpdateCredentialWithStatusList(
|
|
3469
|
+
args: ICheqdUpdateCredentialWithStatusListArgs,
|
|
3470
|
+
context: IContext
|
|
3471
|
+
): Promise<BitstringUpdateResult> {
|
|
3472
|
+
// Verify credential if provided and update options are not
|
|
3473
|
+
if (args?.credential && !args?.updateOptions) {
|
|
3474
|
+
const verificationResult = await context.agent.verifyCredential({
|
|
3475
|
+
...args?.verificationOptions,
|
|
3476
|
+
credential: args.credential,
|
|
3477
|
+
policies: {
|
|
3478
|
+
credentialStatus: false,
|
|
3479
|
+
},
|
|
3480
|
+
} satisfies IVerifyCredentialArgs);
|
|
3481
|
+
|
|
3482
|
+
if (!verificationResult.verified) {
|
|
3483
|
+
return {
|
|
3484
|
+
updated: false,
|
|
3485
|
+
statusValue: BitstringStatusValue.UNKNOWN,
|
|
3486
|
+
statusMessage: 'unknown',
|
|
3487
|
+
error: verificationResult.error,
|
|
3488
|
+
};
|
|
3489
|
+
}
|
|
3490
|
+
}
|
|
3491
|
+
if (typeof args.newStatus !== 'number' || args.newStatus < 0 || args.newStatus > 3)
|
|
3492
|
+
throw new Error(
|
|
3493
|
+
'[did-provider-cheqd]: updateOptions.newStatus must be 0-3 (valid/revoked/suspended/unknown)'
|
|
3494
|
+
);
|
|
3495
|
+
// if update options are provided, give precedence
|
|
3496
|
+
if (args?.updateOptions) {
|
|
3497
|
+
// Validate update options
|
|
3498
|
+
if (!args.updateOptions.issuerDid)
|
|
3499
|
+
throw new Error('[did-provider-cheqd]: updateOptions.issuerDid is required');
|
|
3500
|
+
if (!args.updateOptions.statusListName)
|
|
3501
|
+
throw new Error('[did-provider-cheqd]: updateOptions.statusListName is required');
|
|
3502
|
+
if (typeof args.updateOptions.statusListIndex !== 'number')
|
|
3503
|
+
throw new Error('[did-provider-cheqd]: updateOptions.statusListIndex is required');
|
|
3504
|
+
|
|
3505
|
+
// Construct status list credential URL
|
|
3506
|
+
const statusListCredential = `${DefaultResolverUrl}${args.updateOptions.issuerDid}?resourceName=${args.updateOptions.statusListName}&resourceType=${BitstringStatusListResourceType}`;
|
|
3507
|
+
|
|
3508
|
+
// fetch latest status list
|
|
3509
|
+
const statusList = await Cheqd.fetchBitstringStatusList({
|
|
3510
|
+
credentialStatus: {
|
|
3511
|
+
id: statusListCredential,
|
|
3512
|
+
},
|
|
3513
|
+
} as VerifiableCredential);
|
|
3514
|
+
|
|
3515
|
+
// For multi-purpose status lists, we need to determine the appropriate statusPurpose
|
|
3516
|
+
// based on the credential's current status entry or the new status being set
|
|
3517
|
+
const statusPurpose = this.getStatusPurposeForMultiPurposeList(args.newStatus);
|
|
3518
|
+
// Override the credential with new status information
|
|
3519
|
+
args.credential = {
|
|
3520
|
+
'@context': [],
|
|
3521
|
+
issuer: args.updateOptions.issuerDid,
|
|
3522
|
+
credentialSubject: {},
|
|
3523
|
+
credentialStatus: {
|
|
3524
|
+
id: `${statusListCredential}#${args.updateOptions.statusListIndex}`,
|
|
3525
|
+
type: 'BitstringStatusListEntry',
|
|
3526
|
+
statusPurpose: statusPurpose,
|
|
3527
|
+
statusListIndex: `${args.updateOptions.statusListIndex}`,
|
|
3528
|
+
statusListCredential,
|
|
3529
|
+
statusSize: statusList.metadata.statusSize || 1,
|
|
3530
|
+
statusMessage: statusList.metadata.statusMessages || [],
|
|
3531
|
+
},
|
|
3532
|
+
issuanceDate: '',
|
|
3533
|
+
proof: {},
|
|
3534
|
+
};
|
|
3535
|
+
}
|
|
3536
|
+
// if jwt credential, decode it
|
|
3537
|
+
const credential =
|
|
3538
|
+
typeof args.credential === 'string' ? await Cheqd.decodeCredentialJWT(args.credential) : args.credential;
|
|
3539
|
+
// Validate that credential MUST have credentialStatus
|
|
3540
|
+
if (!credential?.credentialStatus) {
|
|
3541
|
+
throw new Error('[did-provider-cheqd]: update: credential must have credentialStatus');
|
|
3542
|
+
}
|
|
3543
|
+
// Validate that credentialStatus is BitstringStatusListEntry
|
|
3544
|
+
if (credential.credentialStatus.type !== 'BitstringStatusListEntry') {
|
|
3545
|
+
throw new Error(
|
|
3546
|
+
'[did-provider-cheqd]: update: credential must have BitstringStatusListEntry credentialStatus'
|
|
3547
|
+
);
|
|
3548
|
+
}
|
|
3549
|
+
|
|
3550
|
+
// validate args in pairs - case: statusListFile and statusList
|
|
3551
|
+
if (args.options?.statusListFile && args.options?.statusList) {
|
|
3552
|
+
throw new Error('[did-provider-cheqd]: revocation: statusListFile and statusList are mutually exclusive');
|
|
3553
|
+
}
|
|
3554
|
+
|
|
3555
|
+
// validate args in pairs - case: statusListFile and fetchList
|
|
3556
|
+
if (args.options?.statusListFile && args.options?.fetchList) {
|
|
3557
|
+
throw new Error('[did-provider-cheqd]: revocation: statusListFile and fetchList are mutually exclusive');
|
|
3558
|
+
}
|
|
3559
|
+
|
|
3560
|
+
// validate args in pairs - case: statusList and fetchList
|
|
3561
|
+
if (args.options?.statusList && args.options?.fetchList) {
|
|
3562
|
+
throw new Error('[did-provider-cheqd]: revocation: statusList and fetchList are mutually exclusive');
|
|
3563
|
+
}
|
|
3564
|
+
|
|
3565
|
+
// validate args in pairs - case: publish
|
|
3566
|
+
if (args.options?.publish && !args.fetchList && !(args.options?.statusListFile || args.options?.statusList)) {
|
|
3567
|
+
throw new Error(
|
|
3568
|
+
'[did-provider-cheqd]: revocation: publish requires statusListFile or statusList, if fetchList is disabled'
|
|
3569
|
+
);
|
|
3570
|
+
}
|
|
3571
|
+
|
|
3572
|
+
// Define issuer and provider
|
|
3573
|
+
const issuer =
|
|
3574
|
+
typeof credential.issuer === 'string' ? credential.issuer : (credential.issuer as { id: string }).id;
|
|
3575
|
+
|
|
3576
|
+
this.didProvider = await Cheqd.getProviderFromDidUrl(issuer, this.supportedDidProviders);
|
|
3577
|
+
this.providerId = Cheqd.generateProviderId(issuer);
|
|
3578
|
+
args.dkgOptions ||= this.didProvider.dkgOptions;
|
|
3579
|
+
|
|
3580
|
+
// Perform the status update
|
|
3581
|
+
return await Cheqd.updateBitstringCredentialStatus(credential, {
|
|
3582
|
+
...args.options,
|
|
3583
|
+
topArgs: args,
|
|
3584
|
+
publishOptions: {
|
|
3585
|
+
context,
|
|
3586
|
+
statusListEncoding: args?.options?.statusListEncoding,
|
|
3587
|
+
statusListValidUntil: args?.options?.statusListValidUntil,
|
|
3588
|
+
resourceId: args?.options?.resourceId,
|
|
3589
|
+
resourceVersion: args?.options?.resourceVersion,
|
|
3590
|
+
resourceAlsoKnownAs: args?.options?.alsoKnownAs,
|
|
3591
|
+
signInputs: args?.options?.signInputs,
|
|
3592
|
+
fee: args?.options?.fee,
|
|
3593
|
+
},
|
|
3594
|
+
});
|
|
3595
|
+
}
|
|
3596
|
+
private getStatusPurposeForMultiPurposeList(newStatus: BitstringStatusValue): BitstringStatusListPurposeType {
|
|
3597
|
+
// TODO Add map with messages
|
|
3598
|
+
// Since the default status list supports multiple purposes, we can use any of them
|
|
3599
|
+
// For multi-purpose lists, typically 'message' is used as it's the most flexible
|
|
3600
|
+
return BitstringStatusPurposeTypes.message;
|
|
3601
|
+
}
|
|
3602
|
+
// Core status update logic for multi-purpose Bitstring Status Lists
|
|
3603
|
+
static async updateBitstringCredentialStatus(
|
|
3604
|
+
credential: VerifiableCredential,
|
|
3605
|
+
options?: ICheqdStatusListOptions
|
|
3606
|
+
): Promise<BitstringUpdateResult> {
|
|
3607
|
+
try {
|
|
3608
|
+
// Validate credential status
|
|
3609
|
+
if (!credential.credentialStatus) {
|
|
3610
|
+
throw new Error('[did-provider-cheqd]: update: Credential status is not present');
|
|
3611
|
+
}
|
|
3612
|
+
|
|
3613
|
+
// Fetch published status list
|
|
3614
|
+
const publishedList = await Cheqd.fetchBitstringStatusList(credential);
|
|
3615
|
+
|
|
3616
|
+
// Validate that this is a multi-purpose status list with 2-bit status
|
|
3617
|
+
if (publishedList.metadata.statusSize !== 2) {
|
|
3618
|
+
throw new Error('[did-provider-cheqd]: update: Status list must use 2-bit status size');
|
|
3619
|
+
}
|
|
3620
|
+
// Validate status messages are present for 2-bit status
|
|
3621
|
+
if (!publishedList.metadata.statusMessages || publishedList.metadata.statusMessages.length !== 4) {
|
|
3622
|
+
throw new Error(
|
|
3623
|
+
'[did-provider-cheqd]: update: Status list must have 4 status messages for 2-bit status'
|
|
3624
|
+
);
|
|
3625
|
+
}
|
|
3626
|
+
|
|
3627
|
+
// Early return if encrypted and no decryption key provided
|
|
3628
|
+
if (publishedList.metadata.encrypted && !options?.topArgs?.symmetricKey) {
|
|
3629
|
+
throw new Error('[did-provider-cheqd]: update: symmetricKey is required for encrypted status list');
|
|
3630
|
+
}
|
|
3631
|
+
// Calculate positions and values
|
|
3632
|
+
const statusIndex = parseInt(credential.credentialStatus.statusListIndex, 10);
|
|
3633
|
+
const statusSize = publishedList.metadata.statusSize; // Should be 2
|
|
3634
|
+
const newStatusValue = options?.topArgs.newStatus;
|
|
3635
|
+
|
|
3636
|
+
// Fetch and decrypt the current bitstring
|
|
3637
|
+
const currentBitstring = await Cheqd.fetchAndDecryptBitstring(publishedList, options);
|
|
3638
|
+
// Parse the bitstring
|
|
3639
|
+
const decompressedBuffer = await DBBitstring.decodeBits({ encoded: currentBitstring });
|
|
3640
|
+
const bitstring = new DBBitstring({ buffer: decompressedBuffer });
|
|
3641
|
+
|
|
3642
|
+
// Get current status value
|
|
3643
|
+
const bitPosition = statusIndex * statusSize;
|
|
3644
|
+
const currentStatusValue = Cheqd.getBitValue(bitstring, bitPosition, statusSize);
|
|
3645
|
+
|
|
3646
|
+
// Check if update is needed
|
|
3647
|
+
if (currentStatusValue === newStatusValue) {
|
|
3648
|
+
const statusMessage =
|
|
3649
|
+
publishedList.metadata.statusMessages.find((msg) => parseInt(msg.status, 16) === currentStatusValue)
|
|
3650
|
+
?.message || 'unknown';
|
|
3651
|
+
|
|
3652
|
+
return {
|
|
3653
|
+
updated: false,
|
|
3654
|
+
statusValue: currentStatusValue as BitstringStatusValue,
|
|
3655
|
+
statusMessage,
|
|
3656
|
+
error: { message: `Credential already has status value ${newStatusValue} (${statusMessage})` },
|
|
3657
|
+
};
|
|
3658
|
+
}
|
|
3659
|
+
|
|
3660
|
+
// Update the bitstring
|
|
3661
|
+
Cheqd.setBitValue(bitstring, bitPosition, newStatusValue, statusSize);
|
|
3662
|
+
|
|
3663
|
+
// Compress the updated bitstring
|
|
3664
|
+
const compressedBitstring = await bitstring.compressBits();
|
|
3665
|
+
const encodedBitstring = toString(compressedBitstring, 'base64url');
|
|
3666
|
+
|
|
3667
|
+
// Create updated status list credential
|
|
3668
|
+
const updatedStatusListCredential = {
|
|
3669
|
+
...publishedList.bitstringStatusListCredential,
|
|
3670
|
+
credentialSubject: {
|
|
3671
|
+
...publishedList.bitstringStatusListCredential.credentialSubject,
|
|
3672
|
+
encodedList: encodedBitstring,
|
|
3673
|
+
},
|
|
3674
|
+
};
|
|
3675
|
+
|
|
3676
|
+
const updatedStatusList: BitstringStatusList = {
|
|
3677
|
+
bitstringStatusListCredential: updatedStatusListCredential,
|
|
3678
|
+
metadata: publishedList.metadata,
|
|
3679
|
+
};
|
|
3680
|
+
|
|
3681
|
+
// Write to file if requested
|
|
3682
|
+
if (options?.topArgs?.writeToFile) {
|
|
3683
|
+
await Cheqd.writeFile(compressedBitstring, options?.statusListFile);
|
|
3684
|
+
}
|
|
3685
|
+
|
|
3686
|
+
// Publish if requested
|
|
3687
|
+
const published = options?.topArgs?.publish
|
|
3688
|
+
? await Cheqd.publishUpdatedBitstringStatusList(updatedStatusList, credential, options)
|
|
3689
|
+
: undefined;
|
|
3690
|
+
|
|
3691
|
+
// Get status message for new value
|
|
3692
|
+
const newStatusMessage =
|
|
3693
|
+
publishedList.metadata.statusMessages.find((msg) => parseInt(msg.status, 16) === newStatusValue)
|
|
3694
|
+
?.message || 'unknown';
|
|
3695
|
+
|
|
3696
|
+
const previousStatusMessage =
|
|
3697
|
+
publishedList.metadata.statusMessages.find((msg) => parseInt(msg.status, 16) === currentStatusValue)
|
|
3698
|
+
?.message || 'unknown';
|
|
3699
|
+
|
|
3700
|
+
return {
|
|
3701
|
+
updated: true,
|
|
3702
|
+
statusValue: newStatusValue as BitstringStatusValue,
|
|
3703
|
+
previousStatusValue: currentStatusValue as BitstringStatusValue,
|
|
3704
|
+
statusMessage: newStatusMessage,
|
|
3705
|
+
published: options?.topArgs?.publish ? !!published : undefined,
|
|
3706
|
+
statusList: options?.topArgs?.returnUpdatedStatusList ? updatedStatusList : undefined,
|
|
3707
|
+
symmetricKey:
|
|
3708
|
+
options?.topArgs?.returnSymmetricKey && published?.symmetricKey
|
|
3709
|
+
? published.symmetricKey
|
|
3710
|
+
: undefined,
|
|
3711
|
+
resourceMetadata: options?.topArgs?.returnStatusListMetadata
|
|
3712
|
+
? await Cheqd.fetchStatusListMetadata(credential)
|
|
3713
|
+
: undefined,
|
|
3714
|
+
};
|
|
3715
|
+
} catch (error) {
|
|
3716
|
+
console.error('[did-provider-cheqd]: update error:', error);
|
|
3717
|
+
return {
|
|
3718
|
+
updated: false,
|
|
3719
|
+
statusValue: BitstringStatusValue.UNKNOWN,
|
|
3720
|
+
statusMessage: 'unknown',
|
|
3721
|
+
error: error as IError,
|
|
3722
|
+
};
|
|
3723
|
+
}
|
|
3724
|
+
}
|
|
3725
|
+
|
|
3726
|
+
// Helper function to fetch and decrypt bitstring (same as before)
|
|
3727
|
+
static async fetchAndDecryptBitstring(
|
|
3728
|
+
publishedList: BitstringStatusList,
|
|
3729
|
+
options?: ICheqdStatusListOptions
|
|
3730
|
+
): Promise<string> {
|
|
3731
|
+
const topArgs = options?.topArgs as ICheqdUpdateCredentialWithStatusListArgs;
|
|
3732
|
+
const encoded = publishedList.bitstringStatusListCredential.credentialSubject.encodedList;
|
|
3733
|
+
if (topArgs?.fetchList) {
|
|
3734
|
+
// if not encrypted, return published bitstring (always base64url encoded)
|
|
3735
|
+
if (!publishedList.metadata.encrypted) {
|
|
3736
|
+
return encoded;
|
|
3737
|
+
}
|
|
3738
|
+
|
|
3739
|
+
// otherwise, Decrypt using threshold encryption
|
|
3740
|
+
const { thresholdEncryptionCiphertext } = decodeWithMetadata(
|
|
3741
|
+
publishedList.bitstringStatusListCredential.credentialSubject.encodedList,
|
|
3742
|
+
publishedList.metadata.symmetricLength!
|
|
3743
|
+
);
|
|
3744
|
+
|
|
3745
|
+
const lit = (await options!.instantiateDkgClient()) as LitProtocol;
|
|
3746
|
+
// construct access control conditions
|
|
3747
|
+
const unifiedAccessControlConditions = await Promise.all(
|
|
3748
|
+
publishedList.metadata.paymentConditions!.map(async (condition) => {
|
|
3749
|
+
switch (condition.type) {
|
|
3750
|
+
case AccessControlConditionTypes.timelockPayment:
|
|
3751
|
+
return await LitProtocol.generateCosmosAccessControlConditionInverseTimelock(
|
|
3752
|
+
{
|
|
3753
|
+
key: '$.tx_responses.*.timestamp',
|
|
3754
|
+
comparator: '<=',
|
|
3755
|
+
value: `${condition.intervalInSeconds}`,
|
|
3756
|
+
},
|
|
3757
|
+
condition.feePaymentAmount,
|
|
3758
|
+
condition.feePaymentAddress,
|
|
3759
|
+
condition?.blockHeight,
|
|
3760
|
+
options?.topArgs?.dkgOptions?.chain
|
|
3761
|
+
);
|
|
3762
|
+
default:
|
|
3763
|
+
throw new Error(
|
|
3764
|
+
`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`
|
|
3765
|
+
);
|
|
3766
|
+
}
|
|
3767
|
+
})
|
|
3768
|
+
);
|
|
3769
|
+
return await lit.decrypt(
|
|
3770
|
+
toString(thresholdEncryptionCiphertext, 'base64url'),
|
|
3771
|
+
publishedList.metadata.statusListHash!,
|
|
3772
|
+
unifiedAccessControlConditions
|
|
3773
|
+
);
|
|
3774
|
+
} else {
|
|
3775
|
+
// Use provided symmetric key or file
|
|
3776
|
+
if (options?.statusListFile) {
|
|
3777
|
+
// if not encrypted, return bitstring
|
|
3778
|
+
if (!publishedList.metadata.encrypted) {
|
|
3779
|
+
// construct encoded status list
|
|
3780
|
+
const bitstring = new DBBitstring({
|
|
3781
|
+
buffer: await Cheqd.getFile(options.statusListFile),
|
|
3782
|
+
});
|
|
3783
|
+
const compressed = await bitstring.compressBits();
|
|
3784
|
+
// validate against published list
|
|
3785
|
+
if (encoded !== toString(compressed, 'base64url'))
|
|
3786
|
+
throw new Error(
|
|
3787
|
+
'[did-provider-cheqd]: statusListFile does not match published Bitstring status list'
|
|
3788
|
+
);
|
|
3789
|
+
|
|
3790
|
+
// return compressed
|
|
3791
|
+
return compressed;
|
|
3792
|
+
}
|
|
3793
|
+
// otherwise, decrypt and return bitstring
|
|
3794
|
+
const scopedRawBlob = await toBlob(await Cheqd.getFile(options.statusListFile));
|
|
3795
|
+
const decrypted = toString(
|
|
3796
|
+
await LitProtocol.decryptDirect(
|
|
3797
|
+
scopedRawBlob,
|
|
3798
|
+
await safeDeserialise(
|
|
3799
|
+
options?.topArgs?.symmetricKey,
|
|
3800
|
+
fromString,
|
|
3801
|
+
['hex'],
|
|
3802
|
+
'Invalid symmetric key'
|
|
3803
|
+
)
|
|
3804
|
+
),
|
|
3805
|
+
'base64url'
|
|
3806
|
+
);
|
|
3807
|
+
|
|
3808
|
+
// validate against published list
|
|
3809
|
+
if (decrypted !== encoded)
|
|
3810
|
+
throw new Error(
|
|
3811
|
+
'[did-provider-cheqd]: statusListFile does not match published Bitstring status list'
|
|
3812
|
+
);
|
|
2177
3813
|
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
3814
|
+
// return decrypted
|
|
3815
|
+
return decrypted;
|
|
3816
|
+
}
|
|
2181
3817
|
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
3818
|
+
if (!options?.statusListInlineBitstring) {
|
|
3819
|
+
throw new Error(
|
|
3820
|
+
'[did-provider-cheqd]: statusListInlineBitstring required if statusListFile not provided'
|
|
3821
|
+
);
|
|
3822
|
+
}
|
|
3823
|
+
// validate against published list
|
|
3824
|
+
if (options?.statusListInlineBitstring !== encoded)
|
|
3825
|
+
throw new Error(
|
|
3826
|
+
'[did-provider-cheqd]: statusListInlineBitstring does not match published bitstring status list'
|
|
3827
|
+
);
|
|
3828
|
+
// otherwise, read from inline bitstring
|
|
3829
|
+
return options.statusListInlineBitstring;
|
|
3830
|
+
}
|
|
3831
|
+
}
|
|
3832
|
+
// Helper function to publish updated status list
|
|
3833
|
+
static async publishUpdatedBitstringStatusList(
|
|
3834
|
+
updatedStatusList: BitstringStatusList,
|
|
3835
|
+
credential: VerifiableCredential,
|
|
3836
|
+
options?: ICheqdStatusListOptions
|
|
3837
|
+
): Promise<{ symmetricKey?: string }> {
|
|
3838
|
+
const topArgs = options?.topArgs as ICheqdUpdateCredentialWithStatusListArgs;
|
|
2185
3839
|
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
args.statusOptions.statusPurpose === DefaultStatusList2021StatusPurposeTypes.revocation
|
|
2189
|
-
? DefaultStatusList2021ResourceTypes.revocation
|
|
2190
|
-
: DefaultStatusList2021ResourceTypes.suspension;
|
|
3840
|
+
// Fetch current metadata
|
|
3841
|
+
const statusListMetadata = await Cheqd.fetchStatusListMetadata(credential);
|
|
2191
3842
|
|
|
2192
|
-
|
|
2193
|
-
|
|
3843
|
+
// Handle encrypted publishing if needed
|
|
3844
|
+
if (topArgs.publishEncrypted && updatedStatusList.metadata.encrypted) {
|
|
3845
|
+
// Re-encrypt with new content
|
|
3846
|
+
const bitstring = updatedStatusList.bitstringStatusListCredential.credentialSubject.encodedList;
|
|
2194
3847
|
|
|
2195
|
-
//
|
|
2196
|
-
|
|
2197
|
-
'
|
|
2198
|
-
|
|
2199
|
-
credentialSubject: {},
|
|
2200
|
-
credentialStatus: {
|
|
2201
|
-
id: `${statusListCredential}#${args.statusOptions.statusListIndex}`,
|
|
2202
|
-
type: 'StatusList2021Entry',
|
|
2203
|
-
statusPurpose: `${args.statusOptions.statusPurpose}`,
|
|
2204
|
-
statusListIndex: `${args.statusOptions.statusListIndex}`,
|
|
2205
|
-
},
|
|
2206
|
-
issuanceDate: '',
|
|
2207
|
-
proof: {},
|
|
2208
|
-
};
|
|
2209
|
-
}
|
|
3848
|
+
// Encrypt bitstring - case: symmetric
|
|
3849
|
+
const { encryptedString: symmetricEncryptionCiphertext, symmetricKey } = await LitProtocol.encryptDirect(
|
|
3850
|
+
fromString(bitstring, 'base64url')
|
|
3851
|
+
);
|
|
2210
3852
|
|
|
2211
|
-
|
|
2212
|
-
|
|
3853
|
+
// Get DKG client and encrypt threshold
|
|
3854
|
+
const lit = await options!.publishOptions.instantiateDkgClient();
|
|
3855
|
+
const unifiedAccessControlConditions = await Promise.all(
|
|
3856
|
+
updatedStatusList.metadata.paymentConditions!.map(async (condition) => {
|
|
3857
|
+
switch (condition.type) {
|
|
3858
|
+
case AccessControlConditionTypes.timelockPayment:
|
|
3859
|
+
return await LitProtocol.generateCosmosAccessControlConditionInverseTimelock(
|
|
3860
|
+
{
|
|
3861
|
+
key: '$.tx_responses.*.timestamp',
|
|
3862
|
+
comparator: '<=',
|
|
3863
|
+
value: `${condition.intervalInSeconds}`,
|
|
3864
|
+
},
|
|
3865
|
+
condition.feePaymentAmount,
|
|
3866
|
+
condition.feePaymentAddress,
|
|
3867
|
+
condition?.blockHeight,
|
|
3868
|
+
topArgs?.dkgOptions?.chain
|
|
3869
|
+
);
|
|
3870
|
+
default:
|
|
3871
|
+
throw new Error(
|
|
3872
|
+
`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`
|
|
3873
|
+
);
|
|
3874
|
+
}
|
|
3875
|
+
})
|
|
3876
|
+
);
|
|
2213
3877
|
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
3878
|
+
const { encryptedString: thresholdEncryptionCiphertext, stringHash } = await lit.encrypt(
|
|
3879
|
+
fromString(bitstring, 'base64url'),
|
|
3880
|
+
unifiedAccessControlConditions
|
|
3881
|
+
);
|
|
2217
3882
|
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
3883
|
+
// Update encoded list with encrypted content
|
|
3884
|
+
const { encodedList, symmetricLength } = await encodeWithMetadata(
|
|
3885
|
+
symmetricEncryptionCiphertext,
|
|
3886
|
+
thresholdEncryptionCiphertext
|
|
3887
|
+
);
|
|
2221
3888
|
|
|
2222
|
-
|
|
2223
|
-
|
|
3889
|
+
updatedStatusList.bitstringStatusListCredential.credentialSubject.encodedList = encodedList;
|
|
3890
|
+
updatedStatusList.metadata.statusListHash = stringHash;
|
|
3891
|
+
updatedStatusList.metadata.symmetricLength = symmetricLength;
|
|
2224
3892
|
|
|
2225
|
-
|
|
2226
|
-
|
|
3893
|
+
// Publish the encrypted status list
|
|
3894
|
+
await Cheqd.publishBitstringStatusList(
|
|
3895
|
+
fromString(JSON.stringify(updatedStatusList), 'utf-8'),
|
|
3896
|
+
statusListMetadata,
|
|
3897
|
+
options?.publishOptions
|
|
3898
|
+
);
|
|
2227
3899
|
|
|
2228
|
-
|
|
2229
|
-
|
|
3900
|
+
return { symmetricKey: toString(symmetricKey, 'hex') };
|
|
3901
|
+
} else {
|
|
3902
|
+
// Publish unencrypted
|
|
3903
|
+
await Cheqd.publishBitstringStatusList(
|
|
3904
|
+
fromString(JSON.stringify(updatedStatusList), 'utf-8'),
|
|
3905
|
+
statusListMetadata,
|
|
3906
|
+
options?.publishOptions
|
|
3907
|
+
);
|
|
2230
3908
|
|
|
2231
|
-
|
|
2232
|
-
case DefaultStatusList2021StatusPurposeTypes.revocation:
|
|
2233
|
-
return { revoked: await Cheqd.checkRevoked(credential, { ...args.options, topArgs: args }) };
|
|
2234
|
-
case DefaultStatusList2021StatusPurposeTypes.suspension:
|
|
2235
|
-
return { suspended: await Cheqd.checkSuspended(credential, { ...args.options, topArgs: args }) };
|
|
2236
|
-
default:
|
|
2237
|
-
throw new Error(
|
|
2238
|
-
`[did-provider-cheqd]: check status: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`
|
|
2239
|
-
);
|
|
3909
|
+
return {};
|
|
2240
3910
|
}
|
|
2241
3911
|
}
|
|
3912
|
+
// Helper function to publish bitstring status list
|
|
3913
|
+
static async publishBitstringStatusList(
|
|
3914
|
+
statusListRaw: Uint8Array,
|
|
3915
|
+
statusListMetadata: LinkedResourceMetadataResolutionResult,
|
|
3916
|
+
options: {
|
|
3917
|
+
context: IContext;
|
|
3918
|
+
resourceId?: string;
|
|
3919
|
+
resourceVersion?: string;
|
|
3920
|
+
resourceAlsoKnownAs?: AlternativeUri[];
|
|
3921
|
+
signInputs?: ISignInputs[];
|
|
3922
|
+
fee?: DidStdFee | 'auto' | number;
|
|
3923
|
+
}
|
|
3924
|
+
): Promise<boolean> {
|
|
3925
|
+
// Construct payload
|
|
3926
|
+
const payload = {
|
|
3927
|
+
id: options?.resourceId || v4(),
|
|
3928
|
+
collectionId: statusListMetadata.resourceCollectionId,
|
|
3929
|
+
name: statusListMetadata.resourceName,
|
|
3930
|
+
version: options?.resourceVersion || new Date().toISOString(),
|
|
3931
|
+
alsoKnownAs: options?.resourceAlsoKnownAs || [],
|
|
3932
|
+
resourceType: BitstringStatusListResourceType,
|
|
3933
|
+
data: statusListRaw,
|
|
3934
|
+
} satisfies BitstringStatusListResourcePayload;
|
|
3935
|
+
|
|
3936
|
+
return await options.context.agent[BroadcastStatusListMethodName]({
|
|
3937
|
+
kms: (await options.context.agent.keyManagerGetKeyManagementSystems())[0],
|
|
3938
|
+
payload,
|
|
3939
|
+
network: statusListMetadata.resourceURI.split(':')[2] as CheqdNetwork,
|
|
3940
|
+
signInputs: options?.signInputs,
|
|
3941
|
+
fee: options?.fee,
|
|
3942
|
+
});
|
|
3943
|
+
}
|
|
2242
3944
|
|
|
2243
3945
|
private async RevokeCredentialWithStatusList2021(
|
|
2244
|
-
args:
|
|
3946
|
+
args: ICheqdRevokeCredentialWithStatusListArgs,
|
|
2245
3947
|
context: IContext
|
|
2246
3948
|
): Promise<RevocationResult> {
|
|
2247
3949
|
// verify credential, if provided and revocation options are not
|
|
@@ -2359,8 +4061,321 @@ export class Cheqd implements IAgentPlugin {
|
|
|
2359
4061
|
});
|
|
2360
4062
|
}
|
|
2361
4063
|
|
|
4064
|
+
private async BulkUpdateCredentialsWithStatusList(
|
|
4065
|
+
args: ICheqdBulkUpdateCredentialWithStatusListArgs,
|
|
4066
|
+
context: IContext
|
|
4067
|
+
): Promise<BulkBitstringUpdateResult> {
|
|
4068
|
+
// validate new status value
|
|
4069
|
+
if (typeof args.newStatus !== 'number' || args.newStatus < 0 || args.newStatus > 3) {
|
|
4070
|
+
throw new Error(
|
|
4071
|
+
'[did-provider-cheqd]: bulk update: newStatus must be 0-3 (valid/revoked/suspended/unknown)'
|
|
4072
|
+
);
|
|
4073
|
+
}
|
|
4074
|
+
|
|
4075
|
+
// verify credentials, if provided and update options are not
|
|
4076
|
+
if (args?.credentials && !args?.updateOptions) {
|
|
4077
|
+
const verificationResult = await Promise.all(
|
|
4078
|
+
args.credentials.map(async (credential) => {
|
|
4079
|
+
return await context.agent.verifyCredential({
|
|
4080
|
+
...args?.verificationOptions,
|
|
4081
|
+
credential,
|
|
4082
|
+
policies: {
|
|
4083
|
+
credentialStatus: false,
|
|
4084
|
+
},
|
|
4085
|
+
} satisfies IVerifyCredentialArgs);
|
|
4086
|
+
})
|
|
4087
|
+
);
|
|
4088
|
+
|
|
4089
|
+
// early return if verification failed for any credential
|
|
4090
|
+
if (verificationResult.some((result) => !result.verified)) {
|
|
4091
|
+
return {
|
|
4092
|
+
updated: Array(args.credentials.length).fill(false),
|
|
4093
|
+
statusValues: Array(args.credentials.length).fill(BitstringStatusValue.UNKNOWN),
|
|
4094
|
+
statusMessages: Array(args.credentials.length).fill('verification failed'),
|
|
4095
|
+
error: verificationResult.find((result) => !result.verified)!.error || {
|
|
4096
|
+
message: 'verification: could not verify credential',
|
|
4097
|
+
},
|
|
4098
|
+
};
|
|
4099
|
+
}
|
|
4100
|
+
}
|
|
4101
|
+
|
|
4102
|
+
// if update options are provided, give precedence
|
|
4103
|
+
if (args?.updateOptions) {
|
|
4104
|
+
// validate update options
|
|
4105
|
+
if (!args.updateOptions.issuerDid) {
|
|
4106
|
+
throw new Error('[did-provider-cheqd]: bulk update: updateOptions.issuerDid is required');
|
|
4107
|
+
}
|
|
4108
|
+
if (!args.updateOptions.statusListName) {
|
|
4109
|
+
throw new Error('[did-provider-cheqd]: bulk update: updateOptions.statusListName is required');
|
|
4110
|
+
}
|
|
4111
|
+
if (!args.updateOptions.statusListIndices || !Array.isArray(args.updateOptions.statusListIndices)) {
|
|
4112
|
+
throw new Error(
|
|
4113
|
+
'[did-provider-cheqd]: bulk update: updateOptions.statusListIndices is required and must be an array'
|
|
4114
|
+
);
|
|
4115
|
+
}
|
|
4116
|
+
|
|
4117
|
+
// Construct status list credential URL
|
|
4118
|
+
const statusListCredential = `${DefaultResolverUrl}${args.updateOptions.issuerDid}?resourceName=${args.updateOptions.statusListName}&resourceType=${BitstringStatusListResourceType}`;
|
|
4119
|
+
|
|
4120
|
+
// fetch latest status list to get metadata
|
|
4121
|
+
const statusList = await Cheqd.fetchBitstringStatusList({
|
|
4122
|
+
credentialStatus: {
|
|
4123
|
+
id: statusListCredential,
|
|
4124
|
+
},
|
|
4125
|
+
} as VerifiableCredential);
|
|
4126
|
+
|
|
4127
|
+
// For multi-purpose status lists, determine the appropriate statusPurpose
|
|
4128
|
+
const statusPurpose = this.getStatusPurposeForMultiPurposeList(args.newStatus);
|
|
4129
|
+
|
|
4130
|
+
// construct credentials with proper status entries
|
|
4131
|
+
args.credentials = args.updateOptions.statusListIndices.map((index, i) => ({
|
|
4132
|
+
'@context': [],
|
|
4133
|
+
issuer: args.updateOptions!.issuerDid,
|
|
4134
|
+
credentialSubject: {},
|
|
4135
|
+
credentialStatus: {
|
|
4136
|
+
id: `${statusListCredential}#${index}`,
|
|
4137
|
+
type: 'BitstringStatusListEntry',
|
|
4138
|
+
statusPurpose: statusPurpose,
|
|
4139
|
+
statusListIndex: `${index}`,
|
|
4140
|
+
statusListCredential,
|
|
4141
|
+
statusSize: statusList.metadata.statusSize || 1,
|
|
4142
|
+
statusMessage: statusList.metadata.statusMessages || [],
|
|
4143
|
+
},
|
|
4144
|
+
issuanceDate: '',
|
|
4145
|
+
proof: {},
|
|
4146
|
+
}));
|
|
4147
|
+
}
|
|
4148
|
+
// if jwt credentials, decode them
|
|
4149
|
+
const credentials = await Promise.all(
|
|
4150
|
+
args.credentials!.map(async (credential) =>
|
|
4151
|
+
typeof credential === 'string' ? await Cheqd.decodeCredentialJWT(credential) : credential
|
|
4152
|
+
)
|
|
4153
|
+
);
|
|
4154
|
+
|
|
4155
|
+
// Validate that ALL credentials MUST have credentialStatus
|
|
4156
|
+
const credentialsWithoutStatus = credentials.filter((credential, index) => !credential.credentialStatus);
|
|
4157
|
+
if (credentialsWithoutStatus.length > 0) {
|
|
4158
|
+
throw new Error(
|
|
4159
|
+
`[did-provider-cheqd]: bulk update: ${credentialsWithoutStatus.length} credential(s) missing credentialStatus`
|
|
4160
|
+
);
|
|
4161
|
+
}
|
|
4162
|
+
|
|
4163
|
+
// Validate that all credentials have BitstringStatusListEntry type
|
|
4164
|
+
const invalidStatusTypes = credentials.filter(
|
|
4165
|
+
(credential) => credential.credentialStatus?.type !== 'BitstringStatusListEntry'
|
|
4166
|
+
);
|
|
4167
|
+
if (invalidStatusTypes.length > 0) {
|
|
4168
|
+
throw new Error(
|
|
4169
|
+
`[did-provider-cheqd]: bulk update: ${invalidStatusTypes.length} credential(s) must have BitstringStatusListEntry credentialStatus`
|
|
4170
|
+
);
|
|
4171
|
+
}
|
|
4172
|
+
// validate credentials - case: consistent issuer
|
|
4173
|
+
if (
|
|
4174
|
+
credentials
|
|
4175
|
+
.map((credential) => {
|
|
4176
|
+
return (credential.issuer as { id: string }).id
|
|
4177
|
+
? (credential.issuer as { id: string }).id
|
|
4178
|
+
: (credential.issuer as string);
|
|
4179
|
+
})
|
|
4180
|
+
.filter((value, _, self) => value && value !== self[0]).length > 0
|
|
4181
|
+
) {
|
|
4182
|
+
throw new Error('[did-provider-cheqd]: bulk update: Credentials must be issued by the same issuer');
|
|
4183
|
+
}
|
|
4184
|
+
// validate credentials - case: status list index uniqueness
|
|
4185
|
+
if (
|
|
4186
|
+
credentials
|
|
4187
|
+
.map((credential) => credential.credentialStatus!.statusListIndex)
|
|
4188
|
+
.filter((value, index, self) => self.indexOf(value) !== index).length > 0
|
|
4189
|
+
) {
|
|
4190
|
+
throw new Error('[did-provider-cheqd]: bulk update: Credentials must have unique status list index');
|
|
4191
|
+
}
|
|
4192
|
+
// validate credentials - case: status list credential consistency
|
|
4193
|
+
const statusListCredentialUrl = credentials[0].credentialStatus?.statusListCredential;
|
|
4194
|
+
if (!statusListCredentialUrl) {
|
|
4195
|
+
throw new Error('[did-provider-cheqd]: bulk update: Invalid status list credential URL');
|
|
4196
|
+
}
|
|
4197
|
+
if (
|
|
4198
|
+
!credentials.every(
|
|
4199
|
+
(credential) => credential.credentialStatus?.statusListCredential === statusListCredentialUrl
|
|
4200
|
+
)
|
|
4201
|
+
) {
|
|
4202
|
+
throw new Error('[did-provider-cheqd]: bulk update: Credentials must belong to the same status list');
|
|
4203
|
+
}
|
|
4204
|
+
// validate credentials - case: status list type
|
|
4205
|
+
if (!credentials.every((credential) => credential.credentialStatus?.type === 'BitstringStatusListEntry')) {
|
|
4206
|
+
throw new Error('[did-provider-cheqd]: bulk update: Invalid status list type');
|
|
4207
|
+
}
|
|
4208
|
+
|
|
4209
|
+
// validate args in pairs - case: statusListFile and statusList
|
|
4210
|
+
if (args.options?.statusListFile && args.options?.statusList) {
|
|
4211
|
+
throw new Error('[did-provider-cheqd]: bulk update: statusListFile and statusList are mutually exclusive');
|
|
4212
|
+
}
|
|
4213
|
+
|
|
4214
|
+
// validate args in pairs - case: statusListFile and fetchList
|
|
4215
|
+
if (args.options?.statusListFile && args.options?.fetchList) {
|
|
4216
|
+
throw new Error('[did-provider-cheqd]: bulk update: statusListFile and fetchList are mutually exclusive');
|
|
4217
|
+
}
|
|
4218
|
+
|
|
4219
|
+
// validate args in pairs - case: statusList and fetchList
|
|
4220
|
+
if (args.options?.statusList && args.options?.fetchList) {
|
|
4221
|
+
throw new Error('[did-provider-cheqd]: bulk update: statusList and fetchList are mutually exclusive');
|
|
4222
|
+
}
|
|
4223
|
+
|
|
4224
|
+
// validate args in pairs - case: publish
|
|
4225
|
+
if (args.options?.publish && !args.fetchList && !(args.options?.statusListFile || args.options?.statusList)) {
|
|
4226
|
+
throw new Error(
|
|
4227
|
+
'[did-provider-cheqd]: bulk update: publish requires statusListFile or statusList, if fetchList is disabled'
|
|
4228
|
+
);
|
|
4229
|
+
}
|
|
4230
|
+
// Define issuer and provider
|
|
4231
|
+
const issuer =
|
|
4232
|
+
typeof credentials[0].issuer === 'string'
|
|
4233
|
+
? credentials[0].issuer
|
|
4234
|
+
: (credentials[0].issuer as { id: string }).id;
|
|
4235
|
+
|
|
4236
|
+
this.didProvider = await Cheqd.getProviderFromDidUrl(issuer, this.supportedDidProviders);
|
|
4237
|
+
this.providerId = Cheqd.generateProviderId(issuer);
|
|
4238
|
+
args.dkgOptions ||= this.didProvider.dkgOptions;
|
|
4239
|
+
try {
|
|
4240
|
+
// Fetch published status list
|
|
4241
|
+
const publishedList = await Cheqd.fetchBitstringStatusList(credentials[0]);
|
|
4242
|
+
// Error if encrypted and no decryption key provided
|
|
4243
|
+
if (publishedList.metadata.encrypted && !args?.symmetricKey) {
|
|
4244
|
+
throw new Error(
|
|
4245
|
+
'[did-provider-cheqd]: bulk update: symmetricKey is required for encrypted status list'
|
|
4246
|
+
);
|
|
4247
|
+
}
|
|
4248
|
+
// Fetch and decrypt the current bitstring
|
|
4249
|
+
const currentBitstring = await Cheqd.fetchAndDecryptBitstring(publishedList, {
|
|
4250
|
+
...args.options,
|
|
4251
|
+
topArgs: args,
|
|
4252
|
+
instantiateDkgClient: () => this.didProvider.instantiateDkgThresholdProtocolClient(),
|
|
4253
|
+
});
|
|
4254
|
+
// Parse the bitstring
|
|
4255
|
+
const decompressedBuffer = await DBBitstring.decodeBits({ encoded: currentBitstring });
|
|
4256
|
+
const bitstring = new DBBitstring({ buffer: decompressedBuffer });
|
|
4257
|
+
|
|
4258
|
+
const statusSize = publishedList.metadata.statusSize || Cheqd.DefaultBitstringStatusSize;
|
|
4259
|
+
const newStatusValue = args.newStatus;
|
|
4260
|
+
|
|
4261
|
+
// Process all credentials
|
|
4262
|
+
const results: Array<{
|
|
4263
|
+
updated: boolean;
|
|
4264
|
+
statusValue: BitstringStatusValue;
|
|
4265
|
+
previousStatusValue?: BitstringStatusValue;
|
|
4266
|
+
statusMessage?: string;
|
|
4267
|
+
}> = [];
|
|
4268
|
+
|
|
4269
|
+
let anyUpdated = false;
|
|
4270
|
+
for (const credential of credentials) {
|
|
4271
|
+
const statusIndex = parseInt(credential.credentialStatus!.statusListIndex, 10);
|
|
4272
|
+
const bitPosition = statusIndex * statusSize;
|
|
4273
|
+
|
|
4274
|
+
// Get current status value
|
|
4275
|
+
const currentStatusValue = Cheqd.getBitValue(bitstring, bitPosition, statusSize);
|
|
4276
|
+
// Check if update is needed
|
|
4277
|
+
if (currentStatusValue === newStatusValue) {
|
|
4278
|
+
const statusMessage =
|
|
4279
|
+
publishedList.metadata.statusMessages?.find(
|
|
4280
|
+
(msg) => parseInt(msg.status, 16) === currentStatusValue
|
|
4281
|
+
)?.message || 'unknown';
|
|
4282
|
+
|
|
4283
|
+
results.push({
|
|
4284
|
+
updated: false,
|
|
4285
|
+
statusValue: currentStatusValue as BitstringStatusValue,
|
|
4286
|
+
statusMessage,
|
|
4287
|
+
});
|
|
4288
|
+
} else {
|
|
4289
|
+
// Update the bitstring
|
|
4290
|
+
Cheqd.setBitValue(bitstring, bitPosition, newStatusValue, statusSize);
|
|
4291
|
+
|
|
4292
|
+
const newStatusMessage =
|
|
4293
|
+
publishedList.metadata.statusMessages?.find(
|
|
4294
|
+
(msg) => parseInt(msg.status, 16) === newStatusValue
|
|
4295
|
+
)?.message || 'unknown';
|
|
4296
|
+
results.push({
|
|
4297
|
+
updated: true,
|
|
4298
|
+
statusValue: newStatusValue as BitstringStatusValue,
|
|
4299
|
+
previousStatusValue: currentStatusValue as BitstringStatusValue,
|
|
4300
|
+
statusMessage: newStatusMessage,
|
|
4301
|
+
});
|
|
4302
|
+
|
|
4303
|
+
anyUpdated = true;
|
|
4304
|
+
}
|
|
4305
|
+
}
|
|
4306
|
+
// If no updates needed, return early
|
|
4307
|
+
if (!anyUpdated) {
|
|
4308
|
+
return {
|
|
4309
|
+
updated: results.map((r) => r.updated),
|
|
4310
|
+
statusValues: results.map((r) => r.statusValue),
|
|
4311
|
+
previousStatusValues: results.map((r) => r.previousStatusValue).filter((v) => v !== undefined),
|
|
4312
|
+
statusMessages: results.map((r) => r.statusMessage).filter((m) => m !== undefined),
|
|
4313
|
+
};
|
|
4314
|
+
}
|
|
4315
|
+
// Compress the updated bitstring
|
|
4316
|
+
const compressedBitstring = await bitstring.compressBits();
|
|
4317
|
+
const encodedBitstring = toString(compressedBitstring, 'base64url');
|
|
4318
|
+
|
|
4319
|
+
// Create updated status list credential
|
|
4320
|
+
const updatedStatusListCredential = {
|
|
4321
|
+
...publishedList.bitstringStatusListCredential,
|
|
4322
|
+
credentialSubject: {
|
|
4323
|
+
...publishedList.bitstringStatusListCredential.credentialSubject,
|
|
4324
|
+
encodedList: encodedBitstring,
|
|
4325
|
+
},
|
|
4326
|
+
};
|
|
4327
|
+
|
|
4328
|
+
const updatedStatusList: BitstringStatusList = {
|
|
4329
|
+
bitstringStatusListCredential: updatedStatusListCredential,
|
|
4330
|
+
metadata: publishedList.metadata,
|
|
4331
|
+
};
|
|
4332
|
+
// Write to file if requested
|
|
4333
|
+
if (args?.writeToFile) {
|
|
4334
|
+
await Cheqd.writeFile(compressedBitstring, args.options?.statusListFile);
|
|
4335
|
+
}
|
|
4336
|
+
// Publish if requested
|
|
4337
|
+
const published = args?.publish
|
|
4338
|
+
? await Cheqd.publishUpdatedBitstringStatusList(updatedStatusList, credentials[0], {
|
|
4339
|
+
...args.options,
|
|
4340
|
+
topArgs: args,
|
|
4341
|
+
publishOptions: {
|
|
4342
|
+
context,
|
|
4343
|
+
statusListEncoding: args?.options?.statusListEncoding,
|
|
4344
|
+
statusListValidUntil: args?.options?.statusListValidUntil,
|
|
4345
|
+
resourceId: args?.options?.resourceId,
|
|
4346
|
+
resourceVersion: args?.options?.resourceVersion,
|
|
4347
|
+
resourceAlsoKnownAs: args?.options?.alsoKnownAs,
|
|
4348
|
+
signInputs: args?.options?.signInputs,
|
|
4349
|
+
fee: args?.options?.fee,
|
|
4350
|
+
instantiateDkgClient: () => this.didProvider.instantiateDkgThresholdProtocolClient(),
|
|
4351
|
+
},
|
|
4352
|
+
})
|
|
4353
|
+
: undefined;
|
|
4354
|
+
return {
|
|
4355
|
+
updated: results.map((r) => r.updated),
|
|
4356
|
+
statusValues: results.map((r) => r.statusValue),
|
|
4357
|
+
previousStatusValues: results.map((r) => r.previousStatusValue).filter((v) => v !== undefined),
|
|
4358
|
+
statusMessages: results.map((r) => r.statusMessage).filter((m) => m !== undefined),
|
|
4359
|
+
published: args?.publish ? !!published : undefined,
|
|
4360
|
+
statusList: args?.returnUpdatedStatusList ? updatedStatusList : undefined,
|
|
4361
|
+
symmetricKey: args?.returnSymmetricKey && published?.symmetricKey ? published.symmetricKey : undefined,
|
|
4362
|
+
resourceMetadata: args?.returnStatusListMetadata
|
|
4363
|
+
? await Cheqd.fetchStatusListMetadata(credentials[0])
|
|
4364
|
+
: undefined,
|
|
4365
|
+
};
|
|
4366
|
+
} catch (error) {
|
|
4367
|
+
console.error('[did-provider-cheqd]: bulk update error:', error);
|
|
4368
|
+
return {
|
|
4369
|
+
updated: Array(credentials.length).fill(false),
|
|
4370
|
+
statusValues: Array(credentials.length).fill(BitstringStatusValue.UNKNOWN),
|
|
4371
|
+
statusMessages: Array(credentials.length).fill('update failed'),
|
|
4372
|
+
error: error as IError,
|
|
4373
|
+
};
|
|
4374
|
+
}
|
|
4375
|
+
}
|
|
4376
|
+
|
|
2362
4377
|
private async RevokeBulkCredentialsWithStatusList2021(
|
|
2363
|
-
args:
|
|
4378
|
+
args: ICheqdRevokeBulkCredentialsWithStatusListArgs,
|
|
2364
4379
|
context: IContext
|
|
2365
4380
|
): Promise<BulkRevocationResult> {
|
|
2366
4381
|
// verify credential, if provided and revocation options are not
|
|
@@ -2495,7 +4510,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
2495
4510
|
}
|
|
2496
4511
|
|
|
2497
4512
|
private async SuspendCredentialWithStatusList2021(
|
|
2498
|
-
args:
|
|
4513
|
+
args: ICheqdSuspendCredentialWithStatusListArgs,
|
|
2499
4514
|
context: IContext
|
|
2500
4515
|
): Promise<SuspensionResult> {
|
|
2501
4516
|
// verify credential, if provided and suspension options are not
|
|
@@ -2614,7 +4629,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
2614
4629
|
}
|
|
2615
4630
|
|
|
2616
4631
|
private async SuspendBulkCredentialsWithStatusList2021(
|
|
2617
|
-
args:
|
|
4632
|
+
args: ICheqdSuspendBulkCredentialsWithStatusListArgs,
|
|
2618
4633
|
context: IContext
|
|
2619
4634
|
): Promise<BulkSuspensionResult> {
|
|
2620
4635
|
// verify credential, if provided and suspension options are not
|
|
@@ -2749,7 +4764,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
2749
4764
|
}
|
|
2750
4765
|
|
|
2751
4766
|
private async UnsuspendCredentialWithStatusList2021(
|
|
2752
|
-
args:
|
|
4767
|
+
args: ICheqdUnsuspendCredentialWithStatusListArgs,
|
|
2753
4768
|
context: IContext
|
|
2754
4769
|
): Promise<UnsuspensionResult> {
|
|
2755
4770
|
// verify credential, if provided and unsuspension options are not
|
|
@@ -2868,7 +4883,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
2868
4883
|
}
|
|
2869
4884
|
|
|
2870
4885
|
private async UnsuspendBulkCredentialsWithStatusList2021(
|
|
2871
|
-
args:
|
|
4886
|
+
args: ICheqdUnsuspendBulkCredentialsWithStatusListArgs,
|
|
2872
4887
|
context: IContext
|
|
2873
4888
|
): Promise<BulkUnsuspensionResult> {
|
|
2874
4889
|
// verify credential, if provided and unsuspension options are not
|
|
@@ -3343,7 +5358,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
3343
5358
|
|
|
3344
5359
|
static async revokeCredential(
|
|
3345
5360
|
credential: VerifiableCredential,
|
|
3346
|
-
options?:
|
|
5361
|
+
options?: ICheqdStatusListOptions
|
|
3347
5362
|
): Promise<RevocationResult> {
|
|
3348
5363
|
try {
|
|
3349
5364
|
// validate status purpose
|
|
@@ -3369,7 +5384,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
3369
5384
|
: toString(
|
|
3370
5385
|
fromString(
|
|
3371
5386
|
publishedList.StatusList2021.encodedList,
|
|
3372
|
-
publishedList.metadata.encoding as
|
|
5387
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
3373
5388
|
),
|
|
3374
5389
|
'base64url'
|
|
3375
5390
|
);
|
|
@@ -3418,7 +5433,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
3418
5433
|
: toString(
|
|
3419
5434
|
fromString(
|
|
3420
5435
|
publishedList.StatusList2021.encodedList,
|
|
3421
|
-
publishedList.metadata.encoding as
|
|
5436
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
3422
5437
|
),
|
|
3423
5438
|
'base64url'
|
|
3424
5439
|
);
|
|
@@ -3497,7 +5512,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
3497
5512
|
const bitstring = (await statusList.encode()) as Bitstring;
|
|
3498
5513
|
|
|
3499
5514
|
// cast top-level args
|
|
3500
|
-
const topArgs = options?.topArgs as
|
|
5515
|
+
const topArgs = options?.topArgs as ICheqdRevokeCredentialWithStatusListArgs;
|
|
3501
5516
|
|
|
3502
5517
|
// write status list 2021 to file, if provided
|
|
3503
5518
|
if (topArgs?.writeToFile) {
|
|
@@ -3508,7 +5523,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
3508
5523
|
const published = topArgs?.publish
|
|
3509
5524
|
? await (async function () {
|
|
3510
5525
|
// fetch status list 2021 metadata
|
|
3511
|
-
const statusListMetadata = await Cheqd.
|
|
5526
|
+
const statusListMetadata = await Cheqd.fetchStatusListMetadata(credential);
|
|
3512
5527
|
|
|
3513
5528
|
// publish status list 2021 as new version
|
|
3514
5529
|
const scoped = topArgs.publishEncrypted
|
|
@@ -3516,7 +5531,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
3516
5531
|
// validate encoding, if provided
|
|
3517
5532
|
if (
|
|
3518
5533
|
options?.publishOptions?.statusListEncoding &&
|
|
3519
|
-
!Object.values(
|
|
5534
|
+
!Object.values(DefaultStatusListEncodings).includes(
|
|
3520
5535
|
options?.publishOptions?.statusListEncoding
|
|
3521
5536
|
)
|
|
3522
5537
|
) {
|
|
@@ -3713,7 +5728,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
3713
5728
|
encrypted: true,
|
|
3714
5729
|
encoding:
|
|
3715
5730
|
(options?.publishOptions?.statusListEncoding as
|
|
3716
|
-
|
|
|
5731
|
+
| DefaultStatusListEncoding
|
|
3717
5732
|
| undefined) || publishedList.metadata.encoding,
|
|
3718
5733
|
statusListHash:
|
|
3719
5734
|
symmetricEncryptionStringHash === thresholdEncryptionStringHash
|
|
@@ -3746,7 +5761,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
3746
5761
|
// validate encoding, if provided
|
|
3747
5762
|
if (
|
|
3748
5763
|
options?.publishOptions?.statusListEncoding &&
|
|
3749
|
-
!Object.values(
|
|
5764
|
+
!Object.values(DefaultStatusListEncodings).includes(
|
|
3750
5765
|
options?.publishOptions?.statusListEncoding
|
|
3751
5766
|
)
|
|
3752
5767
|
) {
|
|
@@ -3795,7 +5810,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
3795
5810
|
: toString(
|
|
3796
5811
|
fromString(bitstring, 'base64url'),
|
|
3797
5812
|
options!.publishOptions
|
|
3798
|
-
.statusListEncoding as
|
|
5813
|
+
.statusListEncoding as DefaultStatusListEncoding
|
|
3799
5814
|
),
|
|
3800
5815
|
validFrom: publishedList.StatusList2021.validFrom,
|
|
3801
5816
|
validUntil:
|
|
@@ -3806,7 +5821,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
3806
5821
|
type: publishedList.metadata.type,
|
|
3807
5822
|
encoding:
|
|
3808
5823
|
(options?.publishOptions?.statusListEncoding as
|
|
3809
|
-
|
|
|
5824
|
+
| DefaultStatusListEncoding
|
|
3810
5825
|
| undefined) || publishedList.metadata.encoding,
|
|
3811
5826
|
encrypted: false,
|
|
3812
5827
|
},
|
|
@@ -3842,7 +5857,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
3842
5857
|
? toString((published?.[1] as { symmetricKey: Uint8Array })?.symmetricKey, 'hex')
|
|
3843
5858
|
: undefined,
|
|
3844
5859
|
resourceMetadata: topArgs?.returnStatusListMetadata
|
|
3845
|
-
? await Cheqd.
|
|
5860
|
+
? await Cheqd.fetchStatusListMetadata(credential)
|
|
3846
5861
|
: undefined,
|
|
3847
5862
|
} satisfies RevocationResult;
|
|
3848
5863
|
} catch (error) {
|
|
@@ -3855,7 +5870,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
3855
5870
|
|
|
3856
5871
|
static async revokeCredentials(
|
|
3857
5872
|
credentials: VerifiableCredential[],
|
|
3858
|
-
options?:
|
|
5873
|
+
options?: ICheqdStatusListOptions
|
|
3859
5874
|
): Promise<BulkRevocationResult> {
|
|
3860
5875
|
// validate credentials - case: empty
|
|
3861
5876
|
if (!credentials.length || credentials.length === 0)
|
|
@@ -3934,7 +5949,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
3934
5949
|
: toString(
|
|
3935
5950
|
fromString(
|
|
3936
5951
|
publishedList.StatusList2021.encodedList,
|
|
3937
|
-
publishedList.metadata.encoding as
|
|
5952
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
3938
5953
|
),
|
|
3939
5954
|
'base64url'
|
|
3940
5955
|
);
|
|
@@ -3983,7 +5998,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
3983
5998
|
: toString(
|
|
3984
5999
|
fromString(
|
|
3985
6000
|
publishedList.StatusList2021.encodedList,
|
|
3986
|
-
publishedList.metadata.encoding as
|
|
6001
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
3987
6002
|
),
|
|
3988
6003
|
'base64url'
|
|
3989
6004
|
);
|
|
@@ -4086,7 +6101,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4086
6101
|
const bitstring = (await statusList.encode()) as Bitstring;
|
|
4087
6102
|
|
|
4088
6103
|
// cast top-level args
|
|
4089
|
-
const topArgs = options?.topArgs as
|
|
6104
|
+
const topArgs = options?.topArgs as ICheqdRevokeCredentialWithStatusListArgs;
|
|
4090
6105
|
|
|
4091
6106
|
// write status list 2021 to file, if provided
|
|
4092
6107
|
if (topArgs?.writeToFile) {
|
|
@@ -4097,7 +6112,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4097
6112
|
const published = topArgs?.publish
|
|
4098
6113
|
? await (async function () {
|
|
4099
6114
|
// fetch status list 2021 metadata
|
|
4100
|
-
const statusListMetadata = await Cheqd.
|
|
6115
|
+
const statusListMetadata = await Cheqd.fetchStatusListMetadata(credentials[0]);
|
|
4101
6116
|
|
|
4102
6117
|
// publish status list 2021 as new version
|
|
4103
6118
|
const scoped = topArgs.publishEncrypted
|
|
@@ -4105,7 +6120,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4105
6120
|
// validate encoding, if provided
|
|
4106
6121
|
if (
|
|
4107
6122
|
options?.publishOptions?.statusListEncoding &&
|
|
4108
|
-
!Object.values(
|
|
6123
|
+
!Object.values(DefaultStatusListEncodings).includes(
|
|
4109
6124
|
options?.publishOptions?.statusListEncoding
|
|
4110
6125
|
)
|
|
4111
6126
|
) {
|
|
@@ -4302,7 +6317,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4302
6317
|
encrypted: true,
|
|
4303
6318
|
encoding:
|
|
4304
6319
|
(options?.publishOptions?.statusListEncoding as
|
|
4305
|
-
|
|
|
6320
|
+
| DefaultStatusListEncoding
|
|
4306
6321
|
| undefined) || publishedList.metadata.encoding,
|
|
4307
6322
|
statusListHash:
|
|
4308
6323
|
symmetricEncryptionStringHash === thresholdEncryptionStringHash
|
|
@@ -4335,7 +6350,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4335
6350
|
// validate encoding, if provided
|
|
4336
6351
|
if (
|
|
4337
6352
|
options?.publishOptions?.statusListEncoding &&
|
|
4338
|
-
!Object.values(
|
|
6353
|
+
!Object.values(DefaultStatusListEncodings).includes(
|
|
4339
6354
|
options?.publishOptions?.statusListEncoding
|
|
4340
6355
|
)
|
|
4341
6356
|
) {
|
|
@@ -4384,7 +6399,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4384
6399
|
: toString(
|
|
4385
6400
|
fromString(bitstring, 'base64url'),
|
|
4386
6401
|
options!.publishOptions
|
|
4387
|
-
.statusListEncoding as
|
|
6402
|
+
.statusListEncoding as DefaultStatusListEncoding
|
|
4388
6403
|
),
|
|
4389
6404
|
validFrom: publishedList.StatusList2021.validFrom,
|
|
4390
6405
|
validUntil:
|
|
@@ -4395,7 +6410,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4395
6410
|
type: publishedList.metadata.type,
|
|
4396
6411
|
encoding:
|
|
4397
6412
|
(options?.publishOptions?.statusListEncoding as
|
|
4398
|
-
|
|
|
6413
|
+
| DefaultStatusListEncoding
|
|
4399
6414
|
| undefined) || publishedList.metadata.encoding,
|
|
4400
6415
|
encrypted: false,
|
|
4401
6416
|
},
|
|
@@ -4431,7 +6446,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4431
6446
|
? toString((published?.[1] as { symmetricKey: Uint8Array })?.symmetricKey, 'hex')
|
|
4432
6447
|
: undefined,
|
|
4433
6448
|
resourceMetadata: topArgs?.returnStatusListMetadata
|
|
4434
|
-
? await Cheqd.
|
|
6449
|
+
? await Cheqd.fetchStatusListMetadata(credentials[0])
|
|
4435
6450
|
: undefined,
|
|
4436
6451
|
} satisfies BulkRevocationResult;
|
|
4437
6452
|
} catch (error) {
|
|
@@ -4444,7 +6459,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4444
6459
|
|
|
4445
6460
|
static async suspendCredential(
|
|
4446
6461
|
credential: VerifiableCredential,
|
|
4447
|
-
options?:
|
|
6462
|
+
options?: ICheqdStatusListOptions
|
|
4448
6463
|
): Promise<SuspensionResult> {
|
|
4449
6464
|
try {
|
|
4450
6465
|
// validate status purpose
|
|
@@ -4470,7 +6485,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4470
6485
|
: toString(
|
|
4471
6486
|
fromString(
|
|
4472
6487
|
publishedList.StatusList2021.encodedList,
|
|
4473
|
-
publishedList.metadata.encoding as
|
|
6488
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
4474
6489
|
),
|
|
4475
6490
|
'base64url'
|
|
4476
6491
|
);
|
|
@@ -4519,7 +6534,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4519
6534
|
: toString(
|
|
4520
6535
|
fromString(
|
|
4521
6536
|
publishedList.StatusList2021.encodedList,
|
|
4522
|
-
publishedList.metadata.encoding as
|
|
6537
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
4523
6538
|
),
|
|
4524
6539
|
'base64url'
|
|
4525
6540
|
);
|
|
@@ -4599,7 +6614,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4599
6614
|
const bitstring = (await statusList.encode()) as Bitstring;
|
|
4600
6615
|
|
|
4601
6616
|
// cast top-level args
|
|
4602
|
-
const topArgs = options?.topArgs as
|
|
6617
|
+
const topArgs = options?.topArgs as ICheqdSuspendCredentialWithStatusListArgs;
|
|
4603
6618
|
|
|
4604
6619
|
// write status list 2021 to file, if provided
|
|
4605
6620
|
if (topArgs?.writeToFile) {
|
|
@@ -4610,7 +6625,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4610
6625
|
const published = topArgs?.publish
|
|
4611
6626
|
? await (async function () {
|
|
4612
6627
|
// fetch status list 2021 metadata
|
|
4613
|
-
const statusListMetadata = await Cheqd.
|
|
6628
|
+
const statusListMetadata = await Cheqd.fetchStatusListMetadata(credential);
|
|
4614
6629
|
|
|
4615
6630
|
// publish status list 2021 as new version
|
|
4616
6631
|
const scoped = topArgs.publishEncrypted
|
|
@@ -4618,7 +6633,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4618
6633
|
// validate encoding, if provided
|
|
4619
6634
|
if (
|
|
4620
6635
|
options?.publishOptions?.statusListEncoding &&
|
|
4621
|
-
!Object.values(
|
|
6636
|
+
!Object.values(DefaultStatusListEncodings).includes(
|
|
4622
6637
|
options?.publishOptions?.statusListEncoding
|
|
4623
6638
|
)
|
|
4624
6639
|
) {
|
|
@@ -4815,7 +6830,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4815
6830
|
encrypted: true,
|
|
4816
6831
|
encoding:
|
|
4817
6832
|
(options?.publishOptions?.statusListEncoding as
|
|
4818
|
-
|
|
|
6833
|
+
| DefaultStatusListEncoding
|
|
4819
6834
|
| undefined) || publishedList.metadata.encoding,
|
|
4820
6835
|
statusListHash:
|
|
4821
6836
|
symmetricEncryptionStringHash === thresholdEncryptionStringHash
|
|
@@ -4848,7 +6863,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4848
6863
|
// validate encoding, if provided
|
|
4849
6864
|
if (
|
|
4850
6865
|
options?.publishOptions?.statusListEncoding &&
|
|
4851
|
-
!Object.values(
|
|
6866
|
+
!Object.values(DefaultStatusListEncodings).includes(
|
|
4852
6867
|
options?.publishOptions?.statusListEncoding
|
|
4853
6868
|
)
|
|
4854
6869
|
) {
|
|
@@ -4897,7 +6912,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4897
6912
|
: toString(
|
|
4898
6913
|
fromString(bitstring, 'base64url'),
|
|
4899
6914
|
options!.publishOptions
|
|
4900
|
-
.statusListEncoding as
|
|
6915
|
+
.statusListEncoding as DefaultStatusListEncoding
|
|
4901
6916
|
),
|
|
4902
6917
|
validFrom: publishedList.StatusList2021.validFrom,
|
|
4903
6918
|
validUntil:
|
|
@@ -4908,7 +6923,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4908
6923
|
type: publishedList.metadata.type,
|
|
4909
6924
|
encoding:
|
|
4910
6925
|
(options?.publishOptions?.statusListEncoding as
|
|
4911
|
-
|
|
|
6926
|
+
| DefaultStatusListEncoding
|
|
4912
6927
|
| undefined) || publishedList.metadata.encoding,
|
|
4913
6928
|
encrypted: false,
|
|
4914
6929
|
},
|
|
@@ -4944,7 +6959,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4944
6959
|
? toString((published?.[1] as { symmetricKey: Uint8Array })?.symmetricKey, 'hex')
|
|
4945
6960
|
: undefined,
|
|
4946
6961
|
resourceMetadata: topArgs?.returnStatusListMetadata
|
|
4947
|
-
? await Cheqd.
|
|
6962
|
+
? await Cheqd.fetchStatusListMetadata(credential)
|
|
4948
6963
|
: undefined,
|
|
4949
6964
|
} satisfies SuspensionResult;
|
|
4950
6965
|
} catch (error) {
|
|
@@ -4957,7 +6972,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
4957
6972
|
|
|
4958
6973
|
static async suspendCredentials(
|
|
4959
6974
|
credentials: VerifiableCredential[],
|
|
4960
|
-
options?:
|
|
6975
|
+
options?: ICheqdStatusListOptions
|
|
4961
6976
|
): Promise<BulkSuspensionResult> {
|
|
4962
6977
|
// validate credentials - case: empty
|
|
4963
6978
|
if (!credentials.length || credentials.length === 0)
|
|
@@ -5036,7 +7051,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5036
7051
|
: toString(
|
|
5037
7052
|
fromString(
|
|
5038
7053
|
publishedList.StatusList2021.encodedList,
|
|
5039
|
-
publishedList.metadata.encoding as
|
|
7054
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
5040
7055
|
),
|
|
5041
7056
|
'base64url'
|
|
5042
7057
|
);
|
|
@@ -5085,7 +7100,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5085
7100
|
: toString(
|
|
5086
7101
|
fromString(
|
|
5087
7102
|
publishedList.StatusList2021.encodedList,
|
|
5088
|
-
publishedList.metadata.encoding as
|
|
7103
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
5089
7104
|
),
|
|
5090
7105
|
'base64url'
|
|
5091
7106
|
);
|
|
@@ -5188,7 +7203,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5188
7203
|
const bitstring = (await statusList.encode()) as Bitstring;
|
|
5189
7204
|
|
|
5190
7205
|
// cast top-level args
|
|
5191
|
-
const topArgs = options?.topArgs as
|
|
7206
|
+
const topArgs = options?.topArgs as ICheqdRevokeCredentialWithStatusListArgs;
|
|
5192
7207
|
|
|
5193
7208
|
// write status list 2021 to file, if provided
|
|
5194
7209
|
if (topArgs?.writeToFile) {
|
|
@@ -5199,7 +7214,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5199
7214
|
const published = topArgs?.publish
|
|
5200
7215
|
? await (async function () {
|
|
5201
7216
|
// fetch status list 2021 metadata
|
|
5202
|
-
const statusListMetadata = await Cheqd.
|
|
7217
|
+
const statusListMetadata = await Cheqd.fetchStatusListMetadata(credentials[0]);
|
|
5203
7218
|
|
|
5204
7219
|
// publish status list 2021 as new version
|
|
5205
7220
|
const scoped = topArgs.publishEncrypted
|
|
@@ -5207,7 +7222,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5207
7222
|
// validate encoding, if provided
|
|
5208
7223
|
if (
|
|
5209
7224
|
options?.publishOptions?.statusListEncoding &&
|
|
5210
|
-
!Object.values(
|
|
7225
|
+
!Object.values(DefaultStatusListEncodings).includes(
|
|
5211
7226
|
options?.publishOptions?.statusListEncoding
|
|
5212
7227
|
)
|
|
5213
7228
|
) {
|
|
@@ -5404,7 +7419,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5404
7419
|
encrypted: true,
|
|
5405
7420
|
encoding:
|
|
5406
7421
|
(options?.publishOptions?.statusListEncoding as
|
|
5407
|
-
|
|
|
7422
|
+
| DefaultStatusListEncoding
|
|
5408
7423
|
| undefined) || publishedList.metadata.encoding,
|
|
5409
7424
|
statusListHash:
|
|
5410
7425
|
symmetricEncryptionStringHash === thresholdEncryptionStringHash
|
|
@@ -5437,7 +7452,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5437
7452
|
// validate encoding, if provided
|
|
5438
7453
|
if (
|
|
5439
7454
|
options?.publishOptions?.statusListEncoding &&
|
|
5440
|
-
!Object.values(
|
|
7455
|
+
!Object.values(DefaultStatusListEncodings).includes(
|
|
5441
7456
|
options?.publishOptions?.statusListEncoding
|
|
5442
7457
|
)
|
|
5443
7458
|
) {
|
|
@@ -5486,7 +7501,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5486
7501
|
: toString(
|
|
5487
7502
|
fromString(bitstring, 'base64url'),
|
|
5488
7503
|
options!.publishOptions
|
|
5489
|
-
.statusListEncoding as
|
|
7504
|
+
.statusListEncoding as DefaultStatusListEncoding
|
|
5490
7505
|
),
|
|
5491
7506
|
validFrom: publishedList.StatusList2021.validFrom,
|
|
5492
7507
|
validUntil:
|
|
@@ -5497,7 +7512,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5497
7512
|
type: publishedList.metadata.type,
|
|
5498
7513
|
encoding:
|
|
5499
7514
|
(options?.publishOptions?.statusListEncoding as
|
|
5500
|
-
|
|
|
7515
|
+
| DefaultStatusListEncoding
|
|
5501
7516
|
| undefined) || publishedList.metadata.encoding,
|
|
5502
7517
|
encrypted: false,
|
|
5503
7518
|
},
|
|
@@ -5533,7 +7548,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5533
7548
|
? toString((published?.[1] as { symmetricKey: Uint8Array })?.symmetricKey, 'hex')
|
|
5534
7549
|
: undefined,
|
|
5535
7550
|
resourceMetadata: topArgs?.returnStatusListMetadata
|
|
5536
|
-
? await Cheqd.
|
|
7551
|
+
? await Cheqd.fetchStatusListMetadata(credentials[0])
|
|
5537
7552
|
: undefined,
|
|
5538
7553
|
} satisfies BulkSuspensionResult;
|
|
5539
7554
|
} catch (error) {
|
|
@@ -5545,7 +7560,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5545
7560
|
|
|
5546
7561
|
static async unsuspendCredential(
|
|
5547
7562
|
credential: VerifiableCredential,
|
|
5548
|
-
options?:
|
|
7563
|
+
options?: ICheqdStatusListOptions
|
|
5549
7564
|
): Promise<UnsuspensionResult> {
|
|
5550
7565
|
try {
|
|
5551
7566
|
// validate status purpose
|
|
@@ -5571,7 +7586,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5571
7586
|
: toString(
|
|
5572
7587
|
fromString(
|
|
5573
7588
|
publishedList.StatusList2021.encodedList,
|
|
5574
|
-
publishedList.metadata.encoding as
|
|
7589
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
5575
7590
|
),
|
|
5576
7591
|
'base64url'
|
|
5577
7592
|
);
|
|
@@ -5620,7 +7635,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5620
7635
|
: toString(
|
|
5621
7636
|
fromString(
|
|
5622
7637
|
publishedList.StatusList2021.encodedList,
|
|
5623
|
-
publishedList.metadata.encoding as
|
|
7638
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
5624
7639
|
),
|
|
5625
7640
|
'base64url'
|
|
5626
7641
|
);
|
|
@@ -5700,7 +7715,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5700
7715
|
const bitstring = (await statusList.encode()) as Bitstring;
|
|
5701
7716
|
|
|
5702
7717
|
// cast top-level args
|
|
5703
|
-
const topArgs = options?.topArgs as
|
|
7718
|
+
const topArgs = options?.topArgs as ICheqdSuspendCredentialWithStatusListArgs;
|
|
5704
7719
|
|
|
5705
7720
|
// write status list 2021 to file, if provided
|
|
5706
7721
|
if (topArgs?.writeToFile) {
|
|
@@ -5711,7 +7726,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5711
7726
|
const published = topArgs?.publish
|
|
5712
7727
|
? await (async function () {
|
|
5713
7728
|
// fetch status list 2021 metadata
|
|
5714
|
-
const statusListMetadata = await Cheqd.
|
|
7729
|
+
const statusListMetadata = await Cheqd.fetchStatusListMetadata(credential);
|
|
5715
7730
|
|
|
5716
7731
|
// publish status list 2021 as new version
|
|
5717
7732
|
const scoped = topArgs.publishEncrypted
|
|
@@ -5719,7 +7734,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5719
7734
|
// validate encoding, if provided
|
|
5720
7735
|
if (
|
|
5721
7736
|
options?.publishOptions?.statusListEncoding &&
|
|
5722
|
-
!Object.values(
|
|
7737
|
+
!Object.values(DefaultStatusListEncodings).includes(
|
|
5723
7738
|
options?.publishOptions?.statusListEncoding
|
|
5724
7739
|
)
|
|
5725
7740
|
) {
|
|
@@ -5916,7 +7931,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5916
7931
|
encrypted: true,
|
|
5917
7932
|
encoding:
|
|
5918
7933
|
(options?.publishOptions?.statusListEncoding as
|
|
5919
|
-
|
|
|
7934
|
+
| DefaultStatusListEncoding
|
|
5920
7935
|
| undefined) || publishedList.metadata.encoding,
|
|
5921
7936
|
statusListHash:
|
|
5922
7937
|
symmetricEncryptionStringHash === thresholdEncryptionStringHash
|
|
@@ -5949,7 +7964,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5949
7964
|
// validate encoding, if provided
|
|
5950
7965
|
if (
|
|
5951
7966
|
options?.publishOptions?.statusListEncoding &&
|
|
5952
|
-
!Object.values(
|
|
7967
|
+
!Object.values(DefaultStatusListEncodings).includes(
|
|
5953
7968
|
options?.publishOptions?.statusListEncoding
|
|
5954
7969
|
)
|
|
5955
7970
|
) {
|
|
@@ -5998,7 +8013,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
5998
8013
|
: toString(
|
|
5999
8014
|
fromString(bitstring, 'base64url'),
|
|
6000
8015
|
options!.publishOptions
|
|
6001
|
-
.statusListEncoding as
|
|
8016
|
+
.statusListEncoding as DefaultStatusListEncoding
|
|
6002
8017
|
),
|
|
6003
8018
|
validFrom: publishedList.StatusList2021.validFrom,
|
|
6004
8019
|
validUntil:
|
|
@@ -6009,7 +8024,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6009
8024
|
type: publishedList.metadata.type,
|
|
6010
8025
|
encoding:
|
|
6011
8026
|
(options?.publishOptions?.statusListEncoding as
|
|
6012
|
-
|
|
|
8027
|
+
| DefaultStatusListEncoding
|
|
6013
8028
|
| undefined) || publishedList.metadata.encoding,
|
|
6014
8029
|
encrypted: false,
|
|
6015
8030
|
},
|
|
@@ -6045,7 +8060,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6045
8060
|
? toString((published?.[1] as { symmetricKey: Uint8Array })?.symmetricKey, 'hex')
|
|
6046
8061
|
: undefined,
|
|
6047
8062
|
resourceMetadata: topArgs?.returnStatusListMetadata
|
|
6048
|
-
? await Cheqd.
|
|
8063
|
+
? await Cheqd.fetchStatusListMetadata(credential)
|
|
6049
8064
|
: undefined,
|
|
6050
8065
|
} satisfies UnsuspensionResult;
|
|
6051
8066
|
} catch (error) {
|
|
@@ -6058,7 +8073,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6058
8073
|
|
|
6059
8074
|
static async unsuspendCredentials(
|
|
6060
8075
|
credentials: VerifiableCredential[],
|
|
6061
|
-
options?:
|
|
8076
|
+
options?: ICheqdStatusListOptions
|
|
6062
8077
|
): Promise<BulkUnsuspensionResult> {
|
|
6063
8078
|
// validate credentials - case: empty
|
|
6064
8079
|
if (!credentials.length || credentials.length === 0)
|
|
@@ -6137,7 +8152,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6137
8152
|
: toString(
|
|
6138
8153
|
fromString(
|
|
6139
8154
|
publishedList.StatusList2021.encodedList,
|
|
6140
|
-
publishedList.metadata.encoding as
|
|
8155
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
6141
8156
|
),
|
|
6142
8157
|
'base64url'
|
|
6143
8158
|
);
|
|
@@ -6186,7 +8201,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6186
8201
|
: toString(
|
|
6187
8202
|
fromString(
|
|
6188
8203
|
publishedList.StatusList2021.encodedList,
|
|
6189
|
-
publishedList.metadata.encoding as
|
|
8204
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
6190
8205
|
),
|
|
6191
8206
|
'base64url'
|
|
6192
8207
|
);
|
|
@@ -6289,7 +8304,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6289
8304
|
const bitstring = (await statusList.encode()) as Bitstring;
|
|
6290
8305
|
|
|
6291
8306
|
// cast top-level args
|
|
6292
|
-
const topArgs = options?.topArgs as
|
|
8307
|
+
const topArgs = options?.topArgs as ICheqdRevokeCredentialWithStatusListArgs;
|
|
6293
8308
|
|
|
6294
8309
|
// write status list 2021 to file, if provided
|
|
6295
8310
|
if (topArgs?.writeToFile) {
|
|
@@ -6300,7 +8315,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6300
8315
|
const published = topArgs?.publish
|
|
6301
8316
|
? await (async function () {
|
|
6302
8317
|
// fetch status list 2021 metadata
|
|
6303
|
-
const statusListMetadata = await Cheqd.
|
|
8318
|
+
const statusListMetadata = await Cheqd.fetchStatusListMetadata(credentials[0]);
|
|
6304
8319
|
|
|
6305
8320
|
// publish status list 2021 as new version
|
|
6306
8321
|
const scoped = topArgs.publishEncrypted
|
|
@@ -6308,7 +8323,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6308
8323
|
// validate encoding, if provided
|
|
6309
8324
|
if (
|
|
6310
8325
|
options?.publishOptions?.statusListEncoding &&
|
|
6311
|
-
!Object.values(
|
|
8326
|
+
!Object.values(DefaultStatusListEncodings).includes(
|
|
6312
8327
|
options?.publishOptions?.statusListEncoding
|
|
6313
8328
|
)
|
|
6314
8329
|
) {
|
|
@@ -6505,7 +8520,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6505
8520
|
encrypted: true,
|
|
6506
8521
|
encoding:
|
|
6507
8522
|
(options?.publishOptions?.statusListEncoding as
|
|
6508
|
-
|
|
|
8523
|
+
| DefaultStatusListEncoding
|
|
6509
8524
|
| undefined) || publishedList.metadata.encoding,
|
|
6510
8525
|
statusListHash:
|
|
6511
8526
|
symmetricEncryptionStringHash === thresholdEncryptionStringHash
|
|
@@ -6538,7 +8553,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6538
8553
|
// validate encoding, if provided
|
|
6539
8554
|
if (
|
|
6540
8555
|
options?.publishOptions?.statusListEncoding &&
|
|
6541
|
-
!Object.values(
|
|
8556
|
+
!Object.values(DefaultStatusListEncodings).includes(
|
|
6542
8557
|
options?.publishOptions?.statusListEncoding
|
|
6543
8558
|
)
|
|
6544
8559
|
) {
|
|
@@ -6587,7 +8602,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6587
8602
|
: toString(
|
|
6588
8603
|
fromString(bitstring, 'base64url'),
|
|
6589
8604
|
options!.publishOptions
|
|
6590
|
-
.statusListEncoding as
|
|
8605
|
+
.statusListEncoding as DefaultStatusListEncoding
|
|
6591
8606
|
),
|
|
6592
8607
|
validFrom: publishedList.StatusList2021.validFrom,
|
|
6593
8608
|
validUntil:
|
|
@@ -6598,7 +8613,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6598
8613
|
type: publishedList.metadata.type,
|
|
6599
8614
|
encoding:
|
|
6600
8615
|
(options?.publishOptions?.statusListEncoding as
|
|
6601
|
-
|
|
|
8616
|
+
| DefaultStatusListEncoding
|
|
6602
8617
|
| undefined) || publishedList.metadata.encoding,
|
|
6603
8618
|
encrypted: false,
|
|
6604
8619
|
},
|
|
@@ -6636,7 +8651,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6636
8651
|
? toString((published?.[1] as { symmetricKey: Uint8Array })?.symmetricKey, 'hex')
|
|
6637
8652
|
: undefined,
|
|
6638
8653
|
resourceMetadata: topArgs?.returnStatusListMetadata
|
|
6639
|
-
? await Cheqd.
|
|
8654
|
+
? await Cheqd.fetchStatusListMetadata(credentials[0])
|
|
6640
8655
|
: undefined,
|
|
6641
8656
|
} satisfies BulkUnsuspensionResult;
|
|
6642
8657
|
} catch (error) {
|
|
@@ -6649,7 +8664,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6649
8664
|
|
|
6650
8665
|
static async checkRevoked(
|
|
6651
8666
|
credential: VerifiableCredential,
|
|
6652
|
-
options:
|
|
8667
|
+
options: ICheqdStatusListOptions = { fetchList: true }
|
|
6653
8668
|
): Promise<boolean> {
|
|
6654
8669
|
// validate status purpose
|
|
6655
8670
|
if (credential.credentialStatus?.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.revocation) {
|
|
@@ -6684,7 +8699,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6684
8699
|
: toString(
|
|
6685
8700
|
fromString(
|
|
6686
8701
|
publishedList.StatusList2021.encodedList,
|
|
6687
|
-
publishedList.metadata.encoding as
|
|
8702
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
6688
8703
|
),
|
|
6689
8704
|
'base64url'
|
|
6690
8705
|
);
|
|
@@ -6742,7 +8757,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6742
8757
|
: toString(
|
|
6743
8758
|
fromString(
|
|
6744
8759
|
publishedList.StatusList2021.encodedList,
|
|
6745
|
-
publishedList.metadata.encoding as
|
|
8760
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
6746
8761
|
),
|
|
6747
8762
|
'base64url'
|
|
6748
8763
|
);
|
|
@@ -6813,7 +8828,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6813
8828
|
publishedList.metadata.encoding === 'base64url'
|
|
6814
8829
|
? statusList2021
|
|
6815
8830
|
: toString(
|
|
6816
|
-
fromString(statusList2021, publishedList.metadata.encoding as
|
|
8831
|
+
fromString(statusList2021, publishedList.metadata.encoding as DefaultStatusListEncoding),
|
|
6817
8832
|
'base64url'
|
|
6818
8833
|
);
|
|
6819
8834
|
|
|
@@ -6826,7 +8841,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6826
8841
|
|
|
6827
8842
|
static async checkSuspended(
|
|
6828
8843
|
credential: VerifiableCredential,
|
|
6829
|
-
options:
|
|
8844
|
+
options: ICheqdStatusListOptions = { fetchList: true }
|
|
6830
8845
|
): Promise<boolean> {
|
|
6831
8846
|
// validate status purpose
|
|
6832
8847
|
if (credential.credentialStatus?.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.suspension) {
|
|
@@ -6861,7 +8876,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6861
8876
|
: toString(
|
|
6862
8877
|
fromString(
|
|
6863
8878
|
publishedList.StatusList2021.encodedList,
|
|
6864
|
-
publishedList.metadata.encoding as
|
|
8879
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
6865
8880
|
),
|
|
6866
8881
|
'base64url'
|
|
6867
8882
|
);
|
|
@@ -6915,7 +8930,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6915
8930
|
: toString(
|
|
6916
8931
|
fromString(
|
|
6917
8932
|
publishedList.StatusList2021.encodedList,
|
|
6918
|
-
publishedList.metadata.encoding as
|
|
8933
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
6919
8934
|
),
|
|
6920
8935
|
'base64url'
|
|
6921
8936
|
);
|
|
@@ -6991,7 +9006,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
6991
9006
|
private static async checkRevokedNonMigrated(
|
|
6992
9007
|
credential: VerifiableCredential,
|
|
6993
9008
|
associatedStatusList?: StatusList2021RevocationNonMigrated,
|
|
6994
|
-
options:
|
|
9009
|
+
options: ICheqdStatusListOptions = { fetchList: true }
|
|
6995
9010
|
): Promise<boolean> {
|
|
6996
9011
|
// validate status purpose
|
|
6997
9012
|
if (credential.credentialStatus?.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.revocation) {
|
|
@@ -7019,7 +9034,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
7019
9034
|
: toString(
|
|
7020
9035
|
fromString(
|
|
7021
9036
|
publishedList.StatusList2021.encodedList,
|
|
7022
|
-
publishedList.metadata.encoding as
|
|
9037
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
7023
9038
|
),
|
|
7024
9039
|
'base64url'
|
|
7025
9040
|
);
|
|
@@ -7072,7 +9087,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
7072
9087
|
: toString(
|
|
7073
9088
|
fromString(
|
|
7074
9089
|
publishedList.StatusList2021.encodedList,
|
|
7075
|
-
publishedList.metadata.encoding as
|
|
9090
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
7076
9091
|
),
|
|
7077
9092
|
'base64url'
|
|
7078
9093
|
);
|
|
@@ -7135,7 +9150,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
7135
9150
|
publishedList.metadata.encoding === 'base64url'
|
|
7136
9151
|
? statusList2021
|
|
7137
9152
|
: toString(
|
|
7138
|
-
fromString(statusList2021, publishedList.metadata.encoding as
|
|
9153
|
+
fromString(statusList2021, publishedList.metadata.encoding as DefaultStatusListEncoding),
|
|
7139
9154
|
'base64url'
|
|
7140
9155
|
);
|
|
7141
9156
|
|
|
@@ -7149,7 +9164,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
7149
9164
|
private static async checkSuspendedNonMigrated(
|
|
7150
9165
|
credential: VerifiableCredential,
|
|
7151
9166
|
associatedStatusList?: StatusList2021SuspensionNonMigrated,
|
|
7152
|
-
options:
|
|
9167
|
+
options: ICheqdStatusListOptions = { fetchList: true }
|
|
7153
9168
|
): Promise<boolean> {
|
|
7154
9169
|
// validate status purpose
|
|
7155
9170
|
if (credential.credentialStatus?.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.suspension) {
|
|
@@ -7177,7 +9192,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
7177
9192
|
: toString(
|
|
7178
9193
|
fromString(
|
|
7179
9194
|
publishedList.StatusList2021.encodedList,
|
|
7180
|
-
publishedList.metadata.encoding as
|
|
9195
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
7181
9196
|
),
|
|
7182
9197
|
'base64url'
|
|
7183
9198
|
);
|
|
@@ -7230,7 +9245,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
7230
9245
|
: toString(
|
|
7231
9246
|
fromString(
|
|
7232
9247
|
publishedList.StatusList2021.encodedList,
|
|
7233
|
-
publishedList.metadata.encoding as
|
|
9248
|
+
publishedList.metadata.encoding as DefaultStatusListEncoding
|
|
7234
9249
|
),
|
|
7235
9250
|
'base64url'
|
|
7236
9251
|
);
|
|
@@ -7375,7 +9390,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
7375
9390
|
if (returnRaw) {
|
|
7376
9391
|
return fromString(
|
|
7377
9392
|
content.StatusList2021.encodedList,
|
|
7378
|
-
content.metadata.encoding as
|
|
9393
|
+
content.metadata.encoding as DefaultStatusListEncoding
|
|
7379
9394
|
);
|
|
7380
9395
|
}
|
|
7381
9396
|
|
|
@@ -7383,7 +9398,7 @@ export class Cheqd implements IAgentPlugin {
|
|
|
7383
9398
|
return content;
|
|
7384
9399
|
}
|
|
7385
9400
|
|
|
7386
|
-
static async
|
|
9401
|
+
static async fetchStatusListMetadata(
|
|
7387
9402
|
credential: VerifiableCredential
|
|
7388
9403
|
): Promise<LinkedResourceMetadataResolutionResult> {
|
|
7389
9404
|
// get base url
|
|
@@ -7434,6 +9449,28 @@ export class Cheqd implements IAgentPlugin {
|
|
|
7434
9449
|
resourceVersioning.sort((a, b) => new Date(b.created).getTime() - new Date(a.created).getTime())[0]
|
|
7435
9450
|
);
|
|
7436
9451
|
}
|
|
9452
|
+
/**
|
|
9453
|
+
* Fetch the JSON metadata from a bitstring status list credential URL
|
|
9454
|
+
*/
|
|
9455
|
+
static async fetchBitstringStatusList(credential: VerifiableCredential): Promise<BitstringStatusList> {
|
|
9456
|
+
// get base url
|
|
9457
|
+
const baseUrl = new URL(credential.credentialStatus!.id.split('#')[0]);
|
|
9458
|
+
// fetch collection metadata
|
|
9459
|
+
const response = await fetch(baseUrl, {
|
|
9460
|
+
method: 'GET',
|
|
9461
|
+
headers: {
|
|
9462
|
+
Accept: 'application/json',
|
|
9463
|
+
'Content-Type': 'application/json',
|
|
9464
|
+
},
|
|
9465
|
+
});
|
|
9466
|
+
if (!response.ok) {
|
|
9467
|
+
throw new Error(
|
|
9468
|
+
`[did-provider-cheqd]: Bitstring Status List retrieval error ${response.status}: ${response.statusText}`
|
|
9469
|
+
);
|
|
9470
|
+
}
|
|
9471
|
+
const data: BitstringStatusList = await response.json();
|
|
9472
|
+
return data;
|
|
9473
|
+
}
|
|
7437
9474
|
|
|
7438
9475
|
static async getProviderFromDidUrl(
|
|
7439
9476
|
didUrl: string,
|
|
@@ -7525,6 +9562,22 @@ export class Cheqd implements IAgentPlugin {
|
|
|
7525
9562
|
return {
|
|
7526
9563
|
...decodedCredential.payload.vc,
|
|
7527
9564
|
issuer: decodedCredential.payload.iss,
|
|
7528
|
-
} satisfies VerifiableCredential;
|
|
9565
|
+
} satisfies VerifiableCredential | BitstringStatusListCredential;
|
|
9566
|
+
}
|
|
9567
|
+
static getBitValue(bitstring: DBBitstring, bitIndex: number, statusSize = 1): number {
|
|
9568
|
+
let value = 0;
|
|
9569
|
+
for (let i = 0; i < statusSize; i++) {
|
|
9570
|
+
const bit = bitstring.get(bitIndex + i);
|
|
9571
|
+
value |= bit << i;
|
|
9572
|
+
}
|
|
9573
|
+
return value;
|
|
9574
|
+
}
|
|
9575
|
+
// Helper function to set bit values in a bitstring (2-bit values)
|
|
9576
|
+
static setBitValue(bitstring: DBBitstring, bitIndex: number, value: number, statusSize: number = 2): void {
|
|
9577
|
+
for (let i = 0; i < statusSize; i++) {
|
|
9578
|
+
const bit = (value >> i) & 1;
|
|
9579
|
+
bitstring.set(bitIndex + i, bit === 1);
|
|
9580
|
+
}
|
|
7529
9581
|
}
|
|
7530
9582
|
}
|
|
9583
|
+
export { BitstringStatusListResourceType, DefaultStatusListEncodings };
|