@cofhe/sdk 0.6.1 → 0.7.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 (113) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/acps/acp.ts +411 -0
  3. package/acps/index.ts +70 -0
  4. package/{permits → acps}/onchain-utils.ts +49 -24
  5. package/acps/sealing.ts +90 -0
  6. package/acps/signature.ts +89 -0
  7. package/acps/store.ts +172 -0
  8. package/acps/test/acp.test.ts +615 -0
  9. package/acps/test/localstorage.test.ts +105 -0
  10. package/acps/test/sealing.test.ts +77 -0
  11. package/acps/test/store.test.ts +88 -0
  12. package/acps/test/validation.test.ts +361 -0
  13. package/acps/test-utils.ts +32 -0
  14. package/acps/types.ts +252 -0
  15. package/acps/validation.ts +392 -0
  16. package/adapters/test/ethers5.test.ts +4 -1
  17. package/adapters/test/ethers6.test.ts +4 -1
  18. package/adapters/test/wagmi.test.ts +5 -2
  19. package/chains/chains/stagingCofhe.ts +21 -0
  20. package/chains/index.ts +3 -1
  21. package/chains/test/chains.test.ts +2 -1
  22. package/core/acps.ts +625 -0
  23. package/core/client.ts +136 -39
  24. package/core/clientTypes.ts +52 -41
  25. package/core/config.ts +66 -5
  26. package/core/decrypt/MockThresholdNetworkAbi.ts +20 -11
  27. package/core/decrypt/apiError.ts +104 -0
  28. package/core/decrypt/cofheMocksDecryptForTx.ts +11 -11
  29. package/core/decrypt/cofheMocksDecryptForView.ts +7 -7
  30. package/core/decrypt/decryptForTxBuilder.ts +102 -102
  31. package/core/decrypt/decryptForViewBuilder.ts +90 -90
  32. package/core/decrypt/submitRetry.ts +38 -30
  33. package/core/decrypt/tnDecryptV1.ts +5 -5
  34. package/core/decrypt/tnDecryptV2.ts +25 -21
  35. package/core/decrypt/tnSealOutputV1.ts +4 -3
  36. package/core/decrypt/tnSealOutputV2.ts +24 -18
  37. package/core/encrypt/cofheMocksZkVerifySign.ts +59 -74
  38. package/core/encrypt/encryptInputsBuilder.ts +86 -52
  39. package/core/encrypt/zkPackProveVerify.ts +25 -18
  40. package/core/error.ts +34 -6
  41. package/core/index.ts +4 -14
  42. package/core/test/acpDefaults.test.ts +52 -0
  43. package/core/test/acps.test.ts +596 -0
  44. package/core/test/apiError.test.ts +130 -0
  45. package/core/test/client.test.ts +22 -19
  46. package/core/test/config.test.ts +25 -5
  47. package/core/test/decrypt.test.ts +40 -35
  48. package/core/test/decryptBuilders.test.ts +68 -68
  49. package/core/test/decryptErrorCodes.test.ts +217 -0
  50. package/core/test/encryptInputsBuilder.test.ts +72 -41
  51. package/core/test/pollCallbacks.test.ts +89 -18
  52. package/core/test/stagingRedirect.ts +18 -0
  53. package/core/test/submitRetry.test.ts +182 -0
  54. package/core/types.ts +9 -69
  55. package/dist/acp-Wi6isVQI.d.cts +407 -0
  56. package/dist/acp-Wi6isVQI.d.ts +407 -0
  57. package/dist/acps.cjs +1081 -0
  58. package/dist/acps.d.cts +480 -0
  59. package/dist/acps.d.ts +480 -0
  60. package/dist/acps.js +2 -0
  61. package/dist/chains.cjs +14 -1
  62. package/dist/chains.d.cts +30 -1
  63. package/dist/chains.d.ts +30 -1
  64. package/dist/chains.js +1 -1
  65. package/dist/{chunk-NOC3PYB7.js → chunk-43USWPEH.js} +930 -580
  66. package/dist/{chunk-MTRAXQXC.js → chunk-N6IDQRRU.js} +14 -2
  67. package/dist/chunk-Q7CBWGQX.js +1029 -0
  68. package/dist/{clientTypes-CyUvRRzA.d.ts → clientTypes-BN3nbzYM.d.ts} +342 -165
  69. package/dist/{clientTypes-BDy1qIBu.d.cts → clientTypes-CYZjFznO.d.cts} +342 -165
  70. package/dist/core.cjs +1358 -1002
  71. package/dist/core.d.cts +31 -9
  72. package/dist/core.d.ts +31 -9
  73. package/dist/core.js +3 -3
  74. package/dist/node.cjs +1293 -952
  75. package/dist/node.d.cts +2 -2
  76. package/dist/node.d.ts +2 -2
  77. package/dist/node.js +3 -3
  78. package/dist/web.cjs +1293 -952
  79. package/dist/web.d.cts +2 -2
  80. package/dist/web.d.ts +2 -2
  81. package/dist/web.js +3 -3
  82. package/node/test/inherited.test.ts +75 -65
  83. package/node/test/tfheinit.test.ts +23 -8
  84. package/package.json +6 -6
  85. package/web/test/client.web.test.ts +5 -1
  86. package/web/test/inherited.web.test.ts +75 -65
  87. package/web/test/tfheinit.web.test.ts +14 -5
  88. package/web/test/worker.config.web.test.ts +38 -23
  89. package/web/test/worker.output.web.test.ts +25 -24
  90. package/core/encrypt/encryptUtils.ts +0 -67
  91. package/core/permits.ts +0 -216
  92. package/core/test/permits.test.ts +0 -596
  93. package/dist/chunk-VB62WYPL.js +0 -978
  94. package/dist/permit-DnVMDT5h.d.cts +0 -376
  95. package/dist/permit-DnVMDT5h.d.ts +0 -376
  96. package/dist/permits.cjs +0 -1026
  97. package/dist/permits.d.cts +0 -353
  98. package/dist/permits.d.ts +0 -353
  99. package/dist/permits.js +0 -2
  100. package/permits/index.ts +0 -68
  101. package/permits/permit.ts +0 -385
  102. package/permits/sealing.ts +0 -131
  103. package/permits/signature.ts +0 -79
  104. package/permits/store.ts +0 -157
  105. package/permits/test/localstorage.test.ts +0 -113
  106. package/permits/test/permit.test.ts +0 -557
  107. package/permits/test/sealing.test.ts +0 -84
  108. package/permits/test/store.test.ts +0 -88
  109. package/permits/test/validation.test.ts +0 -361
  110. package/permits/test-utils.ts +0 -28
  111. package/permits/types.ts +0 -204
  112. package/permits/validation.ts +0 -327
  113. /package/{permits → acps}/utils.ts +0 -0
@@ -1,596 +0,0 @@
1
- /**
2
- * @vitest-environment happy-dom
3
- */
4
- import { permitStore } from '@/permits';
5
-
6
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
7
- import { createPublicClient, createWalletClient, http, type PublicClient, type WalletClient } from 'viem';
8
- import { arbitrumSepolia } from 'viem/chains';
9
- import { privateKeyToAccount } from 'viem/accounts';
10
- import { permits } from '../permits.js';
11
-
12
- // Type declarations for happy-dom environment
13
- declare const localStorage: {
14
- clear: () => void;
15
- getItem: (name: string) => string | null;
16
- setItem: (name: string, value: string) => void;
17
- };
18
-
19
- // Test private keys (well-known test keys from Anvil/Hardhat)
20
- const BOB_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'; // Bob - always issuer
21
- const ALICE_PRIVATE_KEY = '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d'; // Alice - always recipient
22
-
23
- // Create real viem clients for Arbitrum Sepolia
24
- const publicClient: PublicClient = createPublicClient({
25
- chain: arbitrumSepolia,
26
- transport: http(),
27
- });
28
-
29
- const bobWalletClient: WalletClient = createWalletClient({
30
- chain: arbitrumSepolia,
31
- transport: http(),
32
- account: privateKeyToAccount(BOB_PRIVATE_KEY),
33
- });
34
-
35
- const aliceWalletClient: WalletClient = createWalletClient({
36
- chain: arbitrumSepolia,
37
- transport: http(),
38
- account: privateKeyToAccount(ALICE_PRIVATE_KEY),
39
- });
40
-
41
- // Helper to get the wallet addresses
42
- const bobAddress = bobWalletClient.account!.address;
43
- const aliceAddress = aliceWalletClient.account!.address;
44
- const chainId = 421614; // Arbitrum Sepolia
45
-
46
- describe('Core Permits Tests', () => {
47
- beforeEach(() => {
48
- // Clear localStorage and reset stores
49
- localStorage.clear();
50
- permitStore.store.setState({ permits: {}, activePermitHash: {} });
51
- });
52
-
53
- afterEach(() => {
54
- localStorage.clear();
55
- permitStore.store.setState({ permits: {}, activePermitHash: {} });
56
- });
57
-
58
- describe('Permit Creation', () => {
59
- it('should create and store self permit', async () => {
60
- const permit = await permits.createSelf(
61
- { name: 'Test Self Permit', issuer: bobAddress },
62
- publicClient,
63
- bobWalletClient
64
- );
65
-
66
- expect(permit).toBeDefined();
67
- expect(permit.name).toBe('Test Self Permit');
68
- expect(permit.type).toBe('self');
69
- expect(permit.issuer).toBe(bobAddress);
70
- expect(permit.issuerSignature).toBeDefined();
71
- expect(permit.issuerSignature).not.toBe('0x');
72
-
73
- // Verify localStorage
74
- const storedData = localStorage.getItem('cofhesdk-permits');
75
- expect(storedData).toBeDefined();
76
- const parsedData = JSON.parse(storedData!);
77
- expect(parsedData.state.permits[chainId][bobAddress]).toBeDefined();
78
- expect(parsedData.state.activePermitHash[chainId][bobAddress]).toBeDefined();
79
- });
80
-
81
- it('should create and store sharing permit', async () => {
82
- const permit = await permits.createSharing(
83
- {
84
- name: 'Test Sharing Permit',
85
- issuer: bobAddress,
86
- recipient: aliceAddress,
87
- },
88
- publicClient,
89
- bobWalletClient
90
- );
91
-
92
- expect(permit.name).toBe('Test Sharing Permit');
93
- expect(permit.type).toBe('sharing');
94
- expect(permit.issuer).toBe(bobAddress);
95
- expect(permit.recipient).toBe(aliceAddress);
96
- expect(permit.issuerSignature).toBeDefined();
97
- expect(permit.issuerSignature).not.toBe('0x');
98
-
99
- // Verify localStorage
100
- const storedData = localStorage.getItem('cofhesdk-permits');
101
- expect(storedData).toBeDefined();
102
- const parsedData = JSON.parse(storedData!);
103
- expect(parsedData.state.permits[chainId][bobAddress]).toBeDefined();
104
- expect(parsedData.state.activePermitHash[chainId][bobAddress]).toBeDefined();
105
- });
106
-
107
- it('should import shared permit from JSON string', async () => {
108
- // First create a sharing permit to import
109
- const sharingPermit = await permits.createSharing(
110
- {
111
- name: 'Original Sharing Permit',
112
- issuer: bobAddress,
113
- recipient: aliceAddress,
114
- },
115
- publicClient,
116
- bobWalletClient
117
- );
118
-
119
- // Export the permit as JSON string
120
- const permitJson = JSON.stringify({
121
- name: sharingPermit.name,
122
- type: sharingPermit.type,
123
- issuer: sharingPermit.issuer,
124
- expiration: sharingPermit.expiration,
125
- recipient: sharingPermit.recipient,
126
- validatorId: sharingPermit.validatorId,
127
- validatorContract: sharingPermit.validatorContract,
128
- issuerSignature: sharingPermit.issuerSignature,
129
- });
130
-
131
- // Import the permit as Alice (recipient)
132
- const permit = await permits.importShared(permitJson, publicClient, aliceWalletClient);
133
-
134
- expect(permit.name).toBe('Original Sharing Permit');
135
- expect(permit.type).toBe('recipient');
136
- expect(permit.issuer).toBe(bobAddress);
137
- expect(permit.recipient).toBe(aliceAddress);
138
- expect(permit.recipientSignature).toBeDefined();
139
- expect(permit.recipientSignature).not.toBe('0x');
140
- });
141
- });
142
-
143
- describe('Permit Retrieval', () => {
144
- let createdPermit: any;
145
- let permitHash: string;
146
-
147
- beforeEach(async () => {
148
- // Create a real permit for testing
149
- createdPermit = await permits.createSelf(
150
- { name: 'Test Permit', issuer: bobAddress },
151
- publicClient,
152
- bobWalletClient
153
- );
154
- permitHash = createdPermit.hash;
155
- });
156
-
157
- it('should get permit by hash', async () => {
158
- const permit = await permits.getPermit(chainId, bobAddress, permitHash);
159
- expect(permit?.name).toBe('Test Permit');
160
- expect(permit?.type).toBe('self');
161
- });
162
-
163
- it('should get all permits', async () => {
164
- const allPermits = await permits.getPermits(chainId, bobAddress);
165
- expect(Object.keys(allPermits).length).toBeGreaterThan(0);
166
- });
167
-
168
- it('should get active permit', async () => {
169
- const permit = await permits.getActivePermit(chainId, bobAddress);
170
- expect(permit?.name).toBe('Test Permit');
171
- });
172
-
173
- it('should get active permit hash', async () => {
174
- const hash = await permits.getActivePermitHash(chainId, bobAddress);
175
- expect(typeof hash).toBe('string');
176
- });
177
- });
178
-
179
- describe('localStorage Integration', () => {
180
- it('should persist permits to localStorage', async () => {
181
- const createdPermit = await permits.createSelf(
182
- { name: 'Test Permit', issuer: bobAddress },
183
- publicClient,
184
- bobWalletClient
185
- );
186
-
187
- const storedData = localStorage.getItem('cofhesdk-permits');
188
- expect(storedData).toBeDefined();
189
-
190
- const parsedData = JSON.parse(storedData!);
191
- expect(parsedData.state.permits[chainId][bobAddress]).toBeDefined();
192
- expect(parsedData.state.activePermitHash[chainId][bobAddress]).toBeDefined();
193
-
194
- // Verify the permit data structure
195
- const permitKeys = Object.keys(parsedData.state.permits[chainId][bobAddress]);
196
- expect(permitKeys.length).toBeGreaterThan(0);
197
-
198
- const serializedPermit = permits.serialize(createdPermit);
199
- expect(parsedData.state.permits[chainId][bobAddress][createdPermit.hash]).toEqual(serializedPermit);
200
- });
201
- });
202
-
203
- describe('Real Network Integration', () => {
204
- it('should create permit with real EIP712 domain from Arbitrum Sepolia', async () => {
205
- const permit = await permits.createSelf(
206
- { name: 'Real Network Permit', issuer: bobAddress },
207
- publicClient,
208
- bobWalletClient
209
- );
210
-
211
- expect(permit._signedDomain).toBeDefined();
212
- expect(permit._signedDomain?.chainId).toBe(chainId);
213
- expect(permit._signedDomain?.name).toBeDefined();
214
- expect(permit._signedDomain?.version).toBeDefined();
215
- expect(permit._signedDomain?.verifyingContract).toBeDefined();
216
- });
217
-
218
- it('should handle multiple permits on real network', async () => {
219
- // Create multiple permits
220
- await permits.createSelf({ name: 'Permit 1', issuer: bobAddress }, publicClient, bobWalletClient);
221
- await permits.createSharing(
222
- {
223
- name: 'Permit 2',
224
- issuer: bobAddress,
225
- recipient: aliceAddress,
226
- },
227
- publicClient,
228
- bobWalletClient
229
- );
230
-
231
- // Verify both permits exist
232
- const allPermits = await permits.getPermits(chainId, bobAddress);
233
- expect(Object.keys(allPermits).length).toBeGreaterThanOrEqual(2);
234
-
235
- // Verify active permit is the last created one
236
- const activePermit = await permits.getActivePermit(chainId, bobAddress);
237
- expect(activePermit?.name).toBe('Permit 2');
238
- });
239
- });
240
-
241
- describe('getOrCreateSelfPermit', () => {
242
- it('should create a new self permit when none exists', async () => {
243
- const permit = await permits.getOrCreateSelfPermit(publicClient, bobWalletClient, chainId, bobAddress, {
244
- issuer: bobAddress,
245
- name: 'New Self Permit',
246
- });
247
-
248
- expect(permit).toBeDefined();
249
- expect(permit.name).toBe('New Self Permit');
250
- expect(permit.type).toBe('self');
251
- expect(permit.issuer).toBe(bobAddress);
252
- expect(permit.issuerSignature).toBeDefined();
253
-
254
- // Verify it was stored and set as active
255
- const activePermit = await permits.getActivePermit(chainId, bobAddress);
256
- expect(activePermit?.name).toBe('New Self Permit');
257
- });
258
-
259
- it('should return existing self permit when one exists', async () => {
260
- // Create an initial self permit
261
- const firstPermit = await permits.createSelf(
262
- { name: 'First Self Permit', issuer: bobAddress },
263
- publicClient,
264
- bobWalletClient
265
- );
266
-
267
- // Call getOrCreateSelfPermit - should return existing
268
- const permit = await permits.getOrCreateSelfPermit(publicClient, bobWalletClient, chainId, bobAddress, {
269
- issuer: bobAddress,
270
- name: 'Should Not Create This',
271
- });
272
-
273
- expect(permit.name).toBe('First Self Permit');
274
- expect(permit.hash).toBe(firstPermit.hash);
275
-
276
- // Verify no new permit was created
277
- const allPermits = await permits.getPermits(chainId, bobAddress);
278
- expect(Object.keys(allPermits).length).toBe(1);
279
- });
280
-
281
- it('should create new self permit when active permit is sharing type', async () => {
282
- // Create a sharing permit first
283
- await permits.createSharing(
284
- {
285
- name: 'Sharing Permit',
286
- issuer: bobAddress,
287
- recipient: aliceAddress,
288
- },
289
- publicClient,
290
- bobWalletClient
291
- );
292
-
293
- // Call getOrCreateSelfPermit - should create new since active is sharing type
294
- const permit = await permits.getOrCreateSelfPermit(publicClient, bobWalletClient, chainId, bobAddress, {
295
- issuer: bobAddress,
296
- name: 'New Self Permit',
297
- });
298
-
299
- expect(permit.name).toBe('New Self Permit');
300
- expect(permit.type).toBe('self');
301
-
302
- // Verify two permits exist now
303
- const allPermits = await permits.getPermits(chainId, bobAddress);
304
- expect(Object.keys(allPermits).length).toBe(2);
305
- });
306
-
307
- it('should create a new self permit when active permit is expired', async () => {
308
- // Create an expired self permit (expiration in the past)
309
- const expiredPermit = await permits.createSelf(
310
- { name: 'Expired Self Permit', issuer: bobAddress, expiration: Math.floor(Date.now() / 1000) - 3600 },
311
- publicClient,
312
- bobWalletClient
313
- );
314
-
315
- // Sanity check - it is the active permit and is expired
316
- const activeBefore = await permits.getActivePermit(chainId, bobAddress);
317
- expect(activeBefore?.hash).toBe(expiredPermit.hash);
318
-
319
- // getOrCreateSelfPermit should treat the expired permit as missing and create a fresh one
320
- const permit = await permits.getOrCreateSelfPermit(publicClient, bobWalletClient, chainId, bobAddress, {
321
- issuer: bobAddress,
322
- name: 'Fresh Self Permit',
323
- });
324
-
325
- expect(permit.name).toBe('Fresh Self Permit');
326
- expect(permit.type).toBe('self');
327
- expect(permit.hash).not.toBe(expiredPermit.hash);
328
-
329
- // The fresh permit should now be active
330
- const activeAfter = await permits.getActivePermit(chainId, bobAddress);
331
- expect(activeAfter?.hash).toBe(permit.hash);
332
- });
333
-
334
- it('should use default options when none provided', async () => {
335
- const permit = await permits.getOrCreateSelfPermit(publicClient, bobWalletClient, chainId, bobAddress);
336
-
337
- expect(permit).toBeDefined();
338
- expect(permit.type).toBe('self');
339
- expect(permit.issuer).toBe(bobAddress);
340
- expect(permit.name).toBe('Autogenerated Self Permit');
341
- });
342
-
343
- it('should use default chainId and account when not provided', async () => {
344
- const permit = await permits.getOrCreateSelfPermit(publicClient, bobWalletClient, undefined, undefined, {
345
- issuer: bobAddress,
346
- name: 'Test Permit',
347
- });
348
-
349
- expect(permit).toBeDefined();
350
- expect(permit.issuer).toBe(bobAddress);
351
-
352
- // Verify it was stored with the chain's actual chainId
353
- const activePermit = await permits.getActivePermit(chainId, bobAddress);
354
- expect(activePermit?.name).toBe('Test Permit');
355
- });
356
- });
357
-
358
- describe('getOrCreateSharingPermit', () => {
359
- it('should create a new sharing permit when none exists', async () => {
360
- const permit = await permits.getOrCreateSharingPermit(
361
- publicClient,
362
- bobWalletClient,
363
- {
364
- issuer: bobAddress,
365
- recipient: aliceAddress,
366
- name: 'New Sharing Permit',
367
- },
368
- chainId,
369
- bobAddress
370
- );
371
-
372
- expect(permit).toBeDefined();
373
- expect(permit.name).toBe('New Sharing Permit');
374
- expect(permit.type).toBe('sharing');
375
- expect(permit.issuer).toBe(bobAddress);
376
- expect(permit.recipient).toBe(aliceAddress);
377
- expect(permit.issuerSignature).toBeDefined();
378
-
379
- // Verify it was stored and set as active
380
- const activePermit = await permits.getActivePermit(chainId, bobAddress);
381
- expect(activePermit?.name).toBe('New Sharing Permit');
382
- });
383
-
384
- it('should return existing sharing permit when one exists', async () => {
385
- // Create an initial sharing permit
386
- const firstPermit = await permits.createSharing(
387
- {
388
- name: 'First Sharing Permit',
389
- issuer: bobAddress,
390
- recipient: aliceAddress,
391
- },
392
- publicClient,
393
- bobWalletClient
394
- );
395
-
396
- // Call getOrCreateSharingPermit - should return existing
397
- const permit = await permits.getOrCreateSharingPermit(
398
- publicClient,
399
- bobWalletClient,
400
- {
401
- issuer: bobAddress,
402
- recipient: aliceAddress,
403
- name: 'Should Not Create This',
404
- },
405
- chainId,
406
- bobAddress
407
- );
408
-
409
- expect(permit.name).toBe('First Sharing Permit');
410
- expect(permit.hash).toBe(firstPermit.hash);
411
-
412
- // Verify no new permit was created
413
- const allPermits = await permits.getPermits(chainId, bobAddress);
414
- expect(Object.keys(allPermits).length).toBe(1);
415
- });
416
-
417
- it('should create new sharing permit when active permit is self type', async () => {
418
- // Create a self permit first
419
- await permits.createSelf({ name: 'Self Permit', issuer: bobAddress }, publicClient, bobWalletClient);
420
-
421
- // Call getOrCreateSharingPermit - should create new since active is self type
422
- const permit = await permits.getOrCreateSharingPermit(
423
- publicClient,
424
- bobWalletClient,
425
- {
426
- issuer: bobAddress,
427
- recipient: aliceAddress,
428
- name: 'New Sharing Permit',
429
- },
430
- chainId,
431
- bobAddress
432
- );
433
-
434
- expect(permit.name).toBe('New Sharing Permit');
435
- expect(permit.type).toBe('sharing');
436
-
437
- // Verify two permits exist now
438
- const allPermits = await permits.getPermits(chainId, bobAddress);
439
- expect(Object.keys(allPermits).length).toBe(2);
440
- });
441
-
442
- it('should create a new sharing permit when active permit is expired', async () => {
443
- // Create an expired sharing permit (expiration in the past)
444
- const expiredPermit = await permits.createSharing(
445
- {
446
- name: 'Expired Sharing Permit',
447
- issuer: bobAddress,
448
- recipient: aliceAddress,
449
- expiration: Math.floor(Date.now() / 1000) - 3600,
450
- },
451
- publicClient,
452
- bobWalletClient
453
- );
454
-
455
- // getOrCreateSharingPermit should treat the expired permit as missing and create a fresh one
456
- const permit = await permits.getOrCreateSharingPermit(
457
- publicClient,
458
- bobWalletClient,
459
- {
460
- issuer: bobAddress,
461
- recipient: aliceAddress,
462
- name: 'Fresh Sharing Permit',
463
- },
464
- chainId,
465
- bobAddress
466
- );
467
-
468
- expect(permit.name).toBe('Fresh Sharing Permit');
469
- expect(permit.type).toBe('sharing');
470
- expect(permit.hash).not.toBe(expiredPermit.hash);
471
-
472
- // The fresh permit should now be active
473
- const activeAfter = await permits.getActivePermit(chainId, bobAddress);
474
- expect(activeAfter?.hash).toBe(permit.hash);
475
- });
476
-
477
- it('should use default chainId and account when not provided', async () => {
478
- const permit = await permits.getOrCreateSharingPermit(
479
- publicClient,
480
- bobWalletClient,
481
- {
482
- issuer: bobAddress,
483
- recipient: aliceAddress,
484
- name: 'Test Sharing Permit',
485
- },
486
- undefined,
487
- undefined
488
- );
489
-
490
- expect(permit).toBeDefined();
491
- expect(permit.issuer).toBe(bobAddress);
492
- expect(permit.recipient).toBe(aliceAddress);
493
-
494
- // Verify it was stored with the chain's actual chainId
495
- const activePermit = await permits.getActivePermit(chainId, bobAddress);
496
- expect(activePermit?.name).toBe('Test Sharing Permit');
497
- });
498
- });
499
-
500
- describe('Export', () => {
501
- it('should export self permit data without sensitive fields', async () => {
502
- const permit = await permits.createSelf(
503
- { name: 'Test Self Permit', issuer: bobAddress },
504
- publicClient,
505
- bobWalletClient
506
- );
507
-
508
- const exported = permits.export(permit);
509
- const parsed = JSON.parse(exported);
510
-
511
- expect(parsed.name).toBe('Test Self Permit');
512
- expect(parsed.issuer).toBe(bobAddress);
513
- expect(parsed).not.toHaveProperty('sealingPair');
514
- expect(parsed).not.toHaveProperty('issuerSignature');
515
- });
516
-
517
- it('should export sharing permit data with recipient and issuerSignature', async () => {
518
- const permit = await permits.createSharing(
519
- {
520
- name: 'Test Sharing Permit',
521
- issuer: bobAddress,
522
- recipient: aliceAddress,
523
- },
524
- publicClient,
525
- bobWalletClient
526
- );
527
-
528
- const exported = permits.export(permit);
529
- const parsed = JSON.parse(exported);
530
-
531
- expect(parsed.name).toBe('Test Sharing Permit');
532
- expect(parsed.type).toBe('sharing');
533
- expect(parsed.issuer).toBe(bobAddress);
534
- expect(parsed.recipient).toBe(aliceAddress);
535
- expect(parsed.issuerSignature).toBeDefined();
536
- expect(parsed.issuerSignature).not.toBe('0x');
537
- expect(parsed).not.toHaveProperty('sealingPair');
538
- });
539
- });
540
-
541
- describe('getOrCreate - Multiple Types Scenarios', () => {
542
- it('should handle switching between self and sharing permits', async () => {
543
- // Create self permit
544
- const selfPermit = await permits.getOrCreateSelfPermit(publicClient, bobWalletClient, chainId, bobAddress, {
545
- issuer: bobAddress,
546
- name: 'Self Permit',
547
- });
548
- expect(selfPermit.type).toBe('self');
549
-
550
- // Create sharing permit (should create new one)
551
- const sharingPermit = await permits.getOrCreateSharingPermit(
552
- publicClient,
553
- bobWalletClient,
554
- {
555
- issuer: bobAddress,
556
- recipient: aliceAddress,
557
- name: 'Sharing Permit',
558
- },
559
- chainId,
560
- bobAddress
561
- );
562
- expect(sharingPermit.type).toBe('sharing');
563
-
564
- // Both should exist
565
- const allPermits = await permits.getPermits(chainId, bobAddress);
566
- expect(Object.keys(allPermits).length).toBe(2);
567
-
568
- // Active permit should be the sharing one
569
- const activePermit = await permits.getActivePermit(chainId, bobAddress);
570
- expect(activePermit?.type).toBe('sharing');
571
- expect(activePermit?.name).toBe('Sharing Permit');
572
- });
573
-
574
- it('should correctly handle sequential getOrCreate calls', async () => {
575
- // First call - creates new
576
- const permit1 = await permits.getOrCreateSelfPermit(publicClient, bobWalletClient, chainId, bobAddress, {
577
- issuer: bobAddress,
578
- name: 'Permit 1',
579
- });
580
-
581
- // Second call - returns existing
582
- const permit2 = await permits.getOrCreateSelfPermit(publicClient, bobWalletClient, chainId, bobAddress, {
583
- issuer: bobAddress,
584
- name: 'Permit 2',
585
- });
586
-
587
- // Should be the same permit
588
- expect(permit1.hash).toBe(permit2.hash);
589
- expect(permit2.name).toBe('Permit 1'); // Original name
590
-
591
- // Only one permit should exist
592
- const allPermits = await permits.getPermits(chainId, bobAddress);
593
- expect(Object.keys(allPermits).length).toBe(1);
594
- });
595
- });
596
- });