@cofhe/sdk 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/adapters/ethers6.ts +28 -28
  3. package/adapters/hardhat.ts +0 -1
  4. package/adapters/index.test.ts +14 -19
  5. package/adapters/smartWallet.ts +81 -73
  6. package/adapters/test-utils.ts +45 -45
  7. package/adapters/types.ts +3 -3
  8. package/chains/chains/localcofhe.ts +14 -0
  9. package/chains/chains.test.ts +2 -1
  10. package/chains/defineChain.ts +2 -2
  11. package/chains/index.ts +3 -1
  12. package/chains/types.ts +3 -3
  13. package/core/baseBuilder.ts +30 -49
  14. package/core/client.test.ts +200 -72
  15. package/core/client.ts +152 -148
  16. package/core/clientTypes.ts +114 -0
  17. package/core/config.test.ts +30 -11
  18. package/core/config.ts +26 -13
  19. package/core/consts.ts +18 -0
  20. package/core/decrypt/cofheMocksSealOutput.ts +2 -4
  21. package/core/decrypt/decryptHandleBuilder.ts +51 -45
  22. package/core/decrypt/{tnSealOutput.ts → tnSealOutputV1.ts} +1 -1
  23. package/core/decrypt/tnSealOutputV2.ts +298 -0
  24. package/core/encrypt/cofheMocksZkVerifySign.ts +15 -16
  25. package/core/encrypt/encryptInputsBuilder.test.ts +132 -116
  26. package/core/encrypt/encryptInputsBuilder.ts +159 -111
  27. package/core/encrypt/encryptUtils.ts +6 -3
  28. package/core/encrypt/zkPackProveVerify.ts +70 -8
  29. package/core/error.ts +0 -2
  30. package/core/fetchKeys.test.ts +1 -18
  31. package/core/fetchKeys.ts +0 -26
  32. package/core/index.ts +37 -17
  33. package/core/keyStore.ts +65 -38
  34. package/core/permits.test.ts +255 -4
  35. package/core/permits.ts +83 -18
  36. package/core/types.ts +198 -152
  37. package/core/utils.ts +43 -1
  38. package/dist/adapters.d.cts +38 -20
  39. package/dist/adapters.d.ts +38 -20
  40. package/dist/chains.cjs +18 -8
  41. package/dist/chains.d.cts +31 -9
  42. package/dist/chains.d.ts +31 -9
  43. package/dist/chains.js +1 -1
  44. package/dist/{chunk-KFGPTJ6X.js → chunk-I5WFEYXX.js} +1768 -1526
  45. package/dist/{chunk-LU7BMUUT.js → chunk-R3B5TMVX.js} +330 -197
  46. package/dist/{chunk-GZCQQYVI.js → chunk-TBLR7NNE.js} +18 -9
  47. package/dist/{types-PhwGgQvs.d.ts → clientTypes-RqkgkV2i.d.ts} +331 -429
  48. package/dist/{types-bB7wLj0q.d.cts → clientTypes-e4filDzK.d.cts} +331 -429
  49. package/dist/core.cjs +3000 -2625
  50. package/dist/core.d.cts +113 -7
  51. package/dist/core.d.ts +113 -7
  52. package/dist/core.js +3 -3
  53. package/dist/node.cjs +2851 -2526
  54. package/dist/node.d.cts +4 -4
  55. package/dist/node.d.ts +4 -4
  56. package/dist/node.js +4 -3
  57. package/dist/{permit-S9CnI6MF.d.cts → permit-MZ502UBl.d.cts} +54 -41
  58. package/dist/{permit-S9CnI6MF.d.ts → permit-MZ502UBl.d.ts} +54 -41
  59. package/dist/permits.cjs +328 -195
  60. package/dist/permits.d.cts +113 -825
  61. package/dist/permits.d.ts +113 -825
  62. package/dist/permits.js +1 -1
  63. package/dist/types-YiAC4gig.d.cts +33 -0
  64. package/dist/types-YiAC4gig.d.ts +33 -0
  65. package/dist/web.cjs +3067 -2527
  66. package/dist/web.d.cts +22 -6
  67. package/dist/web.d.ts +22 -6
  68. package/dist/web.js +185 -9
  69. package/dist/zkProve.worker.cjs +93 -0
  70. package/dist/zkProve.worker.d.cts +2 -0
  71. package/dist/zkProve.worker.d.ts +2 -0
  72. package/dist/zkProve.worker.js +91 -0
  73. package/node/client.test.ts +20 -25
  74. package/node/encryptInputs.test.ts +18 -38
  75. package/node/index.ts +1 -0
  76. package/package.json +15 -15
  77. package/permits/index.ts +1 -0
  78. package/permits/localstorage.test.ts +9 -14
  79. package/permits/onchain-utils.ts +221 -0
  80. package/permits/permit.test.ts +76 -27
  81. package/permits/permit.ts +58 -95
  82. package/permits/sealing.test.ts +3 -3
  83. package/permits/sealing.ts +2 -2
  84. package/permits/store.test.ts +10 -50
  85. package/permits/store.ts +9 -21
  86. package/permits/test-utils.ts +11 -3
  87. package/permits/types.ts +39 -9
  88. package/permits/utils.ts +0 -5
  89. package/permits/validation.test.ts +29 -32
  90. package/permits/validation.ts +114 -176
  91. package/web/client.web.test.ts +20 -25
  92. package/web/config.web.test.ts +0 -2
  93. package/web/encryptInputs.web.test.ts +31 -54
  94. package/web/index.ts +65 -1
  95. package/web/storage.ts +19 -5
  96. package/web/worker.builder.web.test.ts +148 -0
  97. package/web/worker.config.web.test.ts +329 -0
  98. package/web/worker.output.web.test.ts +84 -0
  99. package/web/workerManager.test.ts +80 -0
  100. package/web/workerManager.ts +214 -0
  101. package/web/workerManager.web.test.ts +114 -0
  102. package/web/zkProve.worker.ts +133 -0
  103. package/core/result.test.ts +0 -180
  104. package/core/result.ts +0 -67
  105. package/core/test-utils.ts +0 -45
  106. package/dist/types-KImPrEIe.d.cts +0 -48
  107. package/dist/types-KImPrEIe.d.ts +0 -48
@@ -1,42 +1,48 @@
1
1
  import { z } from 'zod';
2
- import { isAddress, zeroAddress } from 'viem';
3
- import { type Permit, type ValidationResult } from './types.js';
4
- import { is0xPrefixed } from './utils.js';
2
+ import { getAddress, isAddress, isHex, zeroAddress, type Hex } from 'viem';
3
+ import type { Permit, ValidationResult } from './types.js';
5
4
 
6
5
  const SerializedSealingPair = z.object({
7
6
  privateKey: z.string(),
8
7
  publicKey: z.string(),
9
8
  });
10
9
 
10
+ export const addressSchema = z
11
+ .string()
12
+ .refine((val) => isAddress(val), {
13
+ error: 'Invalid address',
14
+ })
15
+ .transform((val): Hex => getAddress(val));
16
+
17
+ export const addressNotZeroSchema = addressSchema.refine((val) => val !== zeroAddress, {
18
+ error: 'Must not be zeroAddress',
19
+ });
20
+
21
+ export const bytesSchema = z.custom<Hex>(
22
+ (val) => {
23
+ return typeof val === 'string' && isHex(val);
24
+ },
25
+ {
26
+ message: 'Invalid hex value',
27
+ }
28
+ );
29
+
30
+ export const bytesNotEmptySchema = bytesSchema.refine((val) => val !== '0x', {
31
+ error: 'Must not be empty',
32
+ });
33
+
34
+ const DEFAULT_EXPIRATION_FN = () => Math.round(Date.now() / 1000) + 7 * 24 * 60 * 60; // 7 days from now
35
+
11
36
  const zPermitWithDefaults = z.object({
12
37
  name: z.string().optional().default('Unnamed Permit'),
13
38
  type: z.enum(['self', 'sharing', 'recipient']),
14
- issuer: z
15
- .string()
16
- .refine((val) => isAddress(val), {
17
- message: 'Permit issuer :: invalid address',
18
- })
19
- .refine((val) => val !== zeroAddress, {
20
- message: 'Permit issuer :: must not be zeroAddress',
21
- }),
22
- expiration: z.number().optional().default(1000000000000),
23
- recipient: z
24
- .string()
25
- .optional()
26
- .default(zeroAddress)
27
- .refine((val) => isAddress(val), {
28
- message: 'Permit recipient :: invalid address',
29
- }),
30
- validatorId: z.number().optional().default(0),
31
- validatorContract: z
32
- .string()
33
- .optional()
34
- .default(zeroAddress)
35
- .refine((val) => isAddress(val), {
36
- message: 'Permit validatorContract :: invalid address',
37
- }),
38
- issuerSignature: z.string().optional().default('0x'),
39
- recipientSignature: z.string().optional().default('0x'),
39
+ issuer: addressNotZeroSchema,
40
+ expiration: z.int().optional().default(DEFAULT_EXPIRATION_FN),
41
+ recipient: addressSchema.optional().default(zeroAddress),
42
+ validatorId: z.int().optional().default(0),
43
+ validatorContract: addressSchema.optional().default(zeroAddress),
44
+ issuerSignature: bytesSchema.optional().default('0x'),
45
+ recipientSignature: bytesSchema.optional().default('0x'),
40
46
  });
41
47
 
42
48
  const zPermitWithSealingPair = zPermitWithDefaults.extend({
@@ -50,16 +56,27 @@ type zPermitType = z.infer<typeof zPermitWithDefaults>;
50
56
  * this check ensures that IF an external validator is applied, that both `validatorId` and `validatorContract` are populated,
51
57
  * ELSE ensures that both `validatorId` and `validatorContract` are empty
52
58
  */
53
- const ValidatorContractRefinement = [
59
+ const ExternalValidatorRefinement = [
54
60
  (data: zPermitType) =>
55
61
  (data.validatorId !== 0 && data.validatorContract !== zeroAddress) ||
56
62
  (data.validatorId === 0 && data.validatorContract === zeroAddress),
57
63
  {
58
- message: 'Permit external validator :: validatorId and validatorContract must either both be set or both be unset.',
64
+ error: 'Permit external validator :: validatorId and validatorContract must either both be set or both be unset.',
59
65
  path: ['validatorId', 'validatorContract'] as string[],
60
66
  },
61
67
  ] as const;
62
68
 
69
+ /**
70
+ * Prevents sharable permit from having the same issuer and recipient
71
+ */
72
+ const RecipientRefinement = [
73
+ (data: zPermitType) => data.issuer !== data.recipient,
74
+ {
75
+ error: 'Sharing permit :: issuer and recipient must not be the same',
76
+ path: ['issuer', 'recipient'] as string[],
77
+ },
78
+ ] as const;
79
+
63
80
  // ============================================================================
64
81
  // SELF PERMIT VALIDATORS
65
82
  // ============================================================================
@@ -70,68 +87,34 @@ const ValidatorContractRefinement = [
70
87
  export const SelfPermitOptionsValidator = z
71
88
  .object({
72
89
  type: z.literal('self').optional().default('self'),
73
- issuer: z
74
- .string()
75
- .refine((val) => isAddress(val), {
76
- message: 'Self permit issuer :: invalid address',
77
- })
78
- .refine((val) => val !== zeroAddress, {
79
- message: 'Self permit issuer :: must not be zeroAddress',
80
- }),
90
+ issuer: addressNotZeroSchema,
81
91
  name: z.string().optional().default('Unnamed Permit'),
82
- expiration: z.number().optional().default(1000000000000),
83
- recipient: z
84
- .string()
85
- .optional()
86
- .default(zeroAddress)
87
- .refine((val) => isAddress(val), {
88
- message: 'Self permit recipient :: invalid address',
89
- })
90
- .refine((val) => val === zeroAddress, {
91
- message: 'Self permit recipient :: must be zeroAddress',
92
- }),
93
- validatorId: z.number().optional().default(0),
94
- validatorContract: z
95
- .string()
96
- .optional()
97
- .default(zeroAddress)
98
- .refine((val) => isAddress(val), {
99
- message: 'Self permit validatorContract :: invalid address',
100
- }),
101
- issuerSignature: z
102
- .string()
103
- .optional()
104
- .default('0x')
105
- .refine((val) => is0xPrefixed(val), {
106
- message: 'Self permit issuerSignature :: must be 0x prefixed',
107
- }),
108
- recipientSignature: z
109
- .string()
110
- .optional()
111
- .default('0x')
112
- .refine((val) => is0xPrefixed(val), {
113
- message: 'Self permit recipientSignature :: must be 0x prefixed',
114
- }),
92
+ expiration: z.int().optional().default(DEFAULT_EXPIRATION_FN),
93
+ recipient: addressSchema.optional().default(zeroAddress),
94
+ validatorId: z.int().optional().default(0),
95
+ validatorContract: addressSchema.optional().default(zeroAddress),
96
+ issuerSignature: bytesSchema.optional().default('0x'),
97
+ recipientSignature: bytesSchema.optional().default('0x'),
115
98
  })
116
- .refine(...ValidatorContractRefinement);
99
+ .refine(...ExternalValidatorRefinement);
117
100
 
118
101
  /**
119
102
  * Validator for fully formed self permits
120
103
  */
121
104
  export const SelfPermitValidator = zPermitWithSealingPair
122
105
  .refine((data) => data.type === 'self', {
123
- message: "Self permit :: type must be 'self'",
106
+ error: "Type must be 'self'",
124
107
  })
125
108
  .refine((data) => data.recipient === zeroAddress, {
126
- message: 'Self permit :: recipient must be zeroAddress',
109
+ error: 'Recipient must be zeroAddress',
127
110
  })
128
111
  .refine((data) => data.issuerSignature !== '0x', {
129
- message: 'Self permit :: issuerSignature must be populated',
112
+ error: 'IssuerSignature must be populated',
130
113
  })
131
114
  .refine((data) => data.recipientSignature === '0x', {
132
- message: 'Self permit :: recipientSignature must be empty',
115
+ error: 'RecipientSignature must be empty',
133
116
  })
134
- .refine(...ValidatorContractRefinement);
117
+ .refine(...ExternalValidatorRefinement);
135
118
 
136
119
  // ============================================================================
137
120
  // SHARING PERMIT VALIDATORS
@@ -143,66 +126,35 @@ export const SelfPermitValidator = zPermitWithSealingPair
143
126
  export const SharingPermitOptionsValidator = z
144
127
  .object({
145
128
  type: z.literal('sharing').optional().default('sharing'),
146
- issuer: z
147
- .string()
148
- .refine((val) => isAddress(val), {
149
- message: 'Sharing permit issuer :: invalid address',
150
- })
151
- .refine((val) => val !== zeroAddress, {
152
- message: 'Sharing permit issuer :: must not be zeroAddress',
153
- }),
154
- recipient: z
155
- .string()
156
- .refine((val) => isAddress(val), {
157
- message: 'Sharing permit recipient :: invalid address',
158
- })
159
- .refine((val) => val !== zeroAddress, {
160
- message: 'Sharing permit recipient :: must not be zeroAddress',
161
- }),
129
+ issuer: addressNotZeroSchema,
130
+ recipient: addressNotZeroSchema,
162
131
  name: z.string().optional().default('Unnamed Permit'),
163
- expiration: z.number().optional().default(1000000000000),
164
- validatorId: z.number().optional().default(0),
165
- validatorContract: z
166
- .string()
167
- .optional()
168
- .default(zeroAddress)
169
- .refine((val) => isAddress(val), {
170
- message: 'Sharing permit validatorContract :: invalid address',
171
- }),
172
- issuerSignature: z
173
- .string()
174
- .optional()
175
- .default('0x')
176
- .refine((val) => is0xPrefixed(val), {
177
- message: 'Sharing permit issuerSignature :: must be 0x prefixed',
178
- }),
179
- recipientSignature: z
180
- .string()
181
- .optional()
182
- .default('0x')
183
- .refine((val) => is0xPrefixed(val), {
184
- message: 'Sharing permit recipientSignature :: must be 0x prefixed',
185
- }),
132
+ expiration: z.int().optional().default(DEFAULT_EXPIRATION_FN),
133
+ validatorId: z.int().optional().default(0),
134
+ validatorContract: addressSchema.optional().default(zeroAddress),
135
+ issuerSignature: bytesSchema.optional().default('0x'),
136
+ recipientSignature: bytesSchema.optional().default('0x'),
186
137
  })
187
- .refine(...ValidatorContractRefinement);
138
+ .refine(...RecipientRefinement)
139
+ .refine(...ExternalValidatorRefinement);
188
140
 
189
141
  /**
190
142
  * Validator for fully formed sharing permits
191
143
  */
192
144
  export const SharingPermitValidator = zPermitWithSealingPair
193
145
  .refine((data) => data.type === 'sharing', {
194
- message: "Sharing permit :: type must be 'sharing'",
146
+ error: "Type must be 'sharing'",
195
147
  })
196
148
  .refine((data) => data.recipient !== zeroAddress, {
197
- message: 'Sharing permit :: recipient must not be zeroAddress',
149
+ error: 'Recipient must not be zeroAddress',
198
150
  })
199
151
  .refine((data) => data.issuerSignature !== '0x', {
200
- message: 'Sharing permit :: issuerSignature must be populated',
152
+ error: 'IssuerSignature must be populated',
201
153
  })
202
154
  .refine((data) => data.recipientSignature === '0x', {
203
- message: 'Sharing permit :: recipientSignature must be empty',
155
+ error: 'RecipientSignature must be empty',
204
156
  })
205
- .refine(...ValidatorContractRefinement);
157
+ .refine(...ExternalValidatorRefinement);
206
158
 
207
159
  // ============================================================================
208
160
  // IMPORT/RECIPIENT PERMIT VALIDATORS
@@ -214,101 +166,87 @@ export const SharingPermitValidator = zPermitWithSealingPair
214
166
  export const ImportPermitOptionsValidator = z
215
167
  .object({
216
168
  type: z.literal('recipient').optional().default('recipient'),
217
- issuer: z
218
- .string()
219
- .refine((val) => isAddress(val), {
220
- message: 'Import permit issuer :: invalid address',
221
- })
222
- .refine((val) => val !== zeroAddress, {
223
- message: 'Import permit issuer :: must not be zeroAddress',
224
- }),
225
- recipient: z
226
- .string()
227
- .refine((val) => isAddress(val), {
228
- message: 'Import permit recipient :: invalid address',
229
- })
230
- .refine((val) => val !== zeroAddress, {
231
- message: 'Import permit recipient :: must not be zeroAddress',
232
- }),
233
- issuerSignature: z
234
- .string()
235
- .refine((val) => is0xPrefixed(val), {
236
- message: 'Import permit issuerSignature :: must be 0x prefixed',
237
- })
238
- .refine((val) => val !== '0x', {
239
- message: 'Import permit :: issuerSignature must be provided',
240
- }),
169
+ issuer: addressNotZeroSchema,
170
+ recipient: addressNotZeroSchema,
241
171
  name: z.string().optional().default('Unnamed Permit'),
242
- expiration: z.number().optional().default(1000000000000),
243
- validatorId: z.number().optional().default(0),
244
- validatorContract: z
245
- .string()
246
- .optional()
247
- .default(zeroAddress)
248
- .refine((val) => isAddress(val), {
249
- message: 'Import permit validatorContract :: invalid address',
250
- }),
251
- recipientSignature: z
252
- .string()
253
- .optional()
254
- .default('0x')
255
- .refine((val) => is0xPrefixed(val), {
256
- message: 'Import permit recipientSignature :: must be 0x prefixed',
257
- }),
172
+ expiration: z.int(),
173
+ validatorId: z.int().optional().default(0),
174
+ validatorContract: addressSchema.optional().default(zeroAddress),
175
+ issuerSignature: bytesNotEmptySchema,
176
+ recipientSignature: bytesSchema.optional().default('0x'),
258
177
  })
259
- .refine(...ValidatorContractRefinement);
178
+ .refine(...ExternalValidatorRefinement);
260
179
 
261
180
  /**
262
181
  * Validator for fully formed import/recipient permits
263
182
  */
264
183
  export const ImportPermitValidator = zPermitWithSealingPair
265
184
  .refine((data) => data.type === 'recipient', {
266
- message: "Import permit :: type must be 'recipient'",
185
+ error: "Type must be 'recipient'",
267
186
  })
268
187
  .refine((data) => data.recipient !== zeroAddress, {
269
- message: 'Import permit :: recipient must not be zeroAddress',
188
+ error: 'Recipient must not be zeroAddress',
270
189
  })
271
190
  .refine((data) => data.issuerSignature !== '0x', {
272
- message: 'Import permit :: issuerSignature must be populated',
191
+ error: 'IssuerSignature must be populated',
273
192
  })
274
193
  .refine((data) => data.recipientSignature !== '0x', {
275
- message: 'Import permit :: recipientSignature must be populated',
194
+ error: 'RecipientSignature must be populated',
276
195
  })
277
- .refine(...ValidatorContractRefinement);
196
+ .refine(...ExternalValidatorRefinement);
278
197
 
279
198
  // ============================================================================
280
199
  // VALIDATION FUNCTIONS
281
200
  // ============================================================================
282
201
 
202
+ const safeParseAndThrowFormatted = <T extends z.ZodTypeAny>(schema: T, data: unknown, message: string): z.output<T> => {
203
+ const result = schema.safeParse(data);
204
+ if (!result.success) {
205
+ throw new Error(`${message}: ${z.prettifyError(result.error)}`, { cause: result.error });
206
+ }
207
+ return result.data;
208
+ };
209
+
283
210
  /**
284
211
  * Validates self permit creation options
285
212
  */
286
- export const validateSelfPermitOptions = (options: any) => SelfPermitOptionsValidator.safeParse(options);
287
-
213
+ export const validateSelfPermitOptions = (options: any) => {
214
+ return safeParseAndThrowFormatted(SelfPermitOptionsValidator, options, 'Invalid self permit options');
215
+ };
288
216
  /**
289
217
  * Validates sharing permit creation options
290
218
  */
291
- export const validateSharingPermitOptions = (options: any) => SharingPermitOptionsValidator.safeParse(options);
219
+ export const validateSharingPermitOptions = (options: any) => {
220
+ return safeParseAndThrowFormatted(SharingPermitOptionsValidator, options, 'Invalid sharing permit options');
221
+ };
292
222
 
293
223
  /**
294
224
  * Validates import permit creation options
295
225
  */
296
- export const validateImportPermitOptions = (options: any) => ImportPermitOptionsValidator.safeParse(options);
226
+ export const validateImportPermitOptions = (options: any) => {
227
+ return safeParseAndThrowFormatted(ImportPermitOptionsValidator, options, 'Invalid import permit options');
228
+ };
297
229
 
298
230
  /**
299
231
  * Validates a fully formed self permit
300
232
  */
301
- export const validateSelfPermit = (permit: any) => SelfPermitValidator.safeParse(permit);
233
+ export const validateSelfPermit = (permit: any) => {
234
+ return safeParseAndThrowFormatted(SelfPermitValidator, permit, 'Invalid self permit');
235
+ };
302
236
 
303
237
  /**
304
238
  * Validates a fully formed sharing permit
305
239
  */
306
- export const validateSharingPermit = (permit: any) => SharingPermitValidator.safeParse(permit);
240
+ export const validateSharingPermit = (permit: any) => {
241
+ return safeParseAndThrowFormatted(SharingPermitValidator, permit, 'Invalid sharing permit');
242
+ };
307
243
 
308
244
  /**
309
245
  * Validates a fully formed import/recipient permit
310
246
  */
311
- export const validateImportPermit = (permit: any) => ImportPermitValidator.safeParse(permit);
247
+ export const validateImportPermit = (permit: any) => {
248
+ return safeParseAndThrowFormatted(ImportPermitValidator, permit, 'Invalid import permit');
249
+ };
312
250
 
313
251
  /**
314
252
  * Simple validation functions for common checks
@@ -1,4 +1,4 @@
1
- import { type CofhesdkClient } from '@/core';
1
+ import { CofhesdkErrorCode, CofhesdkError, type CofhesdkClient } from '@/core';
2
2
  import { arbSepolia as cofhesdkArbSepolia } from '@/chains';
3
3
 
4
4
  import { describe, it, expect, beforeAll, beforeEach, vi } from 'vitest';
@@ -60,11 +60,16 @@ describe('@cofhe/web - Client', () => {
60
60
  });
61
61
  });
62
62
 
63
+ describe('Environment', () => {
64
+ it('should have the correct environment', () => {
65
+ expect(cofhesdkClient.config.environment).toBe('web');
66
+ });
67
+ });
68
+
63
69
  describe('Connection', () => {
64
70
  it('should connect to real chain', async () => {
65
- const result = await cofhesdkClient.connect(publicClient, walletClient);
71
+ await cofhesdkClient.connect(publicClient, walletClient);
66
72
 
67
- expect(result.success).toBe(true);
68
73
  expect(cofhesdkClient.connected).toBe(true);
69
74
 
70
75
  const snapshot = cofhesdkClient.getSnapshot();
@@ -74,15 +79,17 @@ describe('@cofhe/web - Client', () => {
74
79
  }, 30000);
75
80
 
76
81
  it('should handle network errors', async () => {
77
- const result = await cofhesdkClient.connect(
78
- {
79
- getChainId: vi.fn().mockRejectedValue(new Error('Network error')),
80
- } as unknown as PublicClient,
81
- walletClient
82
- );
83
-
84
- expect(result.success).toBe(false);
85
- expect(cofhesdkClient.connected).toBe(false);
82
+ try {
83
+ await cofhesdkClient.connect(
84
+ {
85
+ getChainId: vi.fn().mockRejectedValue(new Error('Network error')),
86
+ } as unknown as PublicClient,
87
+ walletClient
88
+ );
89
+ } catch (error) {
90
+ expect(error).toBeInstanceOf(CofhesdkError);
91
+ expect((error as CofhesdkError).code).toBe(CofhesdkErrorCode.PublicWalletGetChainIdFailed);
92
+ }
86
93
  }, 30000);
87
94
  });
88
95
 
@@ -113,23 +120,11 @@ describe('@cofhe/web - Client', () => {
113
120
  }, 30000);
114
121
  });
115
122
 
116
- describe('Initialization Results', () => {
117
- it('should have keyFetchResult promise', () => {
118
- expect(cofhesdkClient.initializationResults).toBeDefined();
119
- expect(cofhesdkClient.initializationResults.keyFetchResult).toBeInstanceOf(Promise);
120
- });
121
-
122
- it('should resolve keyFetchResult', async () => {
123
- const result = await cofhesdkClient.initializationResults.keyFetchResult;
124
- expect(result.success).toBe(true);
125
- });
126
- });
127
-
128
123
  describe('Builder Creation', () => {
129
124
  it('should create encrypt builder after connection', async () => {
130
125
  await cofhesdkClient.connect(publicClient, walletClient);
131
126
 
132
- const builder = cofhesdkClient.encryptInputs([{ data: 100n, utype: 2 }]);
127
+ const builder = cofhesdkClient.encryptInputs([{ data: 100n, utype: 2, securityZone: 0 }]);
133
128
 
134
129
  expect(builder).toBeDefined();
135
130
  expect(typeof builder.setChainId).toBe('function');
@@ -42,14 +42,12 @@ describe('@cofhe/web - Config', () => {
42
42
  it('should preserve all other config options', () => {
43
43
  const config = createCofhesdkConfig({
44
44
  supportedChains: [arbSepolia],
45
- fheKeysPrefetching: 'OFF',
46
45
  mocks: {
47
46
  sealOutputDelay: 500,
48
47
  },
49
48
  });
50
49
 
51
50
  expect(config.supportedChains).toEqual([arbSepolia]);
52
- expect(config.fheKeysPrefetching).toBe('OFF');
53
51
  expect(config.mocks.sealOutputDelay).toBe(500);
54
52
  expect(config.fheKeyStorage).toBeDefined();
55
53
  });
@@ -1,5 +1,5 @@
1
1
  import { arbSepolia as cofhesdkArbSepolia } from '@/chains';
2
- import { Encryptable, FheTypes, type CofhesdkClient, type Result, CofhesdkErrorCode, CofhesdkError } from '@/core';
2
+ import { Encryptable, FheTypes, type CofhesdkClient, CofhesdkErrorCode, CofhesdkError } from '@/core';
3
3
 
4
4
  import { describe, it, expect, beforeAll, beforeEach } from 'vitest';
5
5
  import type { PublicClient, WalletClient } from 'viem';
@@ -11,22 +11,6 @@ import { createCofhesdkClient, createCofhesdkConfig } from './index.js';
11
11
  // Real test setup - runs in browser with real tfhe
12
12
  const TEST_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
13
13
 
14
- const expectResultSuccess = <T>(result: Result<T>): T => {
15
- expect(result.success, `Result error: ${result.error?.toString()}`).toBe(true);
16
- return result.data!;
17
- };
18
-
19
- const expectResultError = <T>(result: Result<T>, errorCode?: CofhesdkErrorCode): void => {
20
- expect(result.success).toBe(false);
21
- expect(result.data).toBe(null);
22
- expect(result.error).not.toBe(null);
23
- const error = result.error as CofhesdkError;
24
- expect(error).toBeInstanceOf(CofhesdkError);
25
- if (errorCode) {
26
- expect(error.code, `Result error: ${result.error?.toString()}`).toBe(errorCode);
27
- }
28
- };
29
-
30
14
  describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
31
15
  let cofhesdkClient: CofhesdkClient;
32
16
  let publicClient: PublicClient;
@@ -60,22 +44,19 @@ describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
60
44
 
61
45
  // This will trigger real TFHE initialization in browser
62
46
  const result = await cofhesdkClient.encryptInputs([Encryptable.uint128(100n)]).encrypt();
63
- const encrypted = expectResultSuccess(result);
64
47
 
65
48
  // If we get here, TFHE was initialized successfully
66
- expect(encrypted).toBeDefined();
49
+ expect(result).toBeDefined();
67
50
  }, 60000); // Longer timeout for real operations
68
51
 
69
52
  it('should handle multiple encryptions without re-initializing', async () => {
70
53
  await cofhesdkClient.connect(publicClient, walletClient);
71
54
 
72
55
  // First encryption
73
- const result1 = await cofhesdkClient.encryptInputs([Encryptable.uint128(100n)]).encrypt();
74
- expectResultSuccess(result1);
56
+ expect(cofhesdkClient.encryptInputs([Encryptable.uint128(100n)]).encrypt()).resolves.not.toThrow();
75
57
 
76
58
  // Second encryption should reuse initialization
77
- const result2 = await cofhesdkClient.encryptInputs([Encryptable.uint64(50n)]).encrypt();
78
- expectResultSuccess(result2);
59
+ expect(cofhesdkClient.encryptInputs([Encryptable.uint64(50n)]).encrypt()).resolves.not.toThrow();
79
60
  }, 60000);
80
61
  });
81
62
 
@@ -84,15 +65,15 @@ describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
84
65
  await cofhesdkClient.connect(publicClient, walletClient);
85
66
 
86
67
  const result = await cofhesdkClient.encryptInputs([Encryptable.bool(true)]).encrypt();
87
- const encrypted = expectResultSuccess(result);
88
68
 
89
- expect(encrypted.length).toBe(1);
90
- expect(encrypted[0].utype).toBe(FheTypes.Bool);
91
- expect(encrypted[0].ctHash).toBeDefined();
92
- expect(typeof encrypted[0].ctHash).toBe('bigint');
93
- expect(encrypted[0].signature).toBeDefined();
94
- expect(typeof encrypted[0].signature).toBe('string');
95
- expect(encrypted[0].securityZone).toBe(0);
69
+ expect(result).toBeDefined();
70
+ expect(result.length).toBe(1);
71
+ expect(result[0].utype).toBe(FheTypes.Bool);
72
+ expect(result[0].ctHash).toBeDefined();
73
+ expect(typeof result[0].ctHash).toBe('bigint');
74
+ expect(result[0].signature).toBeDefined();
75
+ expect(typeof result[0].signature).toBe('string');
76
+ expect(result[0].securityZone).toBe(0);
96
77
  }, 60000);
97
78
 
98
79
  it('should encrypt all supported types together', async () => {
@@ -109,17 +90,17 @@ describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
109
90
  ];
110
91
 
111
92
  const result = await cofhesdkClient.encryptInputs(inputs).encrypt();
112
- const encrypted = expectResultSuccess(result);
93
+ expect(result).toBeDefined();
113
94
 
114
- expect(encrypted.length).toBe(7);
95
+ expect(result.length).toBe(7);
115
96
  // Verify each type
116
- expect(encrypted[0].utype).toBe(FheTypes.Bool);
117
- expect(encrypted[1].utype).toBe(FheTypes.Uint8);
118
- expect(encrypted[2].utype).toBe(FheTypes.Uint16);
119
- expect(encrypted[3].utype).toBe(FheTypes.Uint32);
120
- expect(encrypted[4].utype).toBe(FheTypes.Uint64);
121
- expect(encrypted[5].utype).toBe(FheTypes.Uint128);
122
- expect(encrypted[6].utype).toBe(FheTypes.Uint160);
97
+ expect(result[0].utype).toBe(FheTypes.Bool);
98
+ expect(result[1].utype).toBe(FheTypes.Uint8);
99
+ expect(result[2].utype).toBe(FheTypes.Uint16);
100
+ expect(result[3].utype).toBe(FheTypes.Uint32);
101
+ expect(result[4].utype).toBe(FheTypes.Uint64);
102
+ expect(result[5].utype).toBe(FheTypes.Uint128);
103
+ expect(result[6].utype).toBe(FheTypes.Uint160);
123
104
  }, 90000); // Longer timeout for multiple encryptions
124
105
  });
125
106
 
@@ -128,14 +109,13 @@ describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
128
109
  await cofhesdkClient.connect(publicClient, walletClient);
129
110
 
130
111
  const snapshot = cofhesdkClient.getSnapshot();
131
- const result = await cofhesdkClient
112
+ const encrypted = await cofhesdkClient
132
113
  .encryptInputs([Encryptable.uint128(100n)])
133
114
  .setChainId(snapshot.chainId!)
134
115
  .setAccount(snapshot.account!)
135
116
  .setSecurityZone(0)
136
117
  .encrypt();
137
118
 
138
- const encrypted = expectResultSuccess(result);
139
119
  expect(encrypted.length).toBe(1);
140
120
  expect(encrypted[0].utype).toBe(FheTypes.Uint128);
141
121
  }, 60000);
@@ -144,9 +124,12 @@ describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
144
124
  describe('Browser Error Handling', () => {
145
125
  it('should fail gracefully when not connected', async () => {
146
126
  // Don't connect the client
147
- const result = await cofhesdkClient.encryptInputs([Encryptable.uint128(100n)]).encrypt();
148
-
149
- expectResultError(result, CofhesdkErrorCode.NotConnected);
127
+ try {
128
+ const promise = cofhesdkClient.encryptInputs([Encryptable.uint128(100n)]).encrypt();
129
+ } catch (error) {
130
+ expect(error).toBeInstanceOf(CofhesdkError);
131
+ expect((error as CofhesdkError).code).toBe(CofhesdkErrorCode.NotConnected);
132
+ }
150
133
  }, 30000);
151
134
 
152
135
  it('should handle invalid CoFHE URL', async () => {
@@ -158,18 +141,13 @@ describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
158
141
  verifierUrl: 'http://invalid-verifier-url.local',
159
142
  },
160
143
  ],
161
- fheKeysPrefetching: 'OFF',
162
144
  });
163
145
 
164
146
  const badClient = createCofhesdkClient(badConfig);
165
147
  await badClient.connect(publicClient, walletClient);
166
148
 
167
- const result = await badClient.encryptInputs([Encryptable.uint128(100n)]).encrypt();
168
-
169
- expect(result.success).toBe(false);
170
- if (!result.success) {
171
- expect(result.error).toBeDefined();
172
- }
149
+ const promise = badClient.encryptInputs([Encryptable.uint128(100n)]).encrypt();
150
+ expect(promise).rejects.toThrow();
173
151
  }, 60000);
174
152
  });
175
153
 
@@ -181,8 +159,7 @@ describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
181
159
 
182
160
  // Perform 5 encryptions
183
161
  for (let i = 0; i < 5; i++) {
184
- const result = await cofhesdkClient.encryptInputs([Encryptable.uint128(BigInt(i))]).encrypt();
185
- expectResultSuccess(result);
162
+ await cofhesdkClient.encryptInputs([Encryptable.uint128(BigInt(i))]).encrypt();
186
163
  }
187
164
 
188
165
  const duration = Date.now() - start;