@cofhe/sdk 0.5.1 → 0.5.2
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.
- package/CHANGELOG.md +10 -0
- package/adapters/test/ethers5.test.ts +1 -1
- package/adapters/test/ethers6.test.ts +1 -1
- package/adapters/test/wagmi.test.ts +1 -1
- package/core/decrypt/decryptForTxBuilder.ts +21 -0
- package/core/decrypt/decryptForViewBuilder.ts +19 -0
- package/core/decrypt/submitRetry.ts +126 -0
- package/core/decrypt/tnDecryptV2.ts +48 -53
- package/core/decrypt/tnSealOutputV2.ts +48 -54
- package/core/test/decryptBuilders.test.ts +28 -0
- package/core/test/pollCallbacks.test.ts +226 -0
- package/dist/{chunk-S7OKGLFD.js → chunk-YDOK4BDL.js} +253 -147
- package/dist/{clientTypes-BSbwairE.d.cts → clientTypes-BJbFeeno.d.cts} +5 -0
- package/dist/{clientTypes-DDmcgZ0a.d.ts → clientTypes-CEno_BEf.d.ts} +5 -0
- package/dist/core.cjs +253 -147
- package/dist/core.d.cts +2 -2
- package/dist/core.d.ts +2 -2
- package/dist/core.js +1 -1
- package/dist/node.cjs +208 -102
- package/dist/node.d.cts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +1 -1
- package/dist/web.cjs +208 -102
- package/dist/web.d.cts +1 -1
- package/dist/web.d.ts +1 -1
- package/dist/web.js +1 -1
- package/package.json +1 -1
- package/web/test/tfheinit.web.test.ts +3 -3
|
@@ -188,6 +188,117 @@ describe('decrypt polling callbacks', () => {
|
|
|
188
188
|
);
|
|
189
189
|
});
|
|
190
190
|
|
|
191
|
+
it('tnDecryptV2 calls onPoll for 404 submit retries', async () => {
|
|
192
|
+
const onPoll = vi.fn();
|
|
193
|
+
|
|
194
|
+
let submitCalls = 0;
|
|
195
|
+
const fetchMock = vi.fn(async (url: string, options?: any) => {
|
|
196
|
+
if (url === `${thresholdNetworkUrl}/v2/decrypt` && options?.method === 'POST') {
|
|
197
|
+
submitCalls += 1;
|
|
198
|
+
|
|
199
|
+
if (submitCalls === 1) {
|
|
200
|
+
return makeMockResponse({
|
|
201
|
+
ok: false,
|
|
202
|
+
status: 404,
|
|
203
|
+
statusText: 'Not Found',
|
|
204
|
+
json: async () => ({ message: 'Not Found' }),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return makeMockResponse({
|
|
209
|
+
ok: true,
|
|
210
|
+
json: async () => ({ request_id: 'req-submit-retry-404' }),
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (url === `${thresholdNetworkUrl}/v2/decrypt/req-submit-retry-404` && options?.method === 'GET') {
|
|
215
|
+
return makeMockResponse({
|
|
216
|
+
ok: true,
|
|
217
|
+
json: async () => ({
|
|
218
|
+
request_id: 'req-submit-retry-404',
|
|
219
|
+
status: 'COMPLETED',
|
|
220
|
+
submitted_at: 't',
|
|
221
|
+
is_succeed: true,
|
|
222
|
+
decrypted: [0x01],
|
|
223
|
+
signature: `0x${'01'.repeat(32)}${'02'.repeat(32)}1b`,
|
|
224
|
+
}),
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
throw new Error(`Unexpected fetch: ${url}`);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
global.fetch = fetchMock as any;
|
|
232
|
+
|
|
233
|
+
const promise = tnDecryptV2({
|
|
234
|
+
ctHash: 1n,
|
|
235
|
+
chainId: 1,
|
|
236
|
+
permission: null,
|
|
237
|
+
thresholdNetworkUrl,
|
|
238
|
+
onPoll,
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
for (let i = 0; i < 25 && onPoll.mock.calls.length < 1; i += 1) {
|
|
242
|
+
await Promise.resolve();
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
expect(onPoll).toHaveBeenCalledTimes(1);
|
|
246
|
+
expect(onPoll).toHaveBeenNthCalledWith(
|
|
247
|
+
1,
|
|
248
|
+
expect.objectContaining({
|
|
249
|
+
operation: 'decrypt',
|
|
250
|
+
requestId: '',
|
|
251
|
+
attemptIndex: 0,
|
|
252
|
+
intervalMs: 1000,
|
|
253
|
+
timeoutMs: 5 * 60 * 1000,
|
|
254
|
+
})
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
await vi.advanceTimersByTimeAsync(1000);
|
|
258
|
+
await promise;
|
|
259
|
+
|
|
260
|
+
expect(onPoll).toHaveBeenCalledTimes(2);
|
|
261
|
+
expect(onPoll).toHaveBeenNthCalledWith(
|
|
262
|
+
2,
|
|
263
|
+
expect.objectContaining({
|
|
264
|
+
operation: 'decrypt',
|
|
265
|
+
requestId: 'req-submit-retry-404',
|
|
266
|
+
attemptIndex: 0,
|
|
267
|
+
})
|
|
268
|
+
);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it('tnDecryptV2 times out 404 submit retries using default timeout', async () => {
|
|
272
|
+
const fetchMock = vi.fn(async (url: string, options?: any) => {
|
|
273
|
+
if (url === `${thresholdNetworkUrl}/v2/decrypt` && options?.method === 'POST') {
|
|
274
|
+
return makeMockResponse({
|
|
275
|
+
ok: false,
|
|
276
|
+
status: 404,
|
|
277
|
+
statusText: 'Not Found',
|
|
278
|
+
json: async () => ({ message: 'Not Found' }),
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
throw new Error(`Unexpected fetch: ${url}`);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
global.fetch = fetchMock as any;
|
|
286
|
+
|
|
287
|
+
const promise = tnDecryptV2({
|
|
288
|
+
ctHash: 1n,
|
|
289
|
+
chainId: 1,
|
|
290
|
+
permission: null,
|
|
291
|
+
thresholdNetworkUrl,
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
const rejection = expect(promise).rejects.toMatchObject({
|
|
295
|
+
message: 'decrypt submit retried 404 responses without receiving request_id for 10000ms',
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
await vi.advanceTimersByTimeAsync(11_000);
|
|
299
|
+
await rejection;
|
|
300
|
+
});
|
|
301
|
+
|
|
191
302
|
it('tnDecryptV2 returns immediately when submit responds with cached completed payload', async () => {
|
|
192
303
|
const onPoll = vi.fn();
|
|
193
304
|
|
|
@@ -458,6 +569,121 @@ describe('decrypt polling callbacks', () => {
|
|
|
458
569
|
);
|
|
459
570
|
});
|
|
460
571
|
|
|
572
|
+
it('tnSealOutputV2 calls onPoll for 404 submit retries', async () => {
|
|
573
|
+
const onPoll = vi.fn();
|
|
574
|
+
|
|
575
|
+
let submitCalls = 0;
|
|
576
|
+
const fetchMock = vi.fn(async (url: string, options?: any) => {
|
|
577
|
+
if (url === `${thresholdNetworkUrl}/v2/sealoutput` && options?.method === 'POST') {
|
|
578
|
+
submitCalls += 1;
|
|
579
|
+
|
|
580
|
+
if (submitCalls === 1) {
|
|
581
|
+
return makeMockResponse({
|
|
582
|
+
ok: false,
|
|
583
|
+
status: 404,
|
|
584
|
+
statusText: 'Not Found',
|
|
585
|
+
json: async () => ({ message: 'Not Found' }),
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
return makeMockResponse({
|
|
590
|
+
ok: true,
|
|
591
|
+
json: async () => ({ request_id: 'req-seal-submit-retry-404' }),
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
if (url === `${thresholdNetworkUrl}/v2/sealoutput/req-seal-submit-retry-404` && options?.method === 'GET') {
|
|
596
|
+
return makeMockResponse({
|
|
597
|
+
ok: true,
|
|
598
|
+
json: async () => ({
|
|
599
|
+
request_id: 'req-seal-submit-retry-404',
|
|
600
|
+
status: 'COMPLETED',
|
|
601
|
+
submitted_at: 't',
|
|
602
|
+
is_succeed: true,
|
|
603
|
+
sealed: {
|
|
604
|
+
data: [1, 2, 3],
|
|
605
|
+
public_key: [4, 5],
|
|
606
|
+
nonce: [6],
|
|
607
|
+
},
|
|
608
|
+
}),
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
throw new Error(`Unexpected fetch: ${url}`);
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
global.fetch = fetchMock as any;
|
|
616
|
+
|
|
617
|
+
const promise = tnSealOutputV2({
|
|
618
|
+
ctHash: 1n,
|
|
619
|
+
chainId: 1,
|
|
620
|
+
permission: {} as any,
|
|
621
|
+
thresholdNetworkUrl,
|
|
622
|
+
onPoll,
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
for (let i = 0; i < 25 && onPoll.mock.calls.length < 1; i += 1) {
|
|
626
|
+
await Promise.resolve();
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
expect(onPoll).toHaveBeenCalledTimes(1);
|
|
630
|
+
expect(onPoll).toHaveBeenNthCalledWith(
|
|
631
|
+
1,
|
|
632
|
+
expect.objectContaining({
|
|
633
|
+
operation: 'sealoutput',
|
|
634
|
+
requestId: '',
|
|
635
|
+
attemptIndex: 0,
|
|
636
|
+
intervalMs: 1000,
|
|
637
|
+
timeoutMs: 5 * 60 * 1000,
|
|
638
|
+
})
|
|
639
|
+
);
|
|
640
|
+
|
|
641
|
+
await vi.advanceTimersByTimeAsync(1000);
|
|
642
|
+
await promise;
|
|
643
|
+
|
|
644
|
+
expect(onPoll).toHaveBeenCalledTimes(2);
|
|
645
|
+
expect(onPoll).toHaveBeenNthCalledWith(
|
|
646
|
+
2,
|
|
647
|
+
expect.objectContaining({
|
|
648
|
+
operation: 'sealoutput',
|
|
649
|
+
requestId: 'req-seal-submit-retry-404',
|
|
650
|
+
attemptIndex: 0,
|
|
651
|
+
})
|
|
652
|
+
);
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
it('tnSealOutputV2 uses custom 404 submit retry timeout', async () => {
|
|
656
|
+
const fetchMock = vi.fn(async (url: string, options?: any) => {
|
|
657
|
+
if (url === `${thresholdNetworkUrl}/v2/sealoutput` && options?.method === 'POST') {
|
|
658
|
+
return makeMockResponse({
|
|
659
|
+
ok: false,
|
|
660
|
+
status: 404,
|
|
661
|
+
statusText: 'Not Found',
|
|
662
|
+
json: async () => ({ message: 'Not Found' }),
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
throw new Error(`Unexpected fetch: ${url}`);
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
global.fetch = fetchMock as any;
|
|
670
|
+
|
|
671
|
+
const promise = tnSealOutputV2({
|
|
672
|
+
ctHash: 1n,
|
|
673
|
+
chainId: 1,
|
|
674
|
+
permission: {} as any,
|
|
675
|
+
thresholdNetworkUrl,
|
|
676
|
+
retry404TimeoutMs: 2000,
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
const rejection = expect(promise).rejects.toMatchObject({
|
|
680
|
+
message: 'sealOutput submit retried 404 responses without receiving request_id for 2000ms',
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
await vi.advanceTimersByTimeAsync(3000);
|
|
684
|
+
await rejection;
|
|
685
|
+
});
|
|
686
|
+
|
|
461
687
|
it('tnSealOutputV2 returns immediately when submit responds with cached completed payload', async () => {
|
|
462
688
|
const onPoll = vi.fn();
|
|
463
689
|
|