@docknetwork/wallet-sdk-core 1.5.14 → 1.7.6

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.
Files changed (92) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/generate-docs.js +33 -0
  3. package/jsdoc.conf.json +28 -0
  4. package/lib/biometric-provider.d.ts +124 -32
  5. package/lib/biometric-provider.d.ts.map +1 -1
  6. package/lib/biometric-provider.js +146 -7
  7. package/lib/biometric-provider.js.map +1 -1
  8. package/lib/cloud-wallet.d.ts +8 -6
  9. package/lib/cloud-wallet.d.ts.map +1 -1
  10. package/lib/cloud-wallet.js +41 -57
  11. package/lib/cloud-wallet.js.map +1 -1
  12. package/lib/credential-provider.d.ts +58 -33
  13. package/lib/credential-provider.d.ts.map +1 -1
  14. package/lib/credential-provider.js +212 -11
  15. package/lib/credential-provider.js.map +1 -1
  16. package/lib/credentials/oidvc.js +4 -5
  17. package/lib/credentials/oidvc.js.map +1 -1
  18. package/lib/did-provider.d.ts +102 -36
  19. package/lib/did-provider.d.ts.map +1 -1
  20. package/lib/did-provider.js +185 -27
  21. package/lib/did-provider.js.map +1 -1
  22. package/lib/ecosystem-tools.js +4 -5
  23. package/lib/ecosystem-tools.js.map +1 -1
  24. package/lib/helpers.js +6 -6
  25. package/lib/helpers.js.map +1 -1
  26. package/lib/message-provider.d.ts +39 -13
  27. package/lib/message-provider.d.ts.map +1 -1
  28. package/lib/message-provider.js +173 -22
  29. package/lib/message-provider.js.map +1 -1
  30. package/lib/messages/message-helpers.js +6 -6
  31. package/lib/messages/message-helpers.js.map +1 -1
  32. package/lib/network-resolver.js +5 -5
  33. package/lib/network-resolver.js.map +1 -1
  34. package/lib/qr-handlers/builtin/index.d.ts +30 -0
  35. package/lib/qr-handlers/builtin/index.d.ts.map +1 -0
  36. package/lib/qr-handlers/builtin/index.js +46 -0
  37. package/lib/qr-handlers/builtin/index.js.map +1 -0
  38. package/lib/qr-handlers/builtin/oid4vc-handler.d.ts +137 -0
  39. package/lib/qr-handlers/builtin/oid4vc-handler.d.ts.map +1 -0
  40. package/lib/qr-handlers/builtin/oid4vc-handler.js +134 -0
  41. package/lib/qr-handlers/builtin/oid4vc-handler.js.map +1 -0
  42. package/lib/qr-handlers/index.d.ts +76 -0
  43. package/lib/qr-handlers/index.d.ts.map +1 -0
  44. package/lib/qr-handlers/index.js +92 -0
  45. package/lib/qr-handlers/index.js.map +1 -0
  46. package/lib/qr-handlers/processor.d.ts +110 -0
  47. package/lib/qr-handlers/processor.d.ts.map +1 -0
  48. package/lib/qr-handlers/processor.js +251 -0
  49. package/lib/qr-handlers/processor.js.map +1 -0
  50. package/lib/qr-handlers/types.d.ts +205 -0
  51. package/lib/qr-handlers/types.d.ts.map +1 -0
  52. package/lib/qr-handlers/types.js +10 -0
  53. package/lib/qr-handlers/types.js.map +1 -0
  54. package/lib/types.d.ts +613 -13
  55. package/lib/types.d.ts.map +1 -1
  56. package/lib/types.js +16 -0
  57. package/lib/types.js.map +1 -1
  58. package/lib/verification-controller.d.ts +3 -4
  59. package/lib/verification-controller.d.ts.map +1 -1
  60. package/lib/verification-controller.js +10 -3
  61. package/lib/verification-controller.js.map +1 -1
  62. package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.d.ts +0 -1
  63. package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.d.ts.map +1 -1
  64. package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.js +2 -2
  65. package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.js.map +1 -1
  66. package/lib/wallet-wasm.d.ts +2 -2
  67. package/lib/wallet-wasm.d.ts.map +1 -1
  68. package/lib/wallet-wasm.js +15 -17
  69. package/lib/wallet-wasm.js.map +1 -1
  70. package/lib/wallet.d.ts +36 -20
  71. package/lib/wallet.d.ts.map +1 -1
  72. package/lib/wallet.js +172 -26
  73. package/lib/wallet.js.map +1 -1
  74. package/package.json +19 -11
  75. package/src/biometric-provider.ts +157 -42
  76. package/src/cloud-wallet.ts +21 -60
  77. package/src/credential-provider.test.ts +191 -1
  78. package/src/credential-provider.ts +208 -27
  79. package/src/did-provider.ts +183 -34
  80. package/src/message-provider.ts +177 -38
  81. package/src/qr-handlers/builtin/index.ts +30 -0
  82. package/src/qr-handlers/builtin/oid4vc-handler.ts +198 -0
  83. package/src/qr-handlers/index.ts +76 -0
  84. package/src/qr-handlers/processor.test.ts +514 -0
  85. package/src/qr-handlers/processor.ts +311 -0
  86. package/src/qr-handlers/types.ts +228 -0
  87. package/src/types.ts +671 -11
  88. package/src/verification-controller.test.ts +1 -2
  89. package/src/verification-controller.ts +14 -2
  90. package/src/wallet-wasm.ts +5 -8
  91. package/src/wallet.ts +173 -24
  92. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1,18 +1,20 @@
1
+ /**
2
+ * @module cloud-wallet
3
+ * @description Cloud wallet functionality for the Truvera Wallet SDK.
4
+ * This module provides the main cloud wallet creation and management functions.
5
+ */
6
+
1
7
  import {
2
8
  DataStore,
3
9
  DataStoreEvents,
4
10
  } from '@docknetwork/wallet-sdk-data-store/src/types';
5
11
  import { logger } from '@docknetwork/wallet-sdk-data-store/src/logger';
6
- import { edvService, EDVService } from '@docknetwork/wallet-sdk-wasm/src/services/edv/service';
7
- import hkdf from 'futoin-hkdf';
8
- import crypto from '@docknetwork/universal-wallet/crypto';
12
+ import { edvService } from '@docknetwork/wallet-sdk-wasm/src/services/edv';
9
13
  import { utilCryptoService } from '@docknetwork/wallet-sdk-wasm/src/services/util-crypto';
10
14
 
11
15
  export const SYNC_MARKER_TYPE = 'SyncMarkerDocument';
12
16
  export const MNEMONIC_WORD_COUNT = 12;
13
17
  export const KEY_MAPPING_TYPE = 'KeyMappingDocument';
14
- export const HKDF_LENGTH = 32;
15
- export const HKDF_HASH = 'SHA-256';
16
18
  const MASTER_KEY_SUFFIX = 'master-key';
17
19
 
18
20
  /**
@@ -25,9 +27,7 @@ export function deriveBiometricKey(
25
27
  biometricData: Buffer,
26
28
  identifier: string,
27
29
  ): Buffer {
28
- const salt = identifier;
29
-
30
- return hkdf(biometricData, HKDF_LENGTH, { salt, hash: HKDF_HASH });
30
+ return edvService.deriveBiometricKey(biometricData, identifier);
31
31
  }
32
32
 
33
33
  /**
@@ -55,15 +55,7 @@ export async function deriveBiometricEncryptionKey(
55
55
  biometricData: Buffer,
56
56
  identifier: string
57
57
  ): Promise<{ key: Buffer; iv: Buffer }> {
58
- const key = deriveBiometricKey(biometricData, identifier);
59
-
60
- const randomBytes = crypto.getRandomValues(new Uint8Array(16));
61
- const iv = Buffer.from(randomBytes);
62
-
63
- return {
64
- key,
65
- iv
66
- };
58
+ return edvService.deriveBiometricEncryptionKey(biometricData, identifier);
67
59
  }
68
60
 
69
61
  /**
@@ -78,24 +70,7 @@ export async function encryptMasterKey(
78
70
  encryptionKey: Buffer,
79
71
  iv: Buffer
80
72
  ): Promise<Uint8Array> {
81
- const keyData = new Uint8Array(encryptionKey);
82
- const ivData = new Uint8Array(iv);
83
-
84
- const key = await crypto.subtle.importKey(
85
- 'raw',
86
- keyData,
87
- { name: 'AES-GCM' },
88
- false,
89
- ['encrypt']
90
- );
91
-
92
- const encryptedBuffer = await crypto.subtle.encrypt(
93
- { name: 'AES-GCM', iv: ivData },
94
- key,
95
- masterKey
96
- );
97
-
98
- return new Uint8Array(encryptedBuffer);
73
+ return edvService.encryptMasterKey(masterKey, encryptionKey, iv);
99
74
  }
100
75
 
101
76
  /**
@@ -110,28 +85,7 @@ export async function decryptMasterKey(
110
85
  decryptionKey: Buffer,
111
86
  iv: Buffer
112
87
  ): Promise<Uint8Array> {
113
- try {
114
- const keyData = new Uint8Array(decryptionKey);
115
- const ivData = new Uint8Array(iv);
116
-
117
- const key = await crypto.subtle.importKey(
118
- 'raw',
119
- keyData,
120
- { name: 'AES-GCM' },
121
- false,
122
- ['decrypt']
123
- );
124
-
125
- const decryptedBuffer = await crypto.subtle.decrypt(
126
- { name: 'AES-GCM', iv: ivData },
127
- key,
128
- encryptedKey
129
- );
130
-
131
- return new Uint8Array(decryptedBuffer);
132
- } catch (error) {
133
- throw new Error('Decryption failed: Invalid key or corrupted data');
134
- }
88
+ return edvService.decryptMasterKey(encryptedKey, decryptionKey, iv);
135
89
  }
136
90
 
137
91
  /**
@@ -147,14 +101,14 @@ export async function initializeKeyMappingVault(
147
101
  authKey: string,
148
102
  biometricData: Buffer,
149
103
  identifier: string
150
- ): Promise<EDVService> {
104
+ ): Promise<typeof edvService> {
151
105
  const {
152
106
  hmacKey,
153
107
  agreementKey,
154
108
  verificationKey
155
109
  } = await deriveKeyMappingVaultKeys(biometricData, identifier);
156
110
 
157
- const keyMappingEdvService = new EDVService();
111
+ const keyMappingEdvService = edvService;
158
112
  await keyMappingEdvService.initialize({
159
113
  hmacKey,
160
114
  agreementKey,
@@ -219,7 +173,7 @@ export async function enrollUserWithBiometrics(
219
173
  * @returns The decrypted master key for CloudWalletVault
220
174
  */
221
175
  export async function getKeyMappingMasterKey(
222
- keyMappingEdv: EDVService,
176
+ keyMappingEdv: typeof edvService,
223
177
  identifier: string,
224
178
  decryptionKey: Buffer,
225
179
  ): Promise<Uint8Array> {
@@ -227,6 +181,13 @@ export async function getKeyMappingMasterKey(
227
181
  equals: {
228
182
  'content.id': identifier
229
183
  }
184
+ }).catch(error => {
185
+ if (error.message && error.message.includes('does not exist')) {
186
+ logger.error('KeyMappingVault does not exist, skipping find');
187
+ return { documents: [] };
188
+ }
189
+
190
+ throw error;
230
191
  });
231
192
 
232
193
  if (!result.documents || result.documents.length === 0) {
@@ -227,7 +227,7 @@ describe('CredentialProvider', () => {
227
227
  });
228
228
 
229
229
  await provider.syncCredentialStatus({forceFetch: true});
230
-
230
+
231
231
  // Clear mocks
232
232
  jest.clearAllMocks();
233
233
 
@@ -255,6 +255,196 @@ describe('CredentialProvider', () => {
255
255
  expect(credentialServiceRPC.verifyCredential).toHaveBeenCalledTimes(2);
256
256
  });
257
257
 
258
+ it('should always refetch credentials with Invalid status even when cached', async () => {
259
+ // First, create credentials with Invalid status
260
+ jest
261
+ .spyOn(credentialServiceRPC, 'verifyCredential')
262
+ .mockImplementation(async () => {
263
+ return {
264
+ verified: false,
265
+ error: 'Credential validation failed',
266
+ };
267
+ });
268
+
269
+ await provider.syncCredentialStatus({forceFetch: true});
270
+
271
+ // Verify initial calls
272
+ expect(credentialServiceRPC.verifyCredential).toHaveBeenCalledTimes(2);
273
+
274
+ // Check that status is set to Invalid
275
+ const initialStatusDoc = await wallet.getDocumentById(
276
+ `${customerCredential.id}#status`,
277
+ );
278
+ expect(initialStatusDoc.status).toBe(CredentialStatus.Invalid);
279
+
280
+ // Clear mocks to track only subsequent calls
281
+ jest.clearAllMocks();
282
+
283
+ // Now mock successful verification
284
+ jest
285
+ .spyOn(credentialServiceRPC, 'verifyCredential')
286
+ .mockImplementation(async () => {
287
+ return {
288
+ verified: true,
289
+ };
290
+ });
291
+
292
+ // Call syncCredentialStatus again WITHOUT forceFetch
293
+ // Invalid status should trigger refetch even without forceFetch
294
+ const statusDocs = await provider.syncCredentialStatus({});
295
+
296
+ // Verify that verifyCredential was called again despite no forceFetch
297
+ expect(credentialServiceRPC.verifyCredential).toHaveBeenCalledTimes(2);
298
+
299
+ // Check that status is now updated to Verified
300
+ expect(statusDocs.length).toBe(2);
301
+ for (const statusDoc of statusDocs) {
302
+ expect(statusDoc.status).toBe(CredentialStatus.Verified);
303
+ }
304
+ });
305
+
306
+ it('should always refetch credentials with Pending status even when cached', async () => {
307
+ // First, manually create a Pending status document
308
+ const pendingStatusDoc = {
309
+ type: 'CredentialStatus',
310
+ id: `${customerCredential.id}#status`,
311
+ createdAt: new Date().toISOString(),
312
+ updatedAt: new Date().toISOString(),
313
+ status: CredentialStatus.Pending,
314
+ error: null,
315
+ warning: null,
316
+ };
317
+ await wallet.updateDocument(pendingStatusDoc);
318
+
319
+ // Mock successful verification
320
+ jest
321
+ .spyOn(credentialServiceRPC, 'verifyCredential')
322
+ .mockImplementation(async () => {
323
+ return {
324
+ verified: true,
325
+ };
326
+ });
327
+
328
+ // Call syncCredentialStatus without forceFetch
329
+ // Pending status should trigger refetch
330
+ const statusDocs = await provider.syncCredentialStatus({
331
+ credentialIds: [customerCredential.id],
332
+ });
333
+
334
+ // Verify that verifyCredential was called for the Pending credential
335
+ expect(credentialServiceRPC.verifyCredential).toHaveBeenCalledTimes(1);
336
+
337
+ // Check that status is now updated to Verified
338
+ expect(statusDocs.length).toBe(1);
339
+ expect(statusDocs[0].status).toBe(CredentialStatus.Verified);
340
+ });
341
+
342
+ it('should cache Revoked status and not refetch within 24 hours', async () => {
343
+ // First, create credentials with Revoked status
344
+ jest
345
+ .spyOn(credentialServiceRPC, 'verifyCredential')
346
+ .mockImplementation(async () => {
347
+ return {
348
+ verified: false,
349
+ error: 'Revocation check failed',
350
+ };
351
+ });
352
+
353
+ await provider.syncCredentialStatus({forceFetch: true});
354
+
355
+ // Verify initial calls
356
+ expect(credentialServiceRPC.verifyCredential).toHaveBeenCalledTimes(2);
357
+
358
+ // Check that status is set to Revoked
359
+ const revokedStatusDoc = await wallet.getDocumentById(
360
+ `${customerCredential.id}#status`,
361
+ );
362
+ expect(revokedStatusDoc.status).toBe(CredentialStatus.Revoked);
363
+
364
+ // Clear mocks to track only subsequent calls
365
+ jest.clearAllMocks();
366
+
367
+ // Call syncCredentialStatus again WITHOUT forceFetch
368
+ // Revoked status should NOT trigger refetch within 24 hours
369
+ const statusDocs = await provider.syncCredentialStatus({});
370
+
371
+ // Verify that verifyCredential was NOT called (cached)
372
+ expect(credentialServiceRPC.verifyCredential).toHaveBeenCalledTimes(0);
373
+
374
+ // Check that status remains Revoked
375
+ expect(statusDocs.length).toBe(2);
376
+ for (const statusDoc of statusDocs) {
377
+ expect(statusDoc.status).toBe(CredentialStatus.Revoked);
378
+ }
379
+ });
380
+
381
+ it('should cache Verified status and not refetch within 24 hours', async () => {
382
+ // First, create credentials with Verified status
383
+ jest
384
+ .spyOn(credentialServiceRPC, 'verifyCredential')
385
+ .mockImplementation(async () => {
386
+ return {
387
+ verified: true,
388
+ };
389
+ });
390
+
391
+ await provider.syncCredentialStatus({forceFetch: true});
392
+
393
+ // Verify initial calls
394
+ expect(credentialServiceRPC.verifyCredential).toHaveBeenCalledTimes(2);
395
+
396
+ // Check that status is set to Verified
397
+ const verifiedStatusDoc = await wallet.getDocumentById(
398
+ `${customerCredential.id}#status`,
399
+ );
400
+ expect(verifiedStatusDoc.status).toBe(CredentialStatus.Verified);
401
+
402
+ // Clear mocks to track only subsequent calls
403
+ jest.clearAllMocks();
404
+
405
+ // Call syncCredentialStatus again WITHOUT forceFetch
406
+ // Verified status should NOT trigger refetch within 24 hours
407
+ const statusDocs = await provider.syncCredentialStatus({});
408
+
409
+ // Verify that verifyCredential was NOT called (cached)
410
+ expect(credentialServiceRPC.verifyCredential).toHaveBeenCalledTimes(0);
411
+
412
+ // Check that status remains Verified
413
+ expect(statusDocs.length).toBe(2);
414
+ for (const statusDoc of statusDocs) {
415
+ expect(statusDoc.status).toBe(CredentialStatus.Verified);
416
+ }
417
+ });
418
+
419
+ it('should refetch credentials without status document', async () => {
420
+ // Remove any existing status documents
421
+ await wallet.removeDocument(`${customerCredential.id}#status`).catch(() => {});
422
+ await wallet.removeDocument(`${biometricsBBSRevocation.id}#status`).catch(() => {});
423
+
424
+ // Mock successful verification
425
+ jest
426
+ .spyOn(credentialServiceRPC, 'verifyCredential')
427
+ .mockImplementation(async () => {
428
+ return {
429
+ verified: true,
430
+ };
431
+ });
432
+
433
+ // Call syncCredentialStatus
434
+ // Missing status docs should trigger fetch
435
+ const statusDocs = await provider.syncCredentialStatus({});
436
+
437
+ // Verify that verifyCredential was called for both credentials
438
+ expect(credentialServiceRPC.verifyCredential).toHaveBeenCalledTimes(2);
439
+
440
+ // Check that status documents were created
441
+ expect(statusDocs.length).toBe(2);
442
+ for (const statusDoc of statusDocs) {
443
+ expect(statusDoc.status).toBe(CredentialStatus.Verified);
444
+ expect(statusDoc.type).toBe('CredentialStatus');
445
+ }
446
+ });
447
+
258
448
  afterEach(() => {
259
449
  (credentialServiceRPC.verifyCredential as any).mockReset();
260
450
  });
@@ -1,5 +1,12 @@
1
+ /**
2
+ * @module credential-provider
3
+ * @description Verifiable credential management functionality for the Truvera Wallet SDK.
4
+ * This module provides functions for importing, verifying, storing, and managing verifiable credentials.
5
+ */
6
+
1
7
  import {credentialServiceRPC} from '@docknetwork/wallet-sdk-wasm/src/services/credential';
2
- import {IWallet} from './types';
8
+ import {IWallet, ICredentialProvider} from './types';
9
+ export type {ICredentialProvider};
3
10
  import assert from 'assert';
4
11
  import {blockchainService} from '@docknetwork/wallet-sdk-wasm/src/services/blockchain';
5
12
  import {acquireOpenIDCredentialFromURI} from './credentials/oidvc';
@@ -7,29 +14,10 @@ import {IDIDProvider} from './did-provider';
7
14
 
8
15
  export type Credential = any;
9
16
 
10
- export interface ICredentialProvider {
11
- getCredentials(type?: string): Credential[];
12
- getById(id: string): Credential;
13
- getMembershipWitness(credential: any): Promise<any>;
14
- isBBSPlusCredential(credential: any): boolean;
15
- isValid(credential: any, forceFetch?: boolean): Promise<{
16
- status: string;
17
- error?: string;
18
- warning?: string;
19
- }>;
20
- addCredential(credential: any): Promise<Credential>;
21
- importCredentialFromURI(
22
- params: importCredentialFromUriParams,
23
- ): Promise<Credential>;
24
- syncCredentialStatus(
25
- params: SyncCredentialStatusParams,
26
- ): Promise<CredentialStatusDocument[]>;
27
- getCredentialStatus(
28
- credential: Credential,
29
- ): Promise<{status: string; error?: string}>;
30
- removeCredential(credential: Credential): Promise<void>;
31
- }
32
-
17
+ /**
18
+ * Internal function to check if a credential uses BBS+ signature
19
+ * @private
20
+ */
33
21
  export function isBBSPlusCredential(credential) {
34
22
  return (
35
23
  (typeof credential?.proof?.type === 'string' &&
@@ -47,6 +35,10 @@ type importCredentialFromUriParams = {
47
35
  getAuthCode?: (authorizationURL: string) => Promise<string>;
48
36
  };
49
37
 
38
+ /**
39
+ * Internal function to import credential from URI
40
+ * @private
41
+ */
50
42
  export async function importCredentialFromURI({
51
43
  uri,
52
44
  wallet,
@@ -68,6 +60,10 @@ export async function importCredentialFromURI({
68
60
  await addCredential({wallet, credential});
69
61
  }
70
62
 
63
+ /**
64
+ * Internal function to check if credential is expired
65
+ * @private
66
+ */
71
67
  export function isCredentialExpired(credential) {
72
68
  return (
73
69
  !!credential.expirationDate &&
@@ -78,7 +74,7 @@ export function isCredentialExpired(credential) {
78
74
  /**
79
75
  * Uses Dock SDK to verify a credential
80
76
  * @param credential
81
- * @returns
77
+ * @returns {Promise<Object>} Verification result with status and optional error/warning messages
82
78
  */
83
79
  export async function isValid({
84
80
  credential,
@@ -172,7 +168,26 @@ export async function isValid({
172
168
 
173
169
  export const ACUMM_WITNESS_PROP_KEY = '$$accum__witness$$';
174
170
 
171
+ /**
172
+ * Internal function to add credential to wallet
173
+ * @private
174
+ */
175
175
  export async function addCredential({wallet, credential}) {
176
+ // Check if the credential is an SD-JWT (string format)
177
+ if (typeof credential === 'string') {
178
+ try {
179
+ const isSDJWT = await credentialServiceRPC.isSDJWTCredential({credential});
180
+
181
+ if (isSDJWT) {
182
+ // Convert SD-JWT to W3C format (includes _sd_jwt metadata for unwrapping)
183
+ credential = await credentialServiceRPC.credentialToW3C({credential});
184
+ }
185
+ } catch (error) {
186
+ console.error('Error checking/converting SD-JWT credential:', error);
187
+ throw new Error('Failed to process SD-JWT credential: ' + error.message);
188
+ }
189
+ }
190
+
176
191
  const acummWitness = credential[ACUMM_WITNESS_PROP_KEY];
177
192
 
178
193
  if (acummWitness) {
@@ -195,6 +210,10 @@ export async function addCredential({wallet, credential}) {
195
210
  return response;
196
211
  }
197
212
 
213
+ /**
214
+ * Internal function to get membership witness for credential
215
+ * @private
216
+ */
198
217
  async function getMembershipWitness({credentialId, wallet}) {
199
218
  const document = await wallet.getDocumentById(`${credentialId}#witness`);
200
219
  return document?.value;
@@ -230,6 +249,10 @@ type CredentialStatusDocument = {
230
249
  * @param param0
231
250
  * @returns CredentialStatusDocument[]
232
251
  */
252
+ /**
253
+ * Internal function to sync credential status from blockchain
254
+ * @private
255
+ */
233
256
  async function syncCredentialStatus({
234
257
  wallet,
235
258
  credentialIds,
@@ -268,7 +291,9 @@ async function syncCredentialStatus({
268
291
 
269
292
  statusDocs.push(statusDoc);
270
293
 
271
- if (!statusDoc.status || statusDoc.status === CredentialStatus.Pending) {
294
+ // Revoked and Expired statuses should be cached
295
+ // The user can fore refresh that from the credentials screen
296
+ if (!statusDoc.status || statusDoc.status === CredentialStatus.Invalid || statusDoc.status === CredentialStatus.Pending) {
272
297
  shouldFetch = true;
273
298
  }
274
299
 
@@ -312,7 +337,11 @@ async function syncCredentialStatus({
312
337
  /**
313
338
  * Removes a credential and its related documents from the wallet
314
339
  * @param param0
315
- * @returns
340
+ * @returns {Promise<void>}
341
+ */
342
+ /**
343
+ * Internal function to remove credential and related documents
344
+ * @private
316
345
  */
317
346
  export async function removeCredential({
318
347
  wallet,
@@ -338,6 +367,35 @@ export async function removeCredential({
338
367
  }
339
368
  }
340
369
 
370
+ /**
371
+ * Creates a credential provider instance bound to a wallet
372
+ * @param {Object} params - Provider configuration
373
+ * @param {IWallet} params.wallet - The wallet instance to use for credential storage
374
+ * @returns {ICredentialProvider} A credential provider instance with all verifiable credential management methods
375
+ * @see {@link ICredentialProvider} - The interface defining all available credential provider methods
376
+ * @example
377
+ * import { createCredentialProvider } from '@docknetwork/wallet-sdk-core';
378
+ *
379
+ * const credentialProvider = createCredentialProvider({wallet});
380
+ *
381
+ * // Add a credential
382
+ * const addedCredential = await credentialProvider.addCredential(myCredential);
383
+ *
384
+ * // Validate a credential
385
+ * const result = await credentialProvider.isValid(credential);
386
+ * if (result.status === 'verified') {
387
+ * console.log('Credential is valid');
388
+ * }
389
+ *
390
+ * // Get all credentials
391
+ * const allCredentials = credentialProvider.getCredentials();
392
+ *
393
+ * // Import from URI
394
+ * await credentialProvider.importCredentialFromURI({
395
+ * uri: 'https://example.com/credential-offer',
396
+ * didProvider
397
+ * });
398
+ */
341
399
  export function createCredentialProvider({
342
400
  wallet,
343
401
  }: {
@@ -348,21 +406,103 @@ export function createCredentialProvider({
348
406
  }
349
407
 
350
408
  return {
409
+ /**
410
+ * Imports a credential from a URI (supports OpenID credential offers)
411
+ * @memberof ICredentialProvider
412
+ * @param {Object} params - Import parameters
413
+ * @param {string} params.uri - The URI containing the credential offer
414
+ * @param {any} params.didProvider - DID provider instance for key management
415
+ * @param {Function} [params.getAuthCode] - Optional callback to handle authorization
416
+ * @returns {Promise<any>} The imported credential
417
+ * @throws {Error} If import fails
418
+ * @example
419
+ * const credential = await credentialProvider.importCredentialFromURI({
420
+ * uri: 'https://issuer.example.com/credential-offer',
421
+ * didProvider,
422
+ * getAuthCode: async (url) => getUserAuthCode(url)
423
+ * });
424
+ */
351
425
  importCredentialFromURI: async (params: importCredentialFromUriParams) =>
352
426
  importCredentialFromURI({
353
427
  ...params,
354
428
  wallet,
355
429
  }),
430
+ /**
431
+ * Retrieves credentials from the wallet, optionally filtered by type
432
+ * @memberof ICredentialProvider
433
+ * @param {string} [type='VerifiableCredential'] - The credential type to filter by
434
+ * @returns {any[]} Array of credentials matching the specified type
435
+ * @example
436
+ * const allCredentials = credentialProvider.getCredentials();
437
+ * const certificates = credentialProvider.getCredentials('Certificate');
438
+ */
356
439
  getCredentials,
440
+ /**
441
+ * Gets the membership witness for a credential (used for BBS+ credentials)
442
+ * @memberof ICredentialProvider
443
+ * @param {string} credentialId - The credential ID to get the witness for
444
+ * @returns {Promise<any>} The membership witness data
445
+ * @example
446
+ * const witness = await credentialProvider.getMembershipWitness('credential-123');
447
+ */
357
448
  getMembershipWitness: async (credentialId: string) =>
358
449
  getMembershipWitness({credentialId, wallet}),
450
+ /**
451
+ * Retrieves a credential by its ID
452
+ * @memberof ICredentialProvider
453
+ * @param {string} id - The unique identifier of the credential
454
+ * @returns {any} The credential document
455
+ * @throws {Error} If credential is not found
456
+ * @example
457
+ * const credential = await credentialProvider.getById('credential-123');
458
+ */
359
459
  getById: (id: string) => wallet.getDocumentById(id),
460
+ /**
461
+ * Checks if a credential uses BBS+ signature
462
+ * @memberof ICredentialProvider
463
+ * @param {any} credential - The credential to check
464
+ * @returns {boolean} True if the credential uses BBS+ signature
465
+ * @example
466
+ * const isBBS = credentialProvider.isBBSPlusCredential(credential);
467
+ * if (isBBS) {
468
+ * console.log('This credential uses BBS+ signatures');
469
+ * }
470
+ */
360
471
  isBBSPlusCredential,
472
+ /**
473
+ * Validates a credential by verifying its cryptographic proof and status
474
+ * @memberof ICredentialProvider
475
+ * @param {any} credential - The credential to validate
476
+ * @param {boolean} [forceFetch=false] - Whether to force refresh the credential status
477
+ * @returns {Promise<Object>} Validation result
478
+ * @returns {string} returns.status - Validation status (verified, revoked, expired, invalid, pending)
479
+ * @returns {string} [returns.error] - Error message if validation failed
480
+ * @returns {string} [returns.warning] - Warning message if any
481
+ * @throws {Error} If validation fails
482
+ * @example
483
+ * const result = await credentialProvider.isValid(credential);
484
+ * if (result.status === 'verified') {
485
+ * console.log('Credential is valid');
486
+ * } else if (result.status === 'revoked') {
487
+ * console.log('Credential has been revoked');
488
+ * }
489
+ */
361
490
  isValid: async credential =>
362
491
  isValid({
363
492
  credential,
364
493
  wallet,
365
494
  }) as any,
495
+ /**
496
+ * Gets the current status of a credential (cached, fast operation)
497
+ * @memberof ICredentialProvider
498
+ * @param {any} credential - The credential to check
499
+ * @returns {Promise<Object>} Current credential status
500
+ * @returns {string} returns.status - Current status of the credential
501
+ * @returns {string} [returns.error] - Error message if any
502
+ * @example
503
+ * const status = await credentialProvider.getCredentialStatus(credential);
504
+ * console.log(`Credential status: ${status.status}`);
505
+ */
366
506
  getCredentialStatus: async (credential: Credential) => {
367
507
  assert(!!credential, 'credential is required');
368
508
 
@@ -379,10 +519,51 @@ export function createCredentialProvider({
379
519
  error: statusDoc?.error,
380
520
  };
381
521
  },
522
+ /**
523
+ * Synchronizes credential status from the blockchain
524
+ * @memberof ICredentialProvider
525
+ * @param {Object} params - Sync parameters
526
+ * @param {string[]} [params.credentialIds] - Optional list of credential IDs to sync
527
+ * @param {boolean} [params.forceFetch=false] - Whether to force refresh from blockchain
528
+ * @returns {Promise<any[]>} Array of credential status documents
529
+ * @example
530
+ * // Sync all credentials
531
+ * await credentialProvider.syncCredentialStatus({});
532
+ *
533
+ * // Sync specific credentials
534
+ * await credentialProvider.syncCredentialStatus({
535
+ * credentialIds: ['cred-1', 'cred-2'],
536
+ * forceFetch: true
537
+ * });
538
+ */
382
539
  syncCredentialStatus: async (props: SyncCredentialStatusParams) => {
383
540
  return syncCredentialStatus({wallet, ...props});
384
541
  },
542
+ /**
543
+ * Adds a credential to the wallet
544
+ * @memberof ICredentialProvider
545
+ * @param {any} credential - The credential to add
546
+ * @returns {Promise<any>} The added credential document
547
+ * @example
548
+ * const addedCredential = await credentialProvider.addCredential({
549
+ * '@context': ['https://www.w3.org/2018/credentials/v1'],
550
+ * type: ['VerifiableCredential'],
551
+ * issuer: 'did:dock:issuer123',
552
+ * credentialSubject: { name: 'Alice' }
553
+ * });
554
+ */
385
555
  addCredential: credential => addCredential({wallet, credential}),
556
+ /**
557
+ * Removes a credential and all its related documents from the wallet
558
+ * @memberof ICredentialProvider
559
+ * @param {any} credential - The credential to remove
560
+ * @returns {Promise<void>}
561
+ * @throws {Error} If credential is not found
562
+ * @example
563
+ * await credentialProvider.removeCredential(credential);
564
+ * // Or by ID
565
+ * await credentialProvider.removeCredential('credential-123');
566
+ */
386
567
  removeCredential: credential => removeCredential({wallet, credential}),
387
568
  // TODO: move import credential from json or URL to this provider
388
569
  };