@cofhe/sdk 0.4.0 → 0.5.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 (95) 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 +11 -1
  9. package/core/clientTypes.ts +3 -1
  10. package/core/consts.ts +9 -0
  11. package/core/decrypt/cofheMocksDecryptForTx.ts +14 -3
  12. package/core/decrypt/decryptForTxBuilder.ts +16 -2
  13. package/core/decrypt/decryptForViewBuilder.ts +14 -7
  14. package/core/decrypt/polling.ts +14 -0
  15. package/core/decrypt/tnDecryptV2.ts +250 -110
  16. package/core/decrypt/tnSealOutputV2.ts +245 -104
  17. package/core/decrypt/verifyDecryptResult.ts +65 -0
  18. package/core/encrypt/cofheMocksZkVerifySign.ts +6 -6
  19. package/core/encrypt/zkPackProveVerify.ts +10 -19
  20. package/core/fetchKeys.ts +0 -2
  21. package/core/index.ts +9 -1
  22. package/core/keyStore.ts +5 -2
  23. package/core/permits.ts +5 -0
  24. package/core/{client.test.ts → test/client.test.ts} +7 -7
  25. package/core/{config.test.ts → test/config.test.ts} +1 -1
  26. package/core/test/decrypt.test.ts +252 -0
  27. package/core/test/decryptBuilders.test.ts +390 -0
  28. package/core/{encrypt → test}/encryptInputsBuilder.test.ts +61 -6
  29. package/core/{fetchKeys.test.ts → test/fetchKeys.test.ts} +3 -3
  30. package/core/{keyStore.test.ts → test/keyStore.test.ts} +5 -3
  31. package/core/{permits.test.ts → test/permits.test.ts} +42 -1
  32. package/core/test/pollCallbacks.test.ts +563 -0
  33. package/core/types.ts +13 -0
  34. package/dist/chains.d.cts +2 -2
  35. package/dist/chains.d.ts +2 -2
  36. package/dist/chunk-4FP4V35O.js +13 -0
  37. package/dist/{chunk-NWDKXBIP.js → chunk-MRCKUMOS.js} +62 -22
  38. package/dist/{chunk-MXND5SVN.js → chunk-S7OKGLFD.js} +485 -207
  39. package/dist/{clientTypes-kkrRdawm.d.ts → clientTypes-BSbwairE.d.cts} +23 -6
  40. package/dist/{clientTypes-ACVWbrXL.d.cts → clientTypes-DDmcgZ0a.d.ts} +23 -6
  41. package/dist/core.cjs +561 -244
  42. package/dist/core.d.cts +24 -6
  43. package/dist/core.d.ts +24 -6
  44. package/dist/core.js +3 -2
  45. package/dist/node.cjs +566 -246
  46. package/dist/node.d.cts +3 -3
  47. package/dist/node.d.ts +3 -3
  48. package/dist/node.js +14 -7
  49. package/dist/{permit-MZ502UBl.d.cts → permit-DnVMDT5h.d.cts} +34 -4
  50. package/dist/{permit-MZ502UBl.d.ts → permit-DnVMDT5h.d.ts} +34 -4
  51. package/dist/permits.cjs +66 -29
  52. package/dist/permits.d.cts +18 -13
  53. package/dist/permits.d.ts +18 -13
  54. package/dist/permits.js +2 -1
  55. package/dist/web.cjs +604 -256
  56. package/dist/web.d.cts +8 -4
  57. package/dist/web.d.ts +8 -4
  58. package/dist/web.js +49 -14
  59. package/dist/zkProve.worker.cjs +72 -64
  60. package/dist/zkProve.worker.js +71 -64
  61. package/node/index.ts +13 -4
  62. package/node/test/client.test.ts +25 -0
  63. package/node/test/config.test.ts +16 -0
  64. package/node/test/inherited.test.ts +244 -0
  65. package/node/test/tfheinit.test.ts +56 -0
  66. package/package.json +24 -22
  67. package/permits/permit.ts +31 -5
  68. package/permits/sealing.ts +1 -1
  69. package/permits/{localstorage.test.ts → test/localstorage.test.ts} +2 -2
  70. package/permits/{permit.test.ts → test/permit.test.ts} +35 -1
  71. package/permits/{sealing.test.ts → test/sealing.test.ts} +1 -1
  72. package/permits/{store.test.ts → test/store.test.ts} +2 -2
  73. package/permits/{validation.test.ts → test/validation.test.ts} +82 -6
  74. package/permits/types.ts +1 -1
  75. package/permits/validation.ts +42 -2
  76. package/web/const.ts +2 -0
  77. package/web/index.ts +40 -11
  78. package/web/storage.ts +18 -3
  79. package/web/{client.web.test.ts → test/client.web.test.ts} +13 -1
  80. package/web/test/config.web.test.ts +16 -0
  81. package/web/test/inherited.web.test.ts +245 -0
  82. package/web/test/tfheinit.web.test.ts +62 -0
  83. package/web/{worker.config.web.test.ts → test/worker.config.web.test.ts} +1 -1
  84. package/web/{worker.output.web.test.ts → test/worker.output.web.test.ts} +1 -1
  85. package/web/{workerManager.test.ts → test/workerManager.test.ts} +1 -1
  86. package/web/{workerManager.web.test.ts → test/workerManager.web.test.ts} +1 -1
  87. package/web/zkProve.worker.ts +94 -84
  88. package/node/client.test.ts +0 -147
  89. package/node/config.test.ts +0 -68
  90. package/node/encryptInputs.test.ts +0 -155
  91. package/web/config.web.test.ts +0 -69
  92. package/web/encryptInputs.web.test.ts +0 -172
  93. package/web/worker.builder.web.test.ts +0 -148
  94. /package/dist/{types-YiAC4gig.d.cts → types-C07FK-cL.d.cts} +0 -0
  95. /package/dist/{types-YiAC4gig.d.ts → types-C07FK-cL.d.ts} +0 -0
@@ -0,0 +1,563 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import { tnDecryptV2 } from '../decrypt/tnDecryptV2.js';
3
+ import { tnSealOutputV2 } from '../decrypt/tnSealOutputV2.js';
4
+
5
+ const makeMockResponse = (opts: { ok: boolean; status?: number; statusText?: string; json: () => Promise<any> }) => {
6
+ return {
7
+ ok: opts.ok,
8
+ status: opts.status ?? (opts.ok ? 200 : 500),
9
+ statusText: opts.statusText ?? '',
10
+ json: opts.json,
11
+ } as unknown as Response;
12
+ };
13
+
14
+ describe('decrypt polling callbacks', () => {
15
+ const thresholdNetworkUrl = 'http://threshold.local';
16
+
17
+ beforeEach(() => {
18
+ vi.useFakeTimers();
19
+ });
20
+
21
+ afterEach(() => {
22
+ vi.useRealTimers();
23
+ vi.restoreAllMocks();
24
+ });
25
+
26
+ it('tnDecryptV2 calls onPoll once per poll attempt', async () => {
27
+ const onPoll = vi.fn();
28
+
29
+ let decryptStatusCalls = 0;
30
+ const fetchMock = vi.fn(async (url: string, options?: any) => {
31
+ if (url === `${thresholdNetworkUrl}/v2/decrypt` && options?.method === 'POST') {
32
+ return makeMockResponse({
33
+ ok: true,
34
+ json: async () => ({ request_id: 'req-1' }),
35
+ });
36
+ }
37
+
38
+ if (url === `${thresholdNetworkUrl}/v2/decrypt/req-1` && options?.method === 'GET') {
39
+ decryptStatusCalls += 1;
40
+
41
+ if (decryptStatusCalls === 1) {
42
+ return makeMockResponse({
43
+ ok: true,
44
+ json: async () => ({
45
+ request_id: 'req-1',
46
+ status: 'PROCESSING',
47
+ submitted_at: 't',
48
+ }),
49
+ });
50
+ }
51
+
52
+ return makeMockResponse({
53
+ ok: true,
54
+ json: async () => ({
55
+ request_id: 'req-1',
56
+ status: 'COMPLETED',
57
+ submitted_at: 't',
58
+ is_succeed: true,
59
+ decrypted: [0x01],
60
+ signature: `0x${'01'.repeat(32)}${'02'.repeat(32)}1b`,
61
+ }),
62
+ });
63
+ }
64
+
65
+ throw new Error(`Unexpected fetch: ${url}`);
66
+ });
67
+
68
+ global.fetch = fetchMock as any;
69
+
70
+ const promise = tnDecryptV2({
71
+ ctHash: 1n,
72
+ chainId: 1,
73
+ permission: null,
74
+ thresholdNetworkUrl,
75
+ onPoll,
76
+ });
77
+
78
+ for (let i = 0; i < 25 && onPoll.mock.calls.length < 1; i += 1) {
79
+ await Promise.resolve();
80
+ }
81
+ expect(onPoll).toHaveBeenCalledTimes(1);
82
+
83
+ await vi.advanceTimersByTimeAsync(1000);
84
+ const result = await promise;
85
+
86
+ expect(result.decryptedValue).toBe(1n);
87
+ expect(result.signature.startsWith('0x')).toBe(true);
88
+
89
+ expect(onPoll).toHaveBeenCalledTimes(2);
90
+ expect(onPoll).toHaveBeenNthCalledWith(
91
+ 1,
92
+ expect.objectContaining({
93
+ operation: 'decrypt',
94
+ requestId: 'req-1',
95
+ attemptIndex: 0,
96
+ intervalMs: 1000,
97
+ timeoutMs: 5 * 60 * 1000,
98
+ })
99
+ );
100
+ expect(onPoll).toHaveBeenNthCalledWith(
101
+ 2,
102
+ expect.objectContaining({
103
+ operation: 'decrypt',
104
+ requestId: 'req-1',
105
+ attemptIndex: 1,
106
+ })
107
+ );
108
+ });
109
+
110
+ it('tnDecryptV2 calls onPoll for 204 submit retries', async () => {
111
+ const onPoll = vi.fn();
112
+
113
+ let submitCalls = 0;
114
+ const fetchMock = vi.fn(async (url: string, options?: any) => {
115
+ if (url === `${thresholdNetworkUrl}/v2/decrypt` && options?.method === 'POST') {
116
+ submitCalls += 1;
117
+
118
+ if (submitCalls === 1) {
119
+ return makeMockResponse({
120
+ ok: true,
121
+ status: 204,
122
+ json: async () => {
123
+ throw new Error('json() should not be called for 204 submit responses');
124
+ },
125
+ });
126
+ }
127
+
128
+ return makeMockResponse({
129
+ ok: true,
130
+ json: async () => ({ request_id: 'req-submit-retry' }),
131
+ });
132
+ }
133
+
134
+ if (url === `${thresholdNetworkUrl}/v2/decrypt/req-submit-retry` && options?.method === 'GET') {
135
+ return makeMockResponse({
136
+ ok: true,
137
+ json: async () => ({
138
+ request_id: 'req-submit-retry',
139
+ status: 'COMPLETED',
140
+ submitted_at: 't',
141
+ is_succeed: true,
142
+ decrypted: [0x01],
143
+ signature: `0x${'01'.repeat(32)}${'02'.repeat(32)}1b`,
144
+ }),
145
+ });
146
+ }
147
+
148
+ throw new Error(`Unexpected fetch: ${url}`);
149
+ });
150
+
151
+ global.fetch = fetchMock as any;
152
+
153
+ const promise = tnDecryptV2({
154
+ ctHash: 1n,
155
+ chainId: 1,
156
+ permission: null,
157
+ thresholdNetworkUrl,
158
+ onPoll,
159
+ });
160
+
161
+ for (let i = 0; i < 25 && onPoll.mock.calls.length < 1; i += 1) {
162
+ await Promise.resolve();
163
+ }
164
+
165
+ expect(onPoll).toHaveBeenCalledTimes(1);
166
+ expect(onPoll).toHaveBeenNthCalledWith(
167
+ 1,
168
+ expect.objectContaining({
169
+ operation: 'decrypt',
170
+ requestId: '',
171
+ attemptIndex: 0,
172
+ intervalMs: 1000,
173
+ timeoutMs: 5 * 60 * 1000,
174
+ })
175
+ );
176
+
177
+ await vi.advanceTimersByTimeAsync(1000);
178
+ await promise;
179
+
180
+ expect(onPoll).toHaveBeenCalledTimes(2);
181
+ expect(onPoll).toHaveBeenNthCalledWith(
182
+ 2,
183
+ expect.objectContaining({
184
+ operation: 'decrypt',
185
+ requestId: 'req-submit-retry',
186
+ attemptIndex: 0,
187
+ })
188
+ );
189
+ });
190
+
191
+ it('tnDecryptV2 returns immediately when submit responds with cached completed payload', async () => {
192
+ const onPoll = vi.fn();
193
+
194
+ const fetchMock = vi.fn(async (url: string, options?: any) => {
195
+ if (url === `${thresholdNetworkUrl}/v2/decrypt` && options?.method === 'POST') {
196
+ return makeMockResponse({
197
+ ok: true,
198
+ status: 200,
199
+ json: async () => ({
200
+ request_id: 'req-cached',
201
+ decrypted: [0x00, 0x00, 0x00, 0x5c],
202
+ signature: `${'01'.repeat(32)}${'02'.repeat(32)}1b`,
203
+ encryption_type: 4,
204
+ }),
205
+ });
206
+ }
207
+
208
+ throw new Error(`Unexpected fetch: ${url}`);
209
+ });
210
+
211
+ global.fetch = fetchMock as any;
212
+
213
+ const result = await tnDecryptV2({
214
+ ctHash: 1n,
215
+ chainId: 1,
216
+ permission: null,
217
+ thresholdNetworkUrl,
218
+ onPoll,
219
+ });
220
+
221
+ expect(result.decryptedValue).toBe(92n);
222
+ expect(result.signature.startsWith('0x')).toBe(true);
223
+ expect(onPoll).not.toHaveBeenCalled();
224
+ expect(fetchMock).toHaveBeenCalledTimes(1);
225
+ });
226
+
227
+ it('tnDecryptV2 uses one timeout budget across submit retries and polling', async () => {
228
+ const onPoll = vi.fn();
229
+
230
+ const requestId = 'req-timeout-budget';
231
+ const testStartTime = Date.now();
232
+ let statusCalls = 0;
233
+ const fetchMock = vi.fn(async (url: string, options?: any) => {
234
+ if (url === `${thresholdNetworkUrl}/v2/decrypt` && options?.method === 'POST') {
235
+ if (Date.now() - testStartTime < 299_000) {
236
+ return makeMockResponse({
237
+ ok: true,
238
+ status: 204,
239
+ json: async () => {
240
+ throw new Error('json() should not be called for 204 submit responses');
241
+ },
242
+ });
243
+ }
244
+
245
+ return makeMockResponse({
246
+ ok: true,
247
+ json: async () => ({ request_id: requestId }),
248
+ });
249
+ }
250
+
251
+ if (url === `${thresholdNetworkUrl}/v2/decrypt/${requestId}` && options?.method === 'GET') {
252
+ statusCalls += 1;
253
+ return makeMockResponse({
254
+ ok: true,
255
+ json: async () => ({
256
+ request_id: requestId,
257
+ status: 'PROCESSING',
258
+ submitted_at: 't',
259
+ }),
260
+ });
261
+ }
262
+
263
+ throw new Error(`Unexpected fetch: ${url}`);
264
+ });
265
+
266
+ global.fetch = fetchMock as any;
267
+
268
+ const promise = tnDecryptV2({
269
+ ctHash: 1n,
270
+ chainId: 1,
271
+ permission: null,
272
+ thresholdNetworkUrl,
273
+ onPoll,
274
+ });
275
+ const rejection = expect(promise).rejects.toMatchObject({
276
+ message: 'decrypt polling timed out after 300000ms',
277
+ });
278
+
279
+ await vi.advanceTimersByTimeAsync(310_000);
280
+
281
+ await rejection;
282
+ expect(statusCalls).toBe(1);
283
+ expect(onPoll).toHaveBeenLastCalledWith(
284
+ expect.objectContaining({
285
+ operation: 'decrypt',
286
+ requestId,
287
+ timeoutMs: 5 * 60 * 1000,
288
+ })
289
+ );
290
+ });
291
+
292
+ it('tnSealOutputV2 calls onPoll once per poll attempt', async () => {
293
+ const onPoll = vi.fn();
294
+
295
+ let sealStatusCalls = 0;
296
+ const fetchMock = vi.fn(async (url: string, options?: any) => {
297
+ if (url === `${thresholdNetworkUrl}/v2/sealoutput` && options?.method === 'POST') {
298
+ return makeMockResponse({
299
+ ok: true,
300
+ json: async () => ({ request_id: 'req-2' }),
301
+ });
302
+ }
303
+
304
+ if (url === `${thresholdNetworkUrl}/v2/sealoutput/req-2` && options?.method === 'GET') {
305
+ sealStatusCalls += 1;
306
+
307
+ if (sealStatusCalls === 1) {
308
+ return makeMockResponse({
309
+ ok: true,
310
+ json: async () => ({
311
+ request_id: 'req-2',
312
+ status: 'PROCESSING',
313
+ submitted_at: 't',
314
+ }),
315
+ });
316
+ }
317
+
318
+ return makeMockResponse({
319
+ ok: true,
320
+ json: async () => ({
321
+ request_id: 'req-2',
322
+ status: 'COMPLETED',
323
+ submitted_at: 't',
324
+ is_succeed: true,
325
+ sealed: {
326
+ data: [1, 2, 3],
327
+ public_key: [4, 5],
328
+ nonce: [6],
329
+ },
330
+ }),
331
+ });
332
+ }
333
+
334
+ throw new Error(`Unexpected fetch: ${url}`);
335
+ });
336
+
337
+ global.fetch = fetchMock as any;
338
+
339
+ const promise = tnSealOutputV2({
340
+ ctHash: 1n,
341
+ chainId: 1,
342
+ permission: {} as any,
343
+ thresholdNetworkUrl,
344
+ onPoll,
345
+ });
346
+
347
+ for (let i = 0; i < 25 && onPoll.mock.calls.length < 1; i += 1) {
348
+ await Promise.resolve();
349
+ }
350
+ expect(onPoll).toHaveBeenCalledTimes(1);
351
+
352
+ await vi.advanceTimersByTimeAsync(1000);
353
+ const sealed = await promise;
354
+
355
+ expect(sealed.data).toBeInstanceOf(Uint8Array);
356
+ expect(Array.from(sealed.data)).toEqual([1, 2, 3]);
357
+
358
+ expect(onPoll).toHaveBeenCalledTimes(2);
359
+ expect(onPoll).toHaveBeenNthCalledWith(
360
+ 1,
361
+ expect.objectContaining({
362
+ operation: 'sealoutput',
363
+ requestId: 'req-2',
364
+ attemptIndex: 0,
365
+ })
366
+ );
367
+ expect(onPoll).toHaveBeenNthCalledWith(
368
+ 2,
369
+ expect.objectContaining({
370
+ operation: 'sealoutput',
371
+ requestId: 'req-2',
372
+ attemptIndex: 1,
373
+ })
374
+ );
375
+ });
376
+
377
+ it('tnSealOutputV2 calls onPoll for 204 submit retries', async () => {
378
+ const onPoll = vi.fn();
379
+
380
+ let submitCalls = 0;
381
+ const fetchMock = vi.fn(async (url: string, options?: any) => {
382
+ if (url === `${thresholdNetworkUrl}/v2/sealoutput` && options?.method === 'POST') {
383
+ submitCalls += 1;
384
+
385
+ if (submitCalls === 1) {
386
+ return makeMockResponse({
387
+ ok: true,
388
+ status: 204,
389
+ json: async () => {
390
+ throw new Error('json() should not be called for 204 submit responses');
391
+ },
392
+ });
393
+ }
394
+
395
+ return makeMockResponse({
396
+ ok: true,
397
+ json: async () => ({ request_id: 'req-seal-submit-retry' }),
398
+ });
399
+ }
400
+
401
+ if (url === `${thresholdNetworkUrl}/v2/sealoutput/req-seal-submit-retry` && options?.method === 'GET') {
402
+ return makeMockResponse({
403
+ ok: true,
404
+ json: async () => ({
405
+ request_id: 'req-seal-submit-retry',
406
+ status: 'COMPLETED',
407
+ submitted_at: 't',
408
+ is_succeed: true,
409
+ sealed: {
410
+ data: [1, 2, 3],
411
+ public_key: [4, 5],
412
+ nonce: [6],
413
+ },
414
+ }),
415
+ });
416
+ }
417
+
418
+ throw new Error(`Unexpected fetch: ${url}`);
419
+ });
420
+
421
+ global.fetch = fetchMock as any;
422
+
423
+ const promise = tnSealOutputV2({
424
+ ctHash: 1n,
425
+ chainId: 1,
426
+ permission: {} as any,
427
+ thresholdNetworkUrl,
428
+ onPoll,
429
+ });
430
+
431
+ for (let i = 0; i < 25 && onPoll.mock.calls.length < 1; i += 1) {
432
+ await Promise.resolve();
433
+ }
434
+
435
+ expect(onPoll).toHaveBeenCalledTimes(1);
436
+ expect(onPoll).toHaveBeenNthCalledWith(
437
+ 1,
438
+ expect.objectContaining({
439
+ operation: 'sealoutput',
440
+ requestId: '',
441
+ attemptIndex: 0,
442
+ intervalMs: 1000,
443
+ timeoutMs: 5 * 60 * 1000,
444
+ })
445
+ );
446
+
447
+ await vi.advanceTimersByTimeAsync(1000);
448
+ await promise;
449
+
450
+ expect(onPoll).toHaveBeenCalledTimes(2);
451
+ expect(onPoll).toHaveBeenNthCalledWith(
452
+ 2,
453
+ expect.objectContaining({
454
+ operation: 'sealoutput',
455
+ requestId: 'req-seal-submit-retry',
456
+ attemptIndex: 0,
457
+ })
458
+ );
459
+ });
460
+
461
+ it('tnSealOutputV2 returns immediately when submit responds with cached completed payload', async () => {
462
+ const onPoll = vi.fn();
463
+
464
+ const fetchMock = vi.fn(async (url: string, options?: any) => {
465
+ if (url === `${thresholdNetworkUrl}/v2/sealoutput` && options?.method === 'POST') {
466
+ return makeMockResponse({
467
+ ok: true,
468
+ status: 200,
469
+ json: async () => ({
470
+ request_id: 'req-seal-cached',
471
+ sealed_data: [1, 2, 3],
472
+ ephemeral_public_key: [4, 5],
473
+ nonce: [6],
474
+ encryption_type: 4,
475
+ }),
476
+ });
477
+ }
478
+
479
+ throw new Error(`Unexpected fetch: ${url}`);
480
+ });
481
+
482
+ global.fetch = fetchMock as any;
483
+
484
+ const sealed = await tnSealOutputV2({
485
+ ctHash: 1n,
486
+ chainId: 1,
487
+ permission: {} as any,
488
+ thresholdNetworkUrl,
489
+ onPoll,
490
+ });
491
+
492
+ expect(Array.from(sealed.data)).toEqual([1, 2, 3]);
493
+ expect(Array.from(sealed.public_key)).toEqual([4, 5]);
494
+ expect(Array.from(sealed.nonce)).toEqual([6]);
495
+ expect(onPoll).not.toHaveBeenCalled();
496
+ expect(fetchMock).toHaveBeenCalledTimes(1);
497
+ });
498
+
499
+ it('tnSealOutputV2 uses one timeout budget across submit retries and polling', async () => {
500
+ const onPoll = vi.fn();
501
+
502
+ const requestId = 'req-seal-timeout-budget';
503
+ const testStartTime = Date.now();
504
+ let statusCalls = 0;
505
+ const fetchMock = vi.fn(async (url: string, options?: any) => {
506
+ if (url === `${thresholdNetworkUrl}/v2/sealoutput` && options?.method === 'POST') {
507
+ if (Date.now() - testStartTime < 299_000) {
508
+ return makeMockResponse({
509
+ ok: true,
510
+ status: 204,
511
+ json: async () => {
512
+ throw new Error('json() should not be called for 204 submit responses');
513
+ },
514
+ });
515
+ }
516
+
517
+ return makeMockResponse({
518
+ ok: true,
519
+ json: async () => ({ request_id: requestId }),
520
+ });
521
+ }
522
+
523
+ if (url === `${thresholdNetworkUrl}/v2/sealoutput/${requestId}` && options?.method === 'GET') {
524
+ statusCalls += 1;
525
+ return makeMockResponse({
526
+ ok: true,
527
+ json: async () => ({
528
+ request_id: requestId,
529
+ status: 'PROCESSING',
530
+ submitted_at: 't',
531
+ }),
532
+ });
533
+ }
534
+
535
+ throw new Error(`Unexpected fetch: ${url}`);
536
+ });
537
+
538
+ global.fetch = fetchMock as any;
539
+
540
+ const promise = tnSealOutputV2({
541
+ ctHash: 1n,
542
+ chainId: 1,
543
+ permission: {} as any,
544
+ thresholdNetworkUrl,
545
+ onPoll,
546
+ });
547
+ const rejection = expect(promise).rejects.toMatchObject({
548
+ message: 'sealOutput polling timed out after 300000ms',
549
+ });
550
+
551
+ await vi.advanceTimersByTimeAsync(310_000);
552
+
553
+ await rejection;
554
+ expect(statusCalls).toBe(1);
555
+ expect(onPoll).toHaveBeenLastCalledWith(
556
+ expect.objectContaining({
557
+ operation: 'sealoutput',
558
+ requestId,
559
+ timeoutMs: 5 * 60 * 1000,
560
+ })
561
+ );
562
+ });
563
+ });
package/core/types.ts CHANGED
@@ -389,6 +389,19 @@ export type EncryptStepCallbackFunction = (state: EncryptStep, context?: Encrypt
389
389
 
390
390
  // DECRYPT
391
391
 
392
+ export type DecryptEndpoint = 'decrypt' | 'sealoutput';
393
+
394
+ export type DecryptPollCallbackContext = {
395
+ operation: DecryptEndpoint;
396
+ requestId: string;
397
+ attemptIndex: number;
398
+ elapsedMs: number;
399
+ intervalMs: number;
400
+ timeoutMs: number;
401
+ };
402
+
403
+ export type DecryptPollCallbackFunction = (context: DecryptPollCallbackContext) => void;
404
+
392
405
  /**
393
406
  * Decrypted plaintext value returned by view-decryption helpers.
394
407
  *
package/dist/chains.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CofheChain } from './types-YiAC4gig.cjs';
2
- export { E as Environment } from './types-YiAC4gig.cjs';
1
+ import { C as CofheChain } from './types-C07FK-cL.cjs';
2
+ export { E as Environment } from './types-C07FK-cL.cjs';
3
3
  import 'zod';
4
4
 
5
5
  /**
package/dist/chains.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CofheChain } from './types-YiAC4gig.js';
2
- export { E as Environment } from './types-YiAC4gig.js';
1
+ import { C as CofheChain } from './types-C07FK-cL.js';
2
+ export { E as Environment } from './types-C07FK-cL.js';
3
3
  import 'zod';
4
4
 
5
5
  /**
@@ -0,0 +1,13 @@
1
+ // core/consts.ts
2
+ var TASK_MANAGER_ADDRESS = "0xeA30c4B8b44078Bbf8a6ef5b9f1eC1626C7848D9";
3
+ var MOCKS_ZK_VERIFIER_ADDRESS = "0x0000000000000000000000000000000000005001";
4
+ var MOCKS_THRESHOLD_NETWORK_ADDRESS = "0x0000000000000000000000000000000000005002";
5
+ var TEST_BED_ADDRESS = "0x0000000000000000000000000000000000005003";
6
+ var MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY = "0x6C8D7F768A6BB4AAFE85E8A2F5A9680355239C7E14646ED62B044E39DE154512";
7
+ var MOCKS_ZK_VERIFIER_SIGNER_ADDRESS = "0x6E12D8C87503D4287c294f2Fdef96ACd9DFf6bd2";
8
+ var MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d";
9
+ var TFHE_RS_ZK_MAX_BITS = 2048;
10
+ var TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT = BigInt(1 << 30);
11
+ var TFHE_RS_KEY_VERSION = 2;
12
+
13
+ export { MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY, MOCKS_THRESHOLD_NETWORK_ADDRESS, MOCKS_ZK_VERIFIER_ADDRESS, MOCKS_ZK_VERIFIER_SIGNER_ADDRESS, MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY, TASK_MANAGER_ADDRESS, TEST_BED_ADDRESS, TFHE_RS_KEY_VERSION, TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT, TFHE_RS_ZK_MAX_BITS };