@docknetwork/wallet-sdk-wasm 1.7.0 → 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 (85) hide show
  1. package/lib/index.js +1 -0
  2. package/lib/index.mjs +1 -0
  3. package/lib/modules/network-manager.js +15 -12
  4. package/lib/modules/network-manager.mjs +15 -12
  5. package/lib/rpc-server.js +1 -0
  6. package/lib/rpc-server.mjs +1 -0
  7. package/lib/services/blockchain/service.js +22 -9
  8. package/lib/services/blockchain/service.mjs +23 -10
  9. package/lib/services/credential/bound-check.js +1 -1
  10. package/lib/services/credential/bound-check.mjs +1 -1
  11. package/lib/services/credential/delegatable-credentials.js +300 -0
  12. package/lib/services/credential/delegatable-credentials.mjs +263 -0
  13. package/lib/services/credential/index.js +39 -0
  14. package/lib/services/credential/index.mjs +4 -0
  15. package/lib/services/credential/pex-helpers.js +4 -4
  16. package/lib/services/credential/pex-helpers.mjs +4 -4
  17. package/lib/services/edv/index.js +1 -0
  18. package/lib/services/edv/index.mjs +1 -0
  19. package/lib/services/edv/service-rpc.js +23 -0
  20. package/lib/services/edv/service-rpc.mjs +23 -0
  21. package/lib/services/edv/service.js +81 -1
  22. package/lib/services/edv/service.mjs +78 -2
  23. package/lib/services/index.js +1 -0
  24. package/lib/services/index.mjs +1 -0
  25. package/lib/services/pex/config.js +4 -0
  26. package/lib/services/pex/config.mjs +4 -0
  27. package/lib/services/pex/service-rpc.js +4 -0
  28. package/lib/services/pex/service-rpc.mjs +4 -0
  29. package/lib/services/pex/service.js +7 -0
  30. package/lib/services/pex/service.mjs +7 -0
  31. package/lib/setup-nodejs.js +1 -0
  32. package/lib/setup-nodejs.mjs +1 -0
  33. package/lib/setup-tests.js +1 -0
  34. package/lib/setup-tests.mjs +1 -0
  35. package/lib/src/modules/event-manager.d.ts +0 -1
  36. package/lib/src/modules/event-manager.d.ts.map +1 -1
  37. package/lib/src/modules/network-manager.d.ts +2 -4
  38. package/lib/src/modules/network-manager.d.ts.map +1 -1
  39. package/lib/src/services/blockchain/configs.d.ts +1 -2
  40. package/lib/src/services/blockchain/configs.d.ts.map +1 -1
  41. package/lib/src/services/blockchain/service.d.ts +4 -3
  42. package/lib/src/services/blockchain/service.d.ts.map +1 -1
  43. package/lib/src/services/credential/bbs-revocation.d.ts +1 -1
  44. package/lib/src/services/credential/bbs-revocation.d.ts.map +1 -1
  45. package/lib/src/services/credential/bound-check.d.ts.map +1 -1
  46. package/lib/src/services/credential/delegatable-credentials.d.ts +272 -0
  47. package/lib/src/services/credential/delegatable-credentials.d.ts.map +1 -0
  48. package/lib/src/services/credential/index.d.ts +1 -0
  49. package/lib/src/services/credential/index.d.ts.map +1 -1
  50. package/lib/src/services/credential/pex-helpers.d.ts +2 -2
  51. package/lib/src/services/credential/pex-helpers.d.ts.map +1 -1
  52. package/lib/src/services/dids/keypair-utils.d.ts +2 -2
  53. package/lib/src/services/dids/keypair-utils.d.ts.map +1 -1
  54. package/lib/src/services/dids/service.d.ts +35 -3
  55. package/lib/src/services/dids/service.d.ts.map +1 -1
  56. package/lib/src/services/edv/service.d.ts +50 -1
  57. package/lib/src/services/edv/service.d.ts.map +1 -1
  58. package/lib/src/services/pex/config.d.ts +1 -0
  59. package/lib/src/services/pex/config.d.ts.map +1 -1
  60. package/lib/src/services/pex/service.d.ts +1 -0
  61. package/lib/src/services/pex/service.d.ts.map +1 -1
  62. package/lib/src/services/relay-service/service.d.ts +19 -7
  63. package/lib/src/services/relay-service/service.d.ts.map +1 -1
  64. package/lib/src/services/storage/service.d.ts.map +1 -1
  65. package/lib/src/services/util-crypto/service.d.ts +2 -2
  66. package/lib/src/services/util-crypto/service.d.ts.map +1 -1
  67. package/lib/tsconfig.tsbuildinfo +1 -1
  68. package/package.json +24 -16
  69. package/rollup.config.mjs +5 -3
  70. package/src/globals.d.ts +3 -0
  71. package/src/modules/network-manager.ts +15 -14
  72. package/src/services/blockchain/configs.ts +1 -2
  73. package/src/services/blockchain/service.ts +26 -10
  74. package/src/services/credential/bound-check.ts +1 -1
  75. package/src/services/credential/delegatable-credentials.ts +409 -0
  76. package/src/services/credential/index.ts +16 -0
  77. package/src/services/credential/pex-helpers.js +4 -4
  78. package/src/services/credential/pex-helpers.test.js +2 -2
  79. package/src/services/edv/index.test.js +229 -0
  80. package/src/services/edv/service-rpc.js +23 -0
  81. package/src/services/edv/service.ts +119 -0
  82. package/src/services/pex/config.ts +4 -0
  83. package/src/services/pex/service-rpc.js +4 -0
  84. package/src/services/pex/service.ts +13 -0
  85. package/src/services/pex/tests/pex-service.test.js +210 -0
@@ -5,10 +5,10 @@ export const EPSILON_INT = 1;
5
5
 
6
6
  export const MAX_DATE_PLACEHOLDER = 884541351600000;
7
7
  export const MIN_DATE_PLACEHOLDER = -17592186044415;
8
- export const MAX_INTEGER = 100 ** 9;
9
- export const MIN_INTEGER = -4294967295;
10
- export const MAX_NUMBER = 100 ** 5;
11
- export const MIN_NUMBER = -4294967294;
8
+ export const MAX_INTEGER = Number.MAX_SAFE_INTEGER;
9
+ export const MIN_INTEGER = Number.MIN_SAFE_INTEGER;
10
+ export const MAX_NUMBER = Number.MAX_SAFE_INTEGER;
11
+ export const MIN_NUMBER = Number.MIN_SAFE_INTEGER;
12
12
 
13
13
  /*
14
14
  PEX Filter rules:
@@ -302,7 +302,7 @@ describe('pex helpers', () => {
302
302
  {
303
303
  attributeName: 'credentialSubject.age',
304
304
  min: 0,
305
- max: 10000000000,
305
+ max: Number.MAX_SAFE_INTEGER,
306
306
  proofRequestMax: undefined,
307
307
  proofRequestMin: 0,
308
308
  format: undefined,
@@ -357,7 +357,7 @@ describe('pex helpers', () => {
357
357
  {
358
358
  attributeName: 'credentialSubject.age',
359
359
  min: 0,
360
- max: 10000000000,
360
+ max: Number.MAX_SAFE_INTEGER,
361
361
  proofRequestMax: undefined,
362
362
  proofRequestMin: 0,
363
363
  format: undefined,
@@ -47,5 +47,234 @@ describe('EDVService', () => {
47
47
  expect(JSON.stringify(agreementKey)).toBe(derivedTestAgreementKey);
48
48
  });
49
49
  });
50
+
51
+ describe('deriveBiometricKey', () => {
52
+ it('should derive a key from biometric data', () => {
53
+ const biometricData = Buffer.from('mock-biometric-data');
54
+ const identifier = 'user@example.com';
55
+
56
+ const key = service.deriveBiometricKey(biometricData, identifier);
57
+
58
+ expect(key).toBeDefined();
59
+ expect(Buffer.isBuffer(key)).toBe(true);
60
+ expect(key.length).toBe(32); // HKDF_LENGTH
61
+ });
62
+
63
+ it('should produce consistent keys for same inputs', () => {
64
+ const biometricData = Buffer.from('mock-biometric-data');
65
+ const identifier = 'user@example.com';
66
+
67
+ const key1 = service.deriveBiometricKey(biometricData, identifier);
68
+ const key2 = service.deriveBiometricKey(biometricData, identifier);
69
+
70
+ expect(key1.equals(key2)).toBe(true);
71
+ });
72
+
73
+ it('should produce different keys for different identifiers', () => {
74
+ const biometricData = Buffer.from('mock-biometric-data');
75
+ const identifier1 = 'user1@example.com';
76
+ const identifier2 = 'user2@example.com';
77
+
78
+ const key1 = service.deriveBiometricKey(biometricData, identifier1);
79
+ const key2 = service.deriveBiometricKey(biometricData, identifier2);
80
+
81
+ expect(key1.equals(key2)).toBe(false);
82
+ });
83
+
84
+ it('should produce different keys for different biometric data', () => {
85
+ const biometricData1 = Buffer.from('mock-biometric-data-1');
86
+ const biometricData2 = Buffer.from('mock-biometric-data-2');
87
+ const identifier = 'user@example.com';
88
+
89
+ const key1 = service.deriveBiometricKey(biometricData1, identifier);
90
+ const key2 = service.deriveBiometricKey(biometricData2, identifier);
91
+
92
+ expect(key1.equals(key2)).toBe(false);
93
+ });
94
+ });
95
+
96
+ describe('deriveBiometricEncryptionKey', () => {
97
+ it('should derive encryption key and IV', async () => {
98
+ const biometricData = Buffer.from('mock-biometric-data');
99
+ const identifier = 'user@example.com';
100
+
101
+ const result = await service.deriveBiometricEncryptionKey(
102
+ biometricData,
103
+ identifier,
104
+ );
105
+
106
+ expect(result).toBeDefined();
107
+ expect(result.key).toBeDefined();
108
+ expect(result.iv).toBeDefined();
109
+ expect(Buffer.isBuffer(result.key)).toBe(true);
110
+ expect(Buffer.isBuffer(result.iv)).toBe(true);
111
+ expect(result.key.length).toBe(32); // HKDF_LENGTH
112
+ expect(result.iv.length).toBe(16); // AES-GCM IV length
113
+ });
114
+
115
+ it('should produce consistent keys but different IVs for same inputs', async () => {
116
+ const biometricData = Buffer.from('mock-biometric-data');
117
+ const identifier = 'user@example.com';
118
+
119
+ const result1 = await service.deriveBiometricEncryptionKey(
120
+ biometricData,
121
+ identifier,
122
+ );
123
+ const result2 = await service.deriveBiometricEncryptionKey(
124
+ biometricData,
125
+ identifier,
126
+ );
127
+
128
+ expect(result1.key.equals(result2.key)).toBe(true);
129
+ // IVs should be different (random)
130
+ expect(result1.iv.equals(result2.iv)).toBe(false);
131
+ });
132
+ });
133
+
134
+ describe('encryptMasterKey and decryptMasterKey', () => {
135
+ it('should encrypt and decrypt master key successfully', async () => {
136
+ const masterKey = new Uint8Array(32).fill(42);
137
+ const encryptionKey = Buffer.from(new Uint8Array(32).fill(1));
138
+ const iv = Buffer.from(new Uint8Array(16).fill(2));
139
+
140
+ const encrypted = await service.encryptMasterKey(
141
+ masterKey,
142
+ encryptionKey,
143
+ iv,
144
+ );
145
+ expect(encrypted).toBeDefined();
146
+ expect(encrypted instanceof Uint8Array).toBe(true);
147
+ expect(encrypted.length).toBeGreaterThan(0);
148
+
149
+ const decrypted = await service.decryptMasterKey(
150
+ encrypted,
151
+ encryptionKey,
152
+ iv,
153
+ );
154
+ expect(decrypted).toBeDefined();
155
+ expect(decrypted instanceof Uint8Array).toBe(true);
156
+ expect(new Uint8Array(decrypted)).toEqual(masterKey);
157
+ });
158
+
159
+ it('should fail to decrypt with wrong key', async () => {
160
+ const masterKey = new Uint8Array(32).fill(42);
161
+ const encryptionKey = Buffer.from(new Uint8Array(32).fill(1));
162
+ const wrongKey = Buffer.from(new Uint8Array(32).fill(99));
163
+ const iv = Buffer.from(new Uint8Array(16).fill(2));
164
+
165
+ const encrypted = await service.encryptMasterKey(
166
+ masterKey,
167
+ encryptionKey,
168
+ iv,
169
+ );
170
+
171
+ await expect(
172
+ service.decryptMasterKey(encrypted, wrongKey, iv),
173
+ ).rejects.toThrow('Decryption failed: Invalid key or corrupted data');
174
+ });
175
+
176
+ it('should fail to decrypt with wrong IV', async () => {
177
+ const masterKey = new Uint8Array(32).fill(42);
178
+ const encryptionKey = Buffer.from(new Uint8Array(32).fill(1));
179
+ const iv = Buffer.from(new Uint8Array(16).fill(2));
180
+ const wrongIv = Buffer.from(new Uint8Array(16).fill(99));
181
+
182
+ const encrypted = await service.encryptMasterKey(
183
+ masterKey,
184
+ encryptionKey,
185
+ iv,
186
+ );
187
+
188
+ await expect(
189
+ service.decryptMasterKey(encrypted, encryptionKey, wrongIv),
190
+ ).rejects.toThrow('Decryption failed: Invalid key or corrupted data');
191
+ });
192
+
193
+ it('should produce different ciphertext for same plaintext with different IVs', async () => {
194
+ const masterKey = new Uint8Array(32).fill(42);
195
+ const encryptionKey = Buffer.from(new Uint8Array(32).fill(1));
196
+ const iv1 = Buffer.from(new Uint8Array(16).fill(2));
197
+ const iv2 = Buffer.from(new Uint8Array(16).fill(3));
198
+
199
+ const encrypted1 = await service.encryptMasterKey(
200
+ masterKey,
201
+ encryptionKey,
202
+ iv1,
203
+ );
204
+ const encrypted2 = await service.encryptMasterKey(
205
+ masterKey,
206
+ encryptionKey,
207
+ iv2,
208
+ );
209
+
210
+ expect(encrypted1).not.toEqual(encrypted2);
211
+ });
212
+
213
+ it('should handle empty master key', async () => {
214
+ const masterKey = new Uint8Array(0);
215
+ const encryptionKey = Buffer.from(new Uint8Array(32).fill(1));
216
+ const iv = Buffer.from(new Uint8Array(16).fill(2));
217
+
218
+ const encrypted = await service.encryptMasterKey(
219
+ masterKey,
220
+ encryptionKey,
221
+ iv,
222
+ );
223
+ const decrypted = await service.decryptMasterKey(
224
+ encrypted,
225
+ encryptionKey,
226
+ iv,
227
+ );
228
+
229
+ expect(new Uint8Array(decrypted)).toEqual(masterKey);
230
+ });
231
+ });
232
+
233
+ describe('integration: biometric encryption workflow', () => {
234
+ it('should complete full encryption workflow', async () => {
235
+ const biometricData = Buffer.from('mock-biometric-data');
236
+ const identifier = 'user@example.com';
237
+ const masterKey = new Uint8Array(32).fill(123);
238
+
239
+ // Derive encryption key and IV from biometric data
240
+ const {key, iv} = await service.deriveBiometricEncryptionKey(
241
+ biometricData,
242
+ identifier,
243
+ );
244
+
245
+ // Encrypt master key
246
+ const encrypted = await service.encryptMasterKey(masterKey, key, iv);
247
+
248
+ // Decrypt master key
249
+ const decrypted = await service.decryptMasterKey(encrypted, key, iv);
250
+
251
+ // Verify decrypted matches original
252
+ expect(new Uint8Array(decrypted)).toEqual(masterKey);
253
+ });
254
+
255
+ it('should fail workflow with different biometric data', async () => {
256
+ const biometricData1 = Buffer.from('mock-biometric-data-1');
257
+ const biometricData2 = Buffer.from('mock-biometric-data-2');
258
+ const identifier = 'user@example.com';
259
+ const masterKey = new Uint8Array(32).fill(123);
260
+
261
+ // Encrypt with first biometric data
262
+ const {key: key1, iv} = await service.deriveBiometricEncryptionKey(
263
+ biometricData1,
264
+ identifier,
265
+ );
266
+ const encrypted = await service.encryptMasterKey(masterKey, key1, iv);
267
+
268
+ // Try to decrypt with second biometric data (should fail)
269
+ const {key: key2} = await service.deriveBiometricEncryptionKey(
270
+ biometricData2,
271
+ identifier,
272
+ );
273
+
274
+ await expect(
275
+ service.decryptMasterKey(encrypted, key2, iv),
276
+ ).rejects.toThrow('Decryption failed: Invalid key or corrupted data');
277
+ });
278
+ });
50
279
  });
51
280
  });
@@ -38,4 +38,27 @@ export class EDVServiceRpc extends RpcService {
38
38
  delete(params: any) {
39
39
  return this.call('delete', params);
40
40
  }
41
+
42
+ deriveBiometricKey(biometricData: Buffer, identifier: string) {
43
+ return this.call('deriveBiometricKey', {biometricData, identifier});
44
+ }
45
+
46
+ deriveBiometricEncryptionKey(biometricData: Buffer, identifier: string) {
47
+ return this.call('deriveBiometricEncryptionKey', {
48
+ biometricData,
49
+ identifier,
50
+ });
51
+ }
52
+
53
+ encryptMasterKey(masterKey: Uint8Array, encryptionKey: Buffer, iv: Buffer) {
54
+ return this.call('encryptMasterKey', {masterKey, encryptionKey, iv});
55
+ }
56
+
57
+ decryptMasterKey(
58
+ encryptedKey: Uint8Array,
59
+ decryptionKey: Buffer,
60
+ iv: Buffer,
61
+ ) {
62
+ return this.call('decryptMasterKey', {encryptedKey, decryptionKey, iv});
63
+ }
41
64
  }
@@ -17,6 +17,11 @@ import {getKeypairFromDoc} from '@docknetwork/universal-wallet/methods/keypairs'
17
17
  import {logger} from '@docknetwork/wallet-sdk-data-store/src/logger';
18
18
  import {didService} from '@docknetwork/wallet-sdk-wasm/src/services/dids/service';
19
19
  import {Ed25519Keypair} from '@docknetwork/credential-sdk/keypairs';
20
+ import hkdf from 'futoin-hkdf';
21
+ import crypto from '@docknetwork/universal-wallet/crypto';
22
+
23
+ export const HKDF_LENGTH = 32;
24
+ export const HKDF_HASH = 'SHA-256';
20
25
 
21
26
  /**
22
27
  * Service class for managing Encrypted Data Vaults
@@ -39,6 +44,10 @@ export class EDVService {
39
44
  EDVService.prototype.update,
40
45
  EDVService.prototype.insert,
41
46
  EDVService.prototype.delete,
47
+ EDVService.prototype.deriveBiometricKey,
48
+ EDVService.prototype.deriveBiometricEncryptionKey,
49
+ EDVService.prototype.encryptMasterKey,
50
+ EDVService.prototype.decryptMasterKey,
42
51
  ];
43
52
 
44
53
  /**
@@ -269,6 +278,116 @@ export class EDVService {
269
278
  delete(params: any) {
270
279
  return this.storageInterface.delete(params);
271
280
  }
281
+
282
+ /**
283
+ * Derives a key from biometric data using HKDF
284
+ * @param {Buffer} biometricData - Biometric data from provider
285
+ * @param {string} identifier - User's identifier as salt (email, phone number, etc.)
286
+ * @returns {Buffer} Derived key
287
+ * @example
288
+ * const key = edvService.deriveBiometricKey(biometricData, 'user@example.com');
289
+ */
290
+ deriveBiometricKey(biometricData: Buffer, identifier: string): Buffer {
291
+ const salt = identifier;
292
+ return hkdf(biometricData, HKDF_LENGTH, { salt, hash: HKDF_HASH });
293
+ }
294
+
295
+ /**
296
+ * Generates a key for encrypting/decrypting the master key
297
+ * @param {Buffer} biometricData - Biometric data from provider
298
+ * @param {string} identifier - User's identifier as salt (email, phone number, etc.)
299
+ * @returns {Promise<Object>} Encryption key and IV for AES encryption
300
+ * @returns {Buffer} returns.key - Encryption key
301
+ * @returns {Buffer} returns.iv - Initialization vector
302
+ * @example
303
+ * const { key, iv } = await edvService.deriveBiometricEncryptionKey(biometricData, 'user@example.com');
304
+ */
305
+ async deriveBiometricEncryptionKey(
306
+ biometricData: Buffer,
307
+ identifier: string
308
+ ): Promise<{ key: Buffer; iv: Buffer }> {
309
+ const key = this.deriveBiometricKey(biometricData, identifier);
310
+ const randomBytes = crypto.getRandomValues(new Uint8Array(16));
311
+ const iv = Buffer.from(randomBytes);
312
+
313
+ return {
314
+ key,
315
+ iv
316
+ };
317
+ }
318
+
319
+ /**
320
+ * Encrypts the master key using a key derived from biometric data
321
+ * @param {Uint8Array} masterKey - The CloudWalletVault master key to encrypt
322
+ * @param {Buffer} encryptionKey - Key derived from biometric data
323
+ * @param {Buffer} iv - Initialization vector
324
+ * @returns {Promise<Uint8Array>} Encrypted master key
325
+ * @example
326
+ * const encrypted = await edvService.encryptMasterKey(masterKey, encryptionKey, iv);
327
+ */
328
+ async encryptMasterKey(
329
+ masterKey: Uint8Array,
330
+ encryptionKey: Buffer,
331
+ iv: Buffer
332
+ ): Promise<Uint8Array> {
333
+ const keyData = new Uint8Array(encryptionKey);
334
+ const ivData = new Uint8Array(iv);
335
+
336
+ const key = await crypto.subtle.importKey(
337
+ 'raw',
338
+ keyData,
339
+ { name: 'AES-GCM' },
340
+ false,
341
+ ['encrypt']
342
+ );
343
+
344
+ const encryptedBuffer = await crypto.subtle.encrypt(
345
+ { name: 'AES-GCM', iv: ivData },
346
+ key,
347
+ masterKey
348
+ );
349
+
350
+ return new Uint8Array(encryptedBuffer);
351
+ }
352
+
353
+ /**
354
+ * Decrypts the master key using biometric-derived key
355
+ * @param {Uint8Array} encryptedKey - The encrypted master key
356
+ * @param {Buffer} decryptionKey - Key derived from biometric data
357
+ * @param {Buffer} iv - Initialization vector
358
+ * @returns {Promise<Uint8Array>} The decrypted master key
359
+ * @throws {Error} If decryption fails
360
+ * @example
361
+ * const masterKey = await edvService.decryptMasterKey(encryptedKey, decryptionKey, iv);
362
+ */
363
+ async decryptMasterKey(
364
+ encryptedKey: Uint8Array,
365
+ decryptionKey: Buffer,
366
+ iv: Buffer
367
+ ): Promise<Uint8Array> {
368
+ try {
369
+ const keyData = new Uint8Array(decryptionKey);
370
+ const ivData = new Uint8Array(iv);
371
+
372
+ const key = await crypto.subtle.importKey(
373
+ 'raw',
374
+ keyData,
375
+ { name: 'AES-GCM' },
376
+ false,
377
+ ['decrypt']
378
+ );
379
+
380
+ const decryptedBuffer = await crypto.subtle.decrypt(
381
+ { name: 'AES-GCM', iv: ivData },
382
+ key,
383
+ encryptedKey
384
+ );
385
+
386
+ return new Uint8Array(decryptedBuffer);
387
+ } catch (error) {
388
+ throw new Error('Decryption failed: Invalid key or corrupted data');
389
+ }
390
+ }
272
391
  }
273
392
 
274
393
  /**
@@ -7,6 +7,10 @@ export const validation = {
7
7
  assert(params.credentials, 'credentials is required');
8
8
  assert(params.presentationDefinition, 'presentationDefinition is required');
9
9
  },
10
+ evaluateCredentials: (params: EvaluateCredentialsParams) => {
11
+ assert(params.credentials, 'credentials is required');
12
+ assert(params.presentationDefinition, 'presentationDefinition is required');
13
+ },
10
14
  evaluatePresentation: (params: EvaluatePresentationParams) => {
11
15
  assert(params.presentation, 'presentation is required');
12
16
  assert(params.presentationDefinition, 'presentationDefinition is required');
@@ -24,4 +24,8 @@ export class PEXServiceRPC extends RpcService {
24
24
  async presentationFrom(params: CreatePresentationParams) {
25
25
  return this.call('presentationFrom', params);
26
26
  }
27
+
28
+ async isCredentialSelectionValid(params: EvaluateCredentialsParams) {
29
+ return this.call('isCredentialSelectionValid', params);
30
+ }
27
31
  }
@@ -78,6 +78,7 @@ class PEXService {
78
78
  PEXService.prototype.filterCredentials,
79
79
  PEXService.prototype.evaluatePresentation,
80
80
  PEXService.prototype.presentationFrom,
81
+ PEXService.prototype.isCredentialSelectionValid,
81
82
  ];
82
83
 
83
84
  filterCredentials(params: FilterCredentialsParams) {
@@ -92,6 +93,18 @@ class PEXService {
92
93
  return result;
93
94
  }
94
95
 
96
+ isCredentialSelectionValid(params: EvaluateCredentialsParams) {
97
+ validation.evaluateCredentials(params);
98
+ const {credentials, presentationDefinition, holderDIDs} = params;
99
+ const result = pex.selectFrom(
100
+ removeOptionalAttribute(presentationDefinition),
101
+ credentials,
102
+ holderDIDs,
103
+ );
104
+
105
+ return result.errors.length === 0;
106
+ }
107
+
95
108
  evaluatePresentation(params: EvaluatePresentationParams) {
96
109
  validation.evaluatePresentation(params);
97
110
  const {presentation, presentationDefinition} = params;