@idos-network/credentials 1.5.0 → 2.2.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.
Files changed (82) hide show
  1. package/README.md +289 -85
  2. package/assets/idos-credential-subject-edd-v1.json +10 -0
  3. package/assets/idos-credential-subject-v1.json +1 -1
  4. package/assets/idos-credential-subject-v2.json +1 -1
  5. package/assets/idos-credential-subject-v3.json +83 -0
  6. package/assets/idos-credentials-v1.json +2 -2
  7. package/assets/idos-credentials-v2.json +10 -0
  8. package/dist/index-0NqXMjNk.d.mts +395 -0
  9. package/dist/index-0NqXMjNk.d.mts.map +1 -0
  10. package/dist/index-WW372Tf5.d.mts +57 -0
  11. package/dist/index-WW372Tf5.d.mts.map +1 -0
  12. package/dist/index.mjs +1 -1
  13. package/dist/loader-Cg6hs1-P.mjs +2 -0
  14. package/dist/loader-Cg6hs1-P.mjs.map +1 -0
  15. package/dist/parser/index.d.mts +19 -0
  16. package/dist/parser/index.d.mts.map +1 -0
  17. package/dist/parser/index.mjs +2 -0
  18. package/dist/parser/index.mjs.map +1 -0
  19. package/dist/schemas/index.d.mts +2 -0
  20. package/dist/schemas/index.mjs +1 -0
  21. package/dist/schemas-BVGuUlPe.mjs +2 -0
  22. package/dist/schemas-BVGuUlPe.mjs.map +1 -0
  23. package/dist/types/index.d.mts +2 -134
  24. package/dist/types/index.mjs +1 -63
  25. package/dist/utils/index.d.mts +37 -15
  26. package/dist/utils/index.d.mts.map +1 -1
  27. package/dist/utils/index.mjs +1 -116
  28. package/dist/utils/index.mjs.map +1 -1
  29. package/dist/verifier/index.d.mts +8 -0
  30. package/dist/verifier/index.d.mts.map +1 -0
  31. package/dist/verifier/index.mjs +2 -0
  32. package/dist/verifier/index.mjs.map +1 -0
  33. package/package.json +21 -9
  34. package/src/parser/index.test.ts +266 -0
  35. package/src/parser/index.ts +69 -0
  36. package/src/schemas/EddV1/index.test.ts +40 -0
  37. package/src/schemas/EddV1/index.ts +53 -0
  38. package/src/schemas/Envelope.ts +37 -0
  39. package/src/schemas/FaceIdV1/index.test.ts +26 -0
  40. package/src/schemas/FaceIdV1/index.ts +33 -0
  41. package/src/schemas/KycV1/IdDocument.ts +41 -0
  42. package/src/schemas/KycV1/ResidentialAddress.ts +56 -0
  43. package/src/schemas/KycV1/Subject.ts +86 -0
  44. package/src/schemas/KycV1/index.test.ts +156 -0
  45. package/src/schemas/KycV1/index.ts +40 -0
  46. package/src/schemas/KycV2/Subject.ts +67 -0
  47. package/src/schemas/KycV2/index.test.ts +162 -0
  48. package/src/schemas/KycV2/index.ts +45 -0
  49. package/src/schemas/KycV3/Biometric.ts +14 -0
  50. package/src/schemas/KycV3/Contact.ts +13 -0
  51. package/src/schemas/KycV3/EDD.ts +32 -0
  52. package/src/schemas/KycV3/IdDocument.ts +92 -0
  53. package/src/schemas/KycV3/Onboarding.ts +36 -0
  54. package/src/schemas/KycV3/Person.ts +105 -0
  55. package/src/schemas/KycV3/ResidentialAddress.ts +73 -0
  56. package/src/schemas/KycV3/Screening.ts +27 -0
  57. package/src/schemas/KycV3/SourceOfWealth.ts +44 -0
  58. package/src/schemas/KycV3/Subject.ts +54 -0
  59. package/src/schemas/KycV3/index.test.ts +682 -0
  60. package/src/schemas/KycV3/index.ts +108 -0
  61. package/src/schemas/VerifiableCredential.ts +232 -0
  62. package/src/schemas/enums.ts +126 -0
  63. package/src/schemas/index.ts +14 -0
  64. package/src/schemas/integration.test.ts +251 -0
  65. package/src/schemas/types.ts +11 -0
  66. package/src/schemas/utils.ts +274 -0
  67. package/src/types/credentials.ts +18 -249
  68. package/src/utils/{utils.test.ts → index.test.ts} +59 -67
  69. package/src/utils/index.ts +129 -134
  70. package/src/utils/issuer.ts +42 -0
  71. package/src/{builder → utils}/loader.ts +22 -17
  72. package/src/verifier/index.test.ts +149 -0
  73. package/src/{builder/verifier.ts → verifier/index.ts} +4 -8
  74. package/types/internals.d.ts +11 -6
  75. package/dist/builder/index.d.mts +0 -19
  76. package/dist/builder/index.d.mts.map +0 -1
  77. package/dist/builder/index.mjs +0 -619
  78. package/dist/builder/index.mjs.map +0 -1
  79. package/dist/types/index.d.mts.map +0 -1
  80. package/dist/types/index.mjs.map +0 -1
  81. package/src/builder/builder.test.ts +0 -407
  82. package/src/builder/index.ts +0 -122
@@ -1,255 +1,33 @@
1
- import * as z from "zod";
2
-
3
1
  export type idOSCredential = {
4
2
  id: string;
5
3
  user_id: string;
6
4
  public_notes: string;
7
- content: string;
5
+ content_uri: string;
6
+ content_size: number;
8
7
  encryptor_public_key: string;
9
8
  issuer_auth_public_key: string;
10
9
  original_id?: string | null;
10
+ inserter_type?: string | null;
11
+ inserter_id?: string | null;
12
+ };
13
+
14
+ export type idOSCredentialRecord = Omit<idOSCredential, "content_uri" | "content_size"> & {
15
+ content: string | null;
16
+ content_uri?: string | null;
17
+ content_size?: number | null;
11
18
  };
12
19
 
13
- export type InsertableIDOSCredential = Omit<idOSCredential, "id" | "original_id"> & {
14
- id?: idOSCredential["id"];
15
- content_hash?: string;
20
+ export type SignedCredentialContentReference = {
21
+ public_notes: string;
16
22
  public_notes_signature: string;
17
23
  broader_signature: string;
24
+ issuer_auth_public_key: string;
18
25
  };
19
26
 
20
- // https://github.com/colinhacks/zod/issues/3751
21
- export const CredentialFieldsSchema: z.ZodObject<{
22
- id: z.ZodString;
23
- level: z.ZodString;
24
- issued: z.ZodOptional<z.ZodDate>;
25
- approvedAt: z.ZodOptional<z.ZodDate>;
26
- expirationDate: z.ZodOptional<z.ZodDate>;
27
- }> = z.object({
28
- id: z.string(),
29
-
30
- /* Level of KYC verification performed (e.g., basic, intermediate, advanced). */
31
- level: z.string(),
32
-
33
- /* @default Date.now() */
34
- issued: z.date().optional(),
35
-
36
- /* Date the credential was approved. */
37
- approvedAt: z.date().optional(),
38
-
39
- /* Date the credential was revoked. */
40
- expirationDate: z.date().optional(),
41
- });
42
-
43
- export type CredentialFields = z.infer<typeof CredentialFieldsSchema>;
44
-
45
- // https://github.com/colinhacks/zod/issues/3751
46
- export const CredentialResidentialAddressSchema: z.ZodObject<{
47
- street: z.ZodString;
48
- houseNumber: z.ZodOptional<z.ZodString>;
49
- additionalAddressInfo: z.ZodOptional<z.ZodString>;
50
- region: z.ZodOptional<z.ZodString>;
51
- city: z.ZodString;
52
- postalCode: z.ZodOptional<z.ZodString>;
53
- country: z.ZodString;
54
- proofCategory: z.ZodString;
55
- proofDateOfIssue: z.ZodOptional<z.ZodDate>;
56
- proofFile: z.ZodType<Buffer<ArrayBufferLike>>;
57
- }> = z.object({
58
- /* Street address. */
59
- street: z.string(),
60
-
61
- /* House number. */
62
- houseNumber: z.string().optional(),
63
-
64
- /* Additional address information (e.g., apartment number). */
65
- additionalAddressInfo: z.string().optional(),
66
-
67
- /* Region (e.g., state, province). */
68
- region: z.string().optional(),
69
-
70
- /* Locality (e.g., city, town). */
71
- city: z.string(),
72
-
73
- /* Postal code. */
74
- postalCode: z.string().optional(),
75
-
76
- /* Country (ISO 3166-1 alpha-2). */
77
- country: z.string().min(2).max(2),
78
-
79
- /* Residential Address Proof Category Type of document provided to verify the address(e.g., utility bill, bank statement). */
80
- proofCategory: z.string(),
81
-
82
- /* Residential Address Proof Date Of Issue Date the address proof document was issued. */
83
- proofDateOfIssue: z.date().optional(),
84
-
85
- /* Residential Address Proof File or URL of the document provided as address proof. */
86
- proofFile: z.instanceof(Buffer),
87
- });
88
-
89
- export type CredentialResidentialAddress = z.infer<typeof CredentialResidentialAddressSchema>;
90
-
91
- export const IDDocumentTypeSchema: z.ZodEnum<{
92
- PASSPORT: "PASSPORT";
93
- DRIVERS: "DRIVERS";
94
- ID_CARD: "ID_CARD";
95
- VOTING_CARD: "VOTING_CARD";
96
- PAN_CARD: "PAN_CARD";
97
- INTERNAL_PASSPORT: "INTERNAL_PASSPORT";
98
- RESIDENCE_PERMIT: "RESIDENCE_PERMIT";
99
- }> = z.enum([
100
- "PASSPORT",
101
- "DRIVERS",
102
- "ID_CARD",
103
- "VOTING_CARD",
104
- "PAN_CARD",
105
- "INTERNAL_PASSPORT",
106
- "RESIDENCE_PERMIT",
107
- ]);
108
- export type IDDocumentType = z.infer<typeof IDDocumentTypeSchema>;
109
-
110
- export const GenderSchema: z.ZodEnum<{
111
- M: "M";
112
- F: "F";
113
- OTHER: "OTHER";
114
- }> = z.enum(["M", "F", "OTHER"]);
115
- export type Gender = z.infer<typeof GenderSchema>;
116
-
117
- // https://github.com/colinhacks/zod/issues/3751
118
- export const CredentialSubjectSchema: z.ZodObject<{
119
- id: z.ZodString;
120
- // Indonesian and Indian did not always have first name
121
- firstName: z.ZodOptional<z.ZodString>;
122
- middleName: z.ZodOptional<z.ZodString>;
123
- ssn: z.ZodOptional<z.ZodString>;
124
- gender: z.ZodOptional<typeof GenderSchema>;
125
- nationality: z.ZodOptional<z.ZodString>;
126
- // Indonesian and Indian did not always have family name
127
- familyName: z.ZodOptional<z.ZodString>;
128
- maidenName: z.ZodOptional<z.ZodString>;
129
- email: z.ZodOptional<z.ZodEmail>;
130
- phoneNumber: z.ZodOptional<z.ZodString>;
131
- dateOfBirth: z.ZodDate;
132
- placeOfBirth: z.ZodOptional<z.ZodString>;
133
- idDocumentCountry: z.ZodString;
134
- idDocumentNumber: z.ZodString;
135
- idDocumentType: typeof IDDocumentTypeSchema;
136
- idDocumentDateOfIssue: z.ZodOptional<z.ZodDate>;
137
- idDocumentDateOfExpiry: z.ZodOptional<z.ZodDate>;
138
- idDocumentFrontFile: z.ZodType<Buffer<ArrayBufferLike>>;
139
- idDocumentBackFile: z.ZodOptional<z.ZodType<Buffer<ArrayBufferLike>>>;
140
- selfieFile: z.ZodType<Buffer<ArrayBufferLike>>;
141
- residentialAddress: z.ZodOptional<typeof CredentialResidentialAddressSchema>;
142
- }> = z
143
- .object({
144
- /* ID(unique credential) Unique identifier for the credential itself. */
145
- id: z.string(),
146
-
147
- /* First name. */
148
- firstName: z.string().optional(),
149
-
150
- /* Middle name. */
151
- middleName: z.string().optional(),
152
-
153
- /* Social-security-number (without dashes) */
154
- ssn: z.string().min(9).max(9).optional(),
155
-
156
- /* Nationality (ISO 3166-1 alpha-2). */
157
- nationality: z.string().min(2).max(2).optional(),
158
-
159
- /* Gender (M or F, empty if not provided). */
160
- gender: GenderSchema.optional(),
161
-
162
- /* Family name. */
163
- familyName: z.string().optional(),
164
-
165
- /* Maiden name. */
166
- maidenName: z.string().optional(),
167
-
168
- /* Date of birth. */
169
- dateOfBirth: z.date(),
170
-
171
- /* Place of birth. */
172
- placeOfBirth: z.string().optional(),
173
-
174
- /* Email. */
175
- email: z.email().optional(),
176
-
177
- /* Phone number. */
178
- phoneNumber: z.string().optional(),
179
-
180
- /* Country that issued the identity document (ISO 3166-1 alpha-2). */
181
- idDocumentCountry: z.string().min(2).max(2),
182
-
183
- /* ID Document Number Unique number on the identity document. */
184
- idDocumentNumber: z.string(),
185
-
186
- /* ID Document Type Type of identity document(e.g., Passport, Driver's License, National ID). */
187
- idDocumentType: IDDocumentTypeSchema,
188
-
189
- /* ID Document Date of Issue Date the identity document was issued. */
190
- idDocumentDateOfIssue: z.date().optional(),
191
-
192
- /* ID Document Date of Expiry Expiration date of the identity document - if applicable. */
193
- idDocumentDateOfExpiry: z.date().optional(),
194
-
195
- /* ID Document Front File Buffer with file representing the front of the identity document. */
196
- idDocumentFrontFile: z.instanceof(Buffer),
197
-
198
- /* ID Document Back File Buffer with file representing the back of the identity document - if applicable. */
199
- idDocumentBackFile: z.instanceof(Buffer).optional(),
200
-
201
- /* (ID Document) Selfie File Buffer with selfie with the identity document for verification purposes. */
202
- selfieFile: z.instanceof(Buffer),
203
-
204
- /* Residential Address Full residential address of the individual - if applicable. */
205
- residentialAddress: CredentialResidentialAddressSchema.optional(),
206
- })
207
- .refine(
208
- // At least one of firstName or familyName must be present,
209
- (data) => data.firstName || data.familyName,
210
- { message: "At least one of firstName or familyName must be provided" },
211
- );
212
-
213
- export type CredentialSubject = z.infer<typeof CredentialSubjectSchema>;
214
-
215
- export interface VerifiableCredentialSubject extends Omit<
216
- CredentialSubject,
217
- | "residentialAddress"
218
- | "idDocumentBackFile"
219
- | "idDocumentFrontFile"
220
- | "selfieFile"
221
- | "idDocumentDateOfIssue"
222
- | "idDocumentDateOfExpiry"
223
- | "dateOfBirth"
224
- > {
225
- "@context": string;
226
- // Files are strings in verifiable credentials, but as an input they should be buffers
227
- idDocumentFrontFile?: string;
228
- idDocumentBackFile?: string;
229
- selfieFile?: string;
230
- // Dates are strings in verifiable credentials
231
- dateOfBirth?: string;
232
- idDocumentDateOfIssue?: string;
233
- idDocumentDateOfExpiry?: string;
234
- // This is the residential address flattened fields
235
- residentialAddressStreet?: string;
236
- residentialAddressHouseNumber?: string;
237
- residentialAddressAdditionalAddressInfo?: string;
238
- residentialAddressRegion?: string;
239
- residentialAddressCity?: string;
240
- residentialAddressPostalCode?: string;
241
- residentialAddressCountry?: string;
242
- residentialAddressProofCategory?: string;
243
- // Dates are strings in verifiable credentials
244
- residentialAddressProofDateOfIssue?: string;
245
- // Files are strings in verifiable credentials, but as an input they should be buffers
246
- residentialAddressProofFile?: string;
247
- }
248
-
249
27
  // TODO: This is a stub of the types for @digitalbazaar/vc
250
28
  // when they introduce TypeScript support we should remove this
251
29
  // The copy is here because `types.d.ts` file is not bundled.
252
- export interface VerifiedCredentialsProof {
30
+ export interface VerifiableCredentialProof {
253
31
  type: string;
254
32
  created: string;
255
33
  verificationMethod: string;
@@ -257,26 +35,17 @@ export interface VerifiedCredentialsProof {
257
35
  proofPurpose: string;
258
36
  }
259
37
 
260
- export const CredentialSubjectFaceIdSchema: z.ZodObject<{
261
- faceSignUserId: z.ZodString;
262
- }> = z.object({
263
- faceSignUserId: z.string(),
264
- });
265
-
266
- export type CredentialSubjectFaceId = z.infer<typeof CredentialSubjectFaceIdSchema>;
267
-
268
- export interface VerifiedCredentials<K> {
38
+ export interface VerifiableCredential<K> {
269
39
  "@context": string[];
270
40
  type: string[];
271
41
  issuer: string;
272
42
  id: string;
273
43
  level: string;
44
+ kycLevel?: number;
274
45
  issued: string;
275
46
  approvedAt: string;
276
- expirationDate: string;
47
+ expirationDate?: string;
277
48
  credentialSubject: K;
278
49
  issuanceDate: string;
279
- proof: VerifiedCredentialsProof;
50
+ proof: VerifiableCredentialProof;
280
51
  }
281
-
282
- export type VerifiableCredential<K> = VerifiedCredentials<K>;
@@ -1,26 +1,18 @@
1
+ import { hexEncode, utf8Encode } from "@idos-network/utils/codecs";
2
+ import nacl from "tweetnacl";
1
3
  import { describe, expect, it } from "vitest";
2
4
 
3
- import type { CredentialSubject } from "../types";
4
-
5
5
  import {
6
- deriveLevel,
6
+ buildEphemeralSignedCredentialContentReference,
7
+ buildPreliminaryIDOSCredential,
8
+ buildSignedCredentialContentReference,
7
9
  highestMatchingCredential,
8
10
  matchLevelOrHigher,
9
11
  pickHighestMatchingLevel,
10
12
  recordFilter,
11
- } from "./";
12
-
13
- const defaultCredential: CredentialSubject = {
14
- id: "uuid:1234",
15
- firstName: "John",
16
- familyName: "Doe",
17
- idDocumentType: "PASSPORT",
18
- dateOfBirth: new Date("1990-01-01"),
19
- idDocumentCountry: "US",
20
- idDocumentNumber: "123456789",
21
- idDocumentFrontFile: Buffer.from("ID Document Front"),
22
- selfieFile: Buffer.alloc(0),
23
- };
13
+ type Addon,
14
+ type BaseLevel,
15
+ } from ".";
24
16
 
25
17
  describe("recordFilter", () => {
26
18
  [
@@ -76,6 +68,9 @@ describe("recordFilter", () => {
76
68
 
77
69
  describe("matchLevelOrHigher", () => {
78
70
  [
71
+ ["unverified", [], "unverified", true],
72
+ ["unverified", [], "basic", true],
73
+ ["basic", [], "unverified", false],
79
74
  ["basic", [], "basic+liveness", true],
80
75
  ["plus", [], "plus+liveness", true],
81
76
  ["plus", [], "basic", false],
@@ -86,11 +81,7 @@ describe("matchLevelOrHigher", () => {
86
81
  ].forEach(([level, requiredAddons, testLevel, expected]) => {
87
82
  it(`level=${level} requiredAddons=[${(requiredAddons as string[]).join(",")}] testLevel=${testLevel} => ${expected}`, () => {
88
83
  expect(
89
- matchLevelOrHigher(
90
- level as "basic" | "plus",
91
- requiredAddons as ("liveness" | "email" | "phoneNumber")[],
92
- testLevel as string,
93
- ),
84
+ matchLevelOrHigher(level as BaseLevel, requiredAddons as Addon[], testLevel as string),
94
85
  ).toBe(expected as boolean);
95
86
  });
96
87
  });
@@ -116,6 +107,12 @@ describe("pickHighestMatchingLevel", () => {
116
107
  ["email", "phoneNumber"],
117
108
  null,
118
109
  ],
110
+ [
111
+ ["unverified+phoneNumber", "basic+phoneNumber", "plus+phoneNumber"],
112
+ "unverified",
113
+ ["phoneNumber"],
114
+ "plus+phoneNumber",
115
+ ],
119
116
  [["basic+liveness", "plus+liveness"], "basic", ["liveness"], "plus+liveness"],
120
117
  ].forEach(([levels, requiredLevel, requiredAddons, expected]) => {
121
118
  it(`levels=${levels} requiredLevel=${requiredLevel} requiredAddons=[${(requiredAddons as string[]).join(",")}] => ${expected}`, () => {
@@ -247,57 +244,52 @@ describe("highestMatchingCredential", () => {
247
244
  });
248
245
  });
249
246
 
250
- describe("deriveLevel", () => {
251
- it("basic only", () => {
252
- expect(
253
- deriveLevel({
254
- ...defaultCredential,
255
- // @ts-expect-error - to test absence of selfieFile
256
- selfieFile: undefined,
257
- }),
258
- ).toBe("basic");
247
+ describe("buildSignedCredentialContentReference", () => {
248
+ it("derives issuer_auth_public_key from the signing secret key", () => {
249
+ const keyPair = nacl.sign.keyPair();
250
+ const result = buildSignedCredentialContentReference("", "ipfs://cid", keyPair.secretKey);
251
+
252
+ expect(result.public_notes).toBe("");
253
+ expect(result.public_notes_signature).toBeTruthy();
254
+ expect(result.broader_signature).toBeTruthy();
255
+ expect(result.issuer_auth_public_key).toBe(hexEncode(keyPair.publicKey, true));
259
256
  });
257
+ });
260
258
 
261
- it("basic+liveness", () => {
262
- expect(
263
- deriveLevel({
264
- ...defaultCredential,
265
- }),
266
- ).toBe("basic+liveness");
259
+ describe("buildEphemeralSignedCredentialContentReference", () => {
260
+ it("returns a signed reference with a public key", () => {
261
+ const result = buildEphemeralSignedCredentialContentReference("", "ipfs://cid");
262
+
263
+ expect(result.public_notes).toBe("");
264
+ expect(result.public_notes_signature).toBeTruthy();
265
+ expect(result.broader_signature).toBeTruthy();
266
+ expect(result.issuer_auth_public_key).toMatch(/^(0x)?[0-9a-f]+$/i);
267
267
  });
268
+ });
268
269
 
269
- it("plus+liveness", () => {
270
- expect(
271
- deriveLevel({
272
- ...defaultCredential,
273
- residentialAddress: {
274
- street: "123 Main St",
275
- city: "Anytown",
276
- postalCode: "12345",
277
- country: "US",
278
- proofCategory: "UTILITY_BILL",
279
- proofFile: Buffer.from("Utility Bill"),
280
- },
281
- }),
282
- ).toBe("plus+liveness");
270
+ describe("buildPreliminaryIDOSCredential", () => {
271
+ const recipient = nacl.box.keyPair();
272
+
273
+ it("hashes encrypted content to an ipfs:// uri by default", async () => {
274
+ const result = await buildPreliminaryIDOSCredential({
275
+ publicNotes: "{}",
276
+ plaintextContent: utf8Encode("secret"),
277
+ recipientEncryptionPublicKey: recipient.publicKey,
278
+ });
279
+
280
+ expect(result.contentUri).toMatch(/^ipfs:\/\//);
281
+ expect(result.contentSize).toBe(result.encryptedContent.byteLength);
283
282
  });
284
283
 
285
- it("plus+liveness+phoneNumber", () => {
286
- expect(
287
- deriveLevel({
288
- ...defaultCredential,
289
- selfieFile: Buffer.from("Selfie"),
290
- phoneNumber: "+1234567890",
291
- email: "john.doe@example.com",
292
- residentialAddress: {
293
- street: "123 Main St",
294
- city: "Anytown",
295
- postalCode: "12345",
296
- country: "US",
297
- proofCategory: "UTILITY_BILL",
298
- proofFile: Buffer.from("Utility Bill"),
299
- },
300
- }),
301
- ).toBe("plus+liveness+email+phoneNumber");
284
+ it("uses a provided contentUri instead of hashing to ipfs", async () => {
285
+ const result = await buildPreliminaryIDOSCredential({
286
+ publicNotes: "{}",
287
+ plaintextContent: utf8Encode("secret"),
288
+ recipientEncryptionPublicKey: recipient.publicKey,
289
+ contentUri: "ukyc://storage-abc/blobs/blob-1",
290
+ });
291
+
292
+ expect(result.contentUri).toBe("ukyc://storage-abc/blobs/blob-1");
293
+ expect(result.contentSize).toBe(result.encryptedContent.byteLength);
302
294
  });
303
295
  });