@cofhe/sdk 0.3.2 → 0.5.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 (97) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/adapters/{ethers5.test.ts → test/ethers5.test.ts} +2 -2
  3. package/adapters/{ethers6.test.ts → test/ethers6.test.ts} +2 -2
  4. package/adapters/{hardhat.hh2.test.ts → test/hardhat.hh2.test.ts} +2 -2
  5. package/adapters/{index.test.ts → test/index.test.ts} +1 -1
  6. package/adapters/{wagmi.test.ts → test/wagmi.test.ts} +1 -1
  7. package/chains/{chains.test.ts → test/chains.test.ts} +1 -1
  8. package/core/client.ts +15 -5
  9. package/core/clientTypes.ts +7 -5
  10. package/core/consts.ts +9 -0
  11. package/core/decrypt/cofheMocksDecryptForTx.ts +14 -3
  12. package/core/decrypt/decryptForTxBuilder.ts +24 -10
  13. package/core/decrypt/decryptForViewBuilder.ts +14 -7
  14. package/core/decrypt/polling.ts +14 -0
  15. package/core/decrypt/tnDecryptUtils.ts +65 -0
  16. package/core/decrypt/{tnDecrypt.ts → tnDecryptV1.ts} +7 -70
  17. package/core/decrypt/tnDecryptV2.ts +483 -0
  18. package/core/decrypt/tnSealOutputV2.ts +245 -104
  19. package/core/decrypt/verifyDecryptResult.ts +65 -0
  20. package/core/encrypt/cofheMocksZkVerifySign.ts +6 -6
  21. package/core/encrypt/zkPackProveVerify.ts +10 -19
  22. package/core/fetchKeys.ts +0 -2
  23. package/core/index.ts +9 -1
  24. package/core/keyStore.ts +5 -2
  25. package/core/permits.ts +8 -3
  26. package/core/{client.test.ts → test/client.test.ts} +7 -7
  27. package/core/{config.test.ts → test/config.test.ts} +1 -1
  28. package/core/test/decrypt.test.ts +252 -0
  29. package/core/test/decryptBuilders.test.ts +390 -0
  30. package/core/{encrypt → test}/encryptInputsBuilder.test.ts +61 -6
  31. package/core/{fetchKeys.test.ts → test/fetchKeys.test.ts} +3 -3
  32. package/core/{keyStore.test.ts → test/keyStore.test.ts} +5 -3
  33. package/core/{permits.test.ts → test/permits.test.ts} +42 -1
  34. package/core/test/pollCallbacks.test.ts +563 -0
  35. package/core/types.ts +21 -0
  36. package/dist/chains.d.cts +2 -2
  37. package/dist/chains.d.ts +2 -2
  38. package/dist/chunk-4FP4V35O.js +13 -0
  39. package/dist/{chunk-NWDKXBIP.js → chunk-MRCKUMOS.js} +62 -22
  40. package/dist/{chunk-LWMRB6SD.js → chunk-S7OKGLFD.js} +615 -198
  41. package/dist/{clientTypes-Y43CKbOz.d.cts → clientTypes-BSbwairE.d.cts} +38 -13
  42. package/dist/{clientTypes-PQha8zes.d.ts → clientTypes-DDmcgZ0a.d.ts} +38 -13
  43. package/dist/core.cjs +691 -235
  44. package/dist/core.d.cts +24 -6
  45. package/dist/core.d.ts +24 -6
  46. package/dist/core.js +3 -2
  47. package/dist/node.cjs +696 -237
  48. package/dist/node.d.cts +3 -3
  49. package/dist/node.d.ts +3 -3
  50. package/dist/node.js +14 -7
  51. package/dist/{permit-MZ502UBl.d.ts → permit-DnVMDT5h.d.cts} +34 -4
  52. package/dist/{permit-MZ502UBl.d.cts → permit-DnVMDT5h.d.ts} +34 -4
  53. package/dist/permits.cjs +66 -29
  54. package/dist/permits.d.cts +18 -13
  55. package/dist/permits.d.ts +18 -13
  56. package/dist/permits.js +2 -1
  57. package/dist/web.cjs +718 -242
  58. package/dist/web.d.cts +8 -4
  59. package/dist/web.d.ts +8 -4
  60. package/dist/web.js +34 -11
  61. package/dist/zkProve.worker.cjs +6 -3
  62. package/dist/zkProve.worker.js +5 -3
  63. package/node/index.ts +13 -4
  64. package/node/test/client.test.ts +25 -0
  65. package/node/test/config.test.ts +16 -0
  66. package/node/test/inherited.test.ts +244 -0
  67. package/node/test/tfheinit.test.ts +56 -0
  68. package/package.json +24 -22
  69. package/permits/permit.ts +31 -5
  70. package/permits/sealing.ts +1 -1
  71. package/permits/{localstorage.test.ts → test/localstorage.test.ts} +2 -2
  72. package/permits/{permit.test.ts → test/permit.test.ts} +35 -1
  73. package/permits/{sealing.test.ts → test/sealing.test.ts} +1 -1
  74. package/permits/{store.test.ts → test/store.test.ts} +2 -2
  75. package/permits/{validation.test.ts → test/validation.test.ts} +82 -6
  76. package/permits/types.ts +1 -1
  77. package/permits/validation.ts +42 -2
  78. package/web/const.ts +2 -0
  79. package/web/index.ts +20 -6
  80. package/web/storage.ts +18 -3
  81. package/web/{client.web.test.ts → test/client.web.test.ts} +13 -1
  82. package/web/test/config.web.test.ts +16 -0
  83. package/web/test/inherited.web.test.ts +245 -0
  84. package/web/test/tfheinit.web.test.ts +62 -0
  85. package/web/{worker.config.web.test.ts → test/worker.config.web.test.ts} +1 -1
  86. package/web/{worker.output.web.test.ts → test/worker.output.web.test.ts} +1 -1
  87. package/web/{workerManager.test.ts → test/workerManager.test.ts} +1 -1
  88. package/web/{workerManager.web.test.ts → test/workerManager.web.test.ts} +1 -1
  89. package/web/zkProve.worker.ts +4 -3
  90. package/node/client.test.ts +0 -147
  91. package/node/config.test.ts +0 -68
  92. package/node/encryptInputs.test.ts +0 -155
  93. package/web/config.web.test.ts +0 -69
  94. package/web/encryptInputs.web.test.ts +0 -172
  95. package/web/worker.builder.web.test.ts +0 -148
  96. /package/dist/{types-YiAC4gig.d.cts → types-C07FK-cL.d.cts} +0 -0
  97. /package/dist/{types-YiAC4gig.d.ts → types-C07FK-cL.d.ts} +0 -0
@@ -0,0 +1,390 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { type PublicClient, type WalletClient, createPublicClient, createWalletClient, http } from 'viem';
3
+ import { privateKeyToAccount } from 'viem/accounts';
4
+ import { arbitrumSepolia } from 'viem/chains';
5
+ import { DecryptForTxBuilder } from '../decrypt/decryptForTxBuilder.js';
6
+ import { DecryptForViewBuilder } from '../decrypt/decryptForViewBuilder.js';
7
+ import { createCofheConfigBase, type CofheConfig } from '../config.js';
8
+ import { CofheErrorCode } from '../error.js';
9
+ import { FheTypes } from '../types.js';
10
+
11
+ const TEST_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
12
+ const account = privateKeyToAccount(TEST_PRIVATE_KEY);
13
+ const TEST_CHAIN_ID = 421614;
14
+ const TEST_CT_HASH = '0xabcdef1234567890';
15
+
16
+ const MockCoFheUrl = 'http://localhost:3001';
17
+
18
+ const publicClient: PublicClient = createPublicClient({
19
+ chain: arbitrumSepolia,
20
+ transport: http(),
21
+ });
22
+
23
+ const walletClient: WalletClient = createWalletClient({
24
+ chain: arbitrumSepolia,
25
+ transport: http(),
26
+ account,
27
+ });
28
+
29
+ const mockConfig: CofheConfig = createCofheConfigBase({
30
+ supportedChains: [
31
+ {
32
+ id: TEST_CHAIN_ID,
33
+ name: 'Mock Chain',
34
+ network: 'Mock Network',
35
+ coFheUrl: MockCoFheUrl,
36
+ thresholdNetworkUrl: MockCoFheUrl,
37
+ environment: 'TESTNET',
38
+ verifierUrl: MockCoFheUrl,
39
+ },
40
+ ],
41
+ });
42
+
43
+ function createTxBuilder(overrides?: Partial<{ chainId: number; account: string; ctHash: string | bigint }>) {
44
+ return new DecryptForTxBuilder({
45
+ config: mockConfig,
46
+ publicClient,
47
+ walletClient,
48
+ chainId: TEST_CHAIN_ID,
49
+ account: account.address,
50
+ ctHash: TEST_CT_HASH,
51
+ requireConnected: undefined,
52
+ ...overrides,
53
+ });
54
+ }
55
+
56
+ function createViewBuilder<U extends FheTypes>(
57
+ utype: U,
58
+ overrides?: Partial<{ chainId: number; account: string; ctHash: string | bigint }>
59
+ ) {
60
+ return new DecryptForViewBuilder<U>({
61
+ config: mockConfig,
62
+ publicClient,
63
+ walletClient,
64
+ chainId: TEST_CHAIN_ID,
65
+ account: account.address,
66
+ ctHash: TEST_CT_HASH,
67
+ utype,
68
+ requireConnected: undefined,
69
+ ...overrides,
70
+ });
71
+ }
72
+
73
+ // ---------------------------------------------------------------------------
74
+ // DecryptForTxBuilder
75
+ // ---------------------------------------------------------------------------
76
+
77
+ describe('DecryptForTxBuilder', () => {
78
+ // --- setChainId / getChainId ---
79
+
80
+ describe('setChainId / getChainId', () => {
81
+ it('should store and return the chainId', () => {
82
+ const builder = createTxBuilder({ chainId: undefined });
83
+ expect(builder.getChainId()).toBeUndefined();
84
+
85
+ builder.setChainId(11155111);
86
+ expect(builder.getChainId()).toBe(11155111);
87
+ });
88
+
89
+ it('should allow overriding', () => {
90
+ const builder = createTxBuilder({ chainId: 1 });
91
+ builder.setChainId(42);
92
+ expect(builder.getChainId()).toBe(42);
93
+ });
94
+ });
95
+
96
+ // --- setAccount / getAccount ---
97
+
98
+ describe('setAccount / getAccount', () => {
99
+ it('should store and return the account', () => {
100
+ const builder = createTxBuilder({ account: undefined });
101
+ expect(builder.getAccount()).toBeUndefined();
102
+
103
+ builder.setAccount('0xdeadbeef');
104
+ expect(builder.getAccount()).toBe('0xdeadbeef');
105
+ });
106
+
107
+ it('should allow overriding', () => {
108
+ const builder = createTxBuilder();
109
+ builder.setAccount('0xnewaccount');
110
+ expect(builder.getAccount()).toBe('0xnewaccount');
111
+ });
112
+ });
113
+
114
+ // --- withPermit / withoutPermit selection ---
115
+
116
+ describe('withPermit / withoutPermit selection', () => {
117
+ it('withPermit() should set permit selection', () => {
118
+ const builder = createTxBuilder();
119
+ const selected = builder.withPermit();
120
+ expect(selected).toBeDefined();
121
+ expect(selected.getPermit()).toBeUndefined();
122
+ expect(selected.getPermitHash()).toBeUndefined();
123
+ });
124
+
125
+ it('withPermit(hash) should store the permit hash', () => {
126
+ const builder = createTxBuilder();
127
+ const selected = builder.withPermit('0xmypermithash');
128
+ expect(selected.getPermitHash()).toBe('0xmypermithash');
129
+ expect(selected.getPermit()).toBeUndefined();
130
+ });
131
+
132
+ it('withoutPermit() should set permit selection', () => {
133
+ const builder = createTxBuilder();
134
+ const selected = builder.withoutPermit();
135
+ expect(selected).toBeDefined();
136
+ expect(selected.getPermit()).toBeUndefined();
137
+ expect(selected.getPermitHash()).toBeUndefined();
138
+ });
139
+
140
+ it('should throw when withPermit() is called twice', () => {
141
+ const builder = createTxBuilder();
142
+ builder.withPermit();
143
+
144
+ expect(() => (builder as any).withPermit()).toThrow('withPermit() can only be selected once');
145
+ });
146
+
147
+ it('should throw when withoutPermit() is called twice', () => {
148
+ const builder = createTxBuilder();
149
+ builder.withoutPermit();
150
+
151
+ expect(() => (builder as any).withoutPermit()).toThrow('withoutPermit() can only be selected once');
152
+ });
153
+
154
+ it('should throw when withPermit() is called after withoutPermit()', () => {
155
+ const builder = createTxBuilder();
156
+ builder.withoutPermit();
157
+
158
+ expect(() => (builder as any).withPermit()).toThrow('cannot call withPermit() after withoutPermit()');
159
+ });
160
+
161
+ it('should throw when withoutPermit() is called after withPermit()', () => {
162
+ const builder = createTxBuilder();
163
+ builder.withPermit();
164
+
165
+ expect(() => (builder as any).withoutPermit()).toThrow('cannot call withoutPermit() after withPermit()');
166
+ });
167
+ });
168
+
169
+ // --- chaining ---
170
+
171
+ describe('chaining', () => {
172
+ it('should return the builder from each setter for fluent chaining', () => {
173
+ const builder = createTxBuilder({ chainId: undefined, account: undefined });
174
+ const result = builder.setChainId(TEST_CHAIN_ID).setAccount(account.address).withPermit();
175
+
176
+ expect(result).toBeDefined();
177
+ expect(result.getChainId()).toBe(TEST_CHAIN_ID);
178
+ expect(result.getAccount()).toBe(account.address);
179
+ });
180
+
181
+ it('should allow setChainId and setAccount after withPermit', () => {
182
+ const builder = createTxBuilder({ chainId: undefined, account: undefined });
183
+ const selected = builder.withPermit();
184
+ selected.setChainId(99);
185
+ selected.setAccount('0xabc');
186
+
187
+ expect(selected.getChainId()).toBe(99);
188
+ expect(selected.getAccount()).toBe('0xabc');
189
+ });
190
+
191
+ it('should allow setChainId and setAccount after withoutPermit', () => {
192
+ const builder = createTxBuilder({ chainId: undefined, account: undefined });
193
+ const selected = builder.withoutPermit();
194
+ selected.setChainId(99);
195
+ selected.setAccount('0xabc');
196
+
197
+ expect(selected.getChainId()).toBe(99);
198
+ expect(selected.getAccount()).toBe('0xabc');
199
+ });
200
+ });
201
+
202
+ // --- execute error paths ---
203
+
204
+ describe('execute – error paths', () => {
205
+ it('should throw when execute() is called without permit selection', async () => {
206
+ const builder = createTxBuilder();
207
+
208
+ try {
209
+ await builder.execute();
210
+ expect.fail('Expected error');
211
+ } catch (error) {
212
+ expect((error as any).code).toBe(CofheErrorCode.InternalError);
213
+ expect((error as Error).message).toContain('missing permit selection');
214
+ }
215
+ });
216
+
217
+ it('should throw when withPermit() has no active permit', async () => {
218
+ const builder = createTxBuilder();
219
+
220
+ try {
221
+ await builder.withPermit().execute();
222
+ expect.fail('Expected PermitNotFound error');
223
+ } catch (error) {
224
+ expect((error as any).code).toBe(CofheErrorCode.PermitNotFound);
225
+ expect((error as Error).message).toContain('Active permit not found');
226
+ }
227
+ });
228
+
229
+ it('should throw when withPermit(hash) cannot find permit', async () => {
230
+ const builder = createTxBuilder();
231
+
232
+ try {
233
+ await builder.withPermit('0xnonexistent').execute();
234
+ expect.fail('Expected PermitNotFound error');
235
+ } catch (error) {
236
+ expect((error as any).code).toBe(CofheErrorCode.PermitNotFound);
237
+ expect((error as Error).message).toContain('Permit with hash');
238
+ }
239
+ });
240
+ });
241
+
242
+ // --- constructor error paths ---
243
+
244
+ describe('constructor – error paths', () => {
245
+ it('should throw when config is undefined', () => {
246
+ expect(
247
+ () =>
248
+ new DecryptForTxBuilder({
249
+ config: undefined,
250
+ publicClient,
251
+ walletClient,
252
+ chainId: TEST_CHAIN_ID,
253
+ account: account.address,
254
+ ctHash: TEST_CT_HASH,
255
+ requireConnected: undefined,
256
+ })
257
+ ).toThrow();
258
+ });
259
+ });
260
+ });
261
+
262
+ // ---------------------------------------------------------------------------
263
+ // DecryptForViewBuilder
264
+ // ---------------------------------------------------------------------------
265
+
266
+ describe('DecryptForViewBuilder', () => {
267
+ // --- setChainId / getChainId ---
268
+
269
+ describe('setChainId / getChainId', () => {
270
+ it('should store and return the chainId', () => {
271
+ const builder = createViewBuilder(FheTypes.Uint32, { chainId: undefined });
272
+ expect(builder.getChainId()).toBeUndefined();
273
+
274
+ builder.setChainId(11155111);
275
+ expect(builder.getChainId()).toBe(11155111);
276
+ });
277
+ });
278
+
279
+ // --- setAccount / getAccount ---
280
+
281
+ describe('setAccount / getAccount', () => {
282
+ it('should store and return the account', () => {
283
+ const builder = createViewBuilder(FheTypes.Uint32, { account: undefined });
284
+ expect(builder.getAccount()).toBeUndefined();
285
+
286
+ builder.setAccount('0xdeadbeef');
287
+ expect(builder.getAccount()).toBe('0xdeadbeef');
288
+ });
289
+ });
290
+
291
+ // --- withPermit ---
292
+
293
+ describe('withPermit', () => {
294
+ it('withPermit() should clear permit and hash', () => {
295
+ const builder = createViewBuilder(FheTypes.Uint32);
296
+ builder.withPermit();
297
+ expect(builder.getPermit()).toBeUndefined();
298
+ expect(builder.getPermitHash()).toBeUndefined();
299
+ });
300
+
301
+ it('withPermit(hash) should store the permit hash', () => {
302
+ const builder = createViewBuilder(FheTypes.Uint32);
303
+ builder.withPermit('0xmypermithash');
304
+ expect(builder.getPermitHash()).toBe('0xmypermithash');
305
+ expect(builder.getPermit()).toBeUndefined();
306
+ });
307
+
308
+ it('should allow overriding permit selection', () => {
309
+ const builder = createViewBuilder(FheTypes.Uint32);
310
+ builder.withPermit('0xfirst');
311
+ expect(builder.getPermitHash()).toBe('0xfirst');
312
+
313
+ builder.withPermit('0xsecond');
314
+ expect(builder.getPermitHash()).toBe('0xsecond');
315
+ });
316
+ });
317
+
318
+ // --- chaining ---
319
+
320
+ describe('chaining', () => {
321
+ it('should return the builder from each setter for fluent chaining', () => {
322
+ const builder = createViewBuilder(FheTypes.Uint32, { chainId: undefined, account: undefined });
323
+ const result = builder.setChainId(TEST_CHAIN_ID).setAccount(account.address).withPermit();
324
+
325
+ expect(result).toBeDefined();
326
+ expect(result.getChainId()).toBe(TEST_CHAIN_ID);
327
+ expect(result.getAccount()).toBe(account.address);
328
+ });
329
+ });
330
+
331
+ // --- execute error paths ---
332
+
333
+ describe('execute – error paths', () => {
334
+ it('should throw when active permit is not found', async () => {
335
+ const builder = createViewBuilder(FheTypes.Uint32);
336
+
337
+ try {
338
+ await builder.execute();
339
+ expect.fail('Expected PermitNotFound error');
340
+ } catch (error) {
341
+ expect((error as any).code).toBe(CofheErrorCode.PermitNotFound);
342
+ expect((error as Error).message).toContain('Active permit not found');
343
+ }
344
+ });
345
+
346
+ it('should throw when withPermit(hash) cannot find permit', async () => {
347
+ const builder = createViewBuilder(FheTypes.Uint32);
348
+ builder.withPermit('0xnonexistent');
349
+
350
+ try {
351
+ await builder.execute();
352
+ expect.fail('Expected PermitNotFound error');
353
+ } catch (error) {
354
+ expect((error as any).code).toBe(CofheErrorCode.PermitNotFound);
355
+ expect((error as Error).message).toContain('Permit with hash');
356
+ }
357
+ });
358
+
359
+ it('should throw for invalid utype', async () => {
360
+ const builder = createViewBuilder(999 as FheTypes);
361
+
362
+ try {
363
+ await builder.execute();
364
+ expect.fail('Expected InvalidUtype error');
365
+ } catch (error) {
366
+ expect((error as any).code).toBe(CofheErrorCode.InvalidUtype);
367
+ }
368
+ });
369
+ });
370
+
371
+ // --- constructor error paths ---
372
+
373
+ describe('constructor – error paths', () => {
374
+ it('should throw when config is undefined', () => {
375
+ expect(
376
+ () =>
377
+ new DecryptForViewBuilder({
378
+ config: undefined,
379
+ publicClient,
380
+ walletClient,
381
+ chainId: TEST_CHAIN_ID,
382
+ account: account.address,
383
+ ctHash: TEST_CT_HASH,
384
+ utype: FheTypes.Uint32,
385
+ requireConnected: undefined,
386
+ })
387
+ ).toThrow();
388
+ });
389
+ });
390
+ });
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { EncryptInputsBuilder } from './encryptInputsBuilder.js';
2
+ import { EncryptInputsBuilder } from '../encrypt/encryptInputsBuilder.js';
3
3
  import {
4
4
  type EncryptableItem,
5
5
  FheTypes,
@@ -12,9 +12,9 @@ import { CofheError, CofheErrorCode } from '../error.js';
12
12
  import { fromHexString, toHexString } from '../utils.js';
13
13
  import { type PublicClient, createPublicClient, http, type WalletClient, createWalletClient } from 'viem';
14
14
  import { privateKeyToAccount } from 'viem/accounts';
15
- import { arbitrumSepolia, hardhat } from 'viem/chains';
15
+ import { arbitrumSepolia } from 'viem/chains';
16
16
  import { type CofheConfig, createCofheConfigBase } from '../config.js';
17
- import { type ZkBuilderAndCrsGenerator } from './zkPackProveVerify.js';
17
+ import { type ZkBuilderAndCrsGenerator } from '../encrypt/zkPackProveVerify.js';
18
18
  import { type KeysStorage, createKeysStore } from '../keyStore.js';
19
19
  import { type FheKeyDeserializer } from '../fetchKeys.js';
20
20
 
@@ -122,8 +122,7 @@ class MockZkListBuilder {
122
122
 
123
123
  const MockCrs = {
124
124
  free: () => {},
125
- serialize: () => new Uint8Array(),
126
- safe_serialize: () => new Uint8Array(),
125
+ safe_serialize: (_serializedSizeLimit: bigint) => new Uint8Array(),
127
126
  };
128
127
 
129
128
  // Setup fetch mock for http://localhost:3001/verify
@@ -223,7 +222,7 @@ class MockZkProvenList {
223
222
  this.metadata = metadata;
224
223
  }
225
224
 
226
- serialize(): Uint8Array {
225
+ safe_serialize(_serializedSizeLimit: bigint): Uint8Array {
227
226
  // Serialize this.items into JSON, then encode as Uint8Array (utf-8)
228
227
  const json = stringifyWithBigInt({ items: this.items, metadata: this.metadata });
229
228
  return new TextEncoder().encode(json);
@@ -744,4 +743,60 @@ describe('EncryptInputsBuilder', () => {
744
743
  expect(encryptedMetadata2.chainId).toBe(defaultChainId);
745
744
  });
746
745
  });
746
+
747
+ describe('setUseWorker and getUseWorker', () => {
748
+ it('should have setUseWorker method', () => {
749
+ expect(builder).toHaveProperty('setUseWorker');
750
+ expect(typeof builder.setUseWorker).toBe('function');
751
+ });
752
+
753
+ it('should have getUseWorker method', () => {
754
+ expect(builder).toHaveProperty('getUseWorker');
755
+ expect(typeof builder.getUseWorker).toBe('function');
756
+ });
757
+
758
+ it('should return builder for method chaining', () => {
759
+ const returnedBuilder = builder.setUseWorker(false);
760
+ expect(returnedBuilder).toBe(builder);
761
+ });
762
+
763
+ it('should allow chaining with other builder methods', () => {
764
+ const chainedBuilder = builder.setUseWorker(false).onStep(() => {});
765
+ expect(chainedBuilder).toBeDefined();
766
+ expect(chainedBuilder).toHaveProperty('execute');
767
+ });
768
+
769
+ it('should accept true and false parameters without throwing', () => {
770
+ expect(() => builder.setUseWorker(true)).not.toThrow();
771
+ expect(() => builder.setUseWorker(false)).not.toThrow();
772
+ });
773
+
774
+ it('should return current useWorker value via getUseWorker', () => {
775
+ builder.setUseWorker(true);
776
+ expect(builder.getUseWorker()).toBe(true);
777
+
778
+ builder.setUseWorker(false);
779
+ expect(builder.getUseWorker()).toBe(false);
780
+ });
781
+
782
+ it('should reflect changes across multiple setUseWorker calls', () => {
783
+ builder.setUseWorker(true);
784
+ expect(builder.getUseWorker()).toBe(true);
785
+
786
+ builder.setUseWorker(false);
787
+ expect(builder.getUseWorker()).toBe(false);
788
+
789
+ builder.setUseWorker(true);
790
+ expect(builder.getUseWorker()).toBe(true);
791
+ });
792
+
793
+ it('should default useWorker based on config.useWorkers', () => {
794
+ const configWithWorkers = createMockCofheConfig(defaultChainId, MockZkVerifierUrl);
795
+ const builderWithWorkers = new EncryptInputsBuilder({
796
+ ...createDefaultParams(),
797
+ config: configWithWorkers,
798
+ });
799
+ expect(builderWithWorkers.getUseWorker()).toBe(configWithWorkers.useWorkers);
800
+ });
801
+ });
747
802
  });
@@ -4,9 +4,9 @@
4
4
  import { sepolia, arbSepolia } from '@/chains';
5
5
 
6
6
  import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
7
- import { fetchKeys } from './fetchKeys.js';
8
- import { type CofheConfig, createCofheConfigBase } from './config.js';
9
- import { createKeysStore, type KeysStorage } from './keyStore.js';
7
+ import { fetchKeys } from '../fetchKeys.js';
8
+ import { type CofheConfig, createCofheConfigBase } from '../config.js';
9
+ import { createKeysStore, type KeysStorage } from '../keyStore.js';
10
10
 
11
11
  describe('fetchKeys', () => {
12
12
  let config: CofheConfig;
@@ -2,7 +2,9 @@
2
2
  /* eslint-disable no-undef */
3
3
 
4
4
  import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
5
- import { createKeysStore, type KeysStore, type KeysStorage } from './keyStore.js';
5
+
6
+ import { createKeysStore, type KeysStore, type KeysStorage } from '../keyStore';
7
+ import { TFHE_RS_KEY_VERSION } from 'core/consts';
6
8
 
7
9
  // Mock the storage module
8
10
  const mockStorage = {
@@ -11,7 +13,7 @@ const mockStorage = {
11
13
  removeItem: vi.fn(),
12
14
  };
13
15
 
14
- vi.mock('../src/storage', () => ({
16
+ vi.mock('../../src/storage', () => ({
15
17
  getStorage: () => mockStorage,
16
18
  }));
17
19
 
@@ -124,7 +126,7 @@ describe('KeyStore', () => {
124
126
  it('should clear keys storage', async () => {
125
127
  await keysStorage.clearKeysStorage();
126
128
 
127
- expect(mockStorage.removeItem).toHaveBeenCalledWith('cofhesdk-keys');
129
+ expect(mockStorage.removeItem).toHaveBeenCalledWith(`cofhesdk-keys-v${TFHE_RS_KEY_VERSION}`);
128
130
  });
129
131
 
130
132
  it('should rehydrate keys store', async () => {
@@ -7,7 +7,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
7
7
  import { createPublicClient, createWalletClient, http, type PublicClient, type WalletClient } from 'viem';
8
8
  import { arbitrumSepolia } from 'viem/chains';
9
9
  import { privateKeyToAccount } from 'viem/accounts';
10
- import { permits } from './permits.js';
10
+ import { permits } from '../permits.js';
11
11
 
12
12
  // Type declarations for happy-dom environment
13
13
  declare const localStorage: {
@@ -435,6 +435,47 @@ describe('Core Permits Tests', () => {
435
435
  });
436
436
  });
437
437
 
438
+ describe('Export', () => {
439
+ it('should export self permit data without sensitive fields', async () => {
440
+ const permit = await permits.createSelf(
441
+ { name: 'Test Self Permit', issuer: bobAddress },
442
+ publicClient,
443
+ bobWalletClient
444
+ );
445
+
446
+ const exported = permits.export(permit);
447
+ const parsed = JSON.parse(exported);
448
+
449
+ expect(parsed.name).toBe('Test Self Permit');
450
+ expect(parsed.issuer).toBe(bobAddress);
451
+ expect(parsed).not.toHaveProperty('sealingPair');
452
+ expect(parsed).not.toHaveProperty('issuerSignature');
453
+ });
454
+
455
+ it('should export sharing permit data with recipient and issuerSignature', async () => {
456
+ const permit = await permits.createSharing(
457
+ {
458
+ name: 'Test Sharing Permit',
459
+ issuer: bobAddress,
460
+ recipient: aliceAddress,
461
+ },
462
+ publicClient,
463
+ bobWalletClient
464
+ );
465
+
466
+ const exported = permits.export(permit);
467
+ const parsed = JSON.parse(exported);
468
+
469
+ expect(parsed.name).toBe('Test Sharing Permit');
470
+ expect(parsed.type).toBe('sharing');
471
+ expect(parsed.issuer).toBe(bobAddress);
472
+ expect(parsed.recipient).toBe(aliceAddress);
473
+ expect(parsed.issuerSignature).toBeDefined();
474
+ expect(parsed.issuerSignature).not.toBe('0x');
475
+ expect(parsed).not.toHaveProperty('sealingPair');
476
+ });
477
+ });
478
+
438
479
  describe('getOrCreate - Multiple Types Scenarios', () => {
439
480
  it('should handle switching between self and sharing permits', async () => {
440
481
  // Create self permit