@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,4 +1,5 @@
1
- import { arbSepolia as cofheArbSepolia } from '@/chains';
1
+ import { STAGING_TESTS, stagingViemChain } from '../../core/test/stagingRedirect';
2
+ import { arbSepolia as cofheArbSepolia, stagingCofhe } from '@/chains';
2
3
  import { Encryptable } from '@/core';
3
4
 
4
5
  import { describe, it, expect, beforeAll } from 'vitest';
@@ -10,33 +11,38 @@ import { createCofheClient, createCofheConfig } from '../index.js';
10
11
 
11
12
  const TEST_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
12
13
 
14
+ const testViemChain = STAGING_TESTS ? stagingViemChain : viemArbitrumSepolia;
15
+ const testCofheChain = STAGING_TESTS ? stagingCofhe : cofheArbSepolia;
16
+
13
17
  describe('@cofhe/sdk/web - Worker vs Main Thread Output Validation', () => {
14
18
  let publicClient: PublicClient;
15
19
  let walletClient: WalletClient;
20
+ let consumingContract: `0x${string}`;
16
21
 
17
22
  beforeAll(() => {
18
23
  publicClient = createPublicClient({
19
- chain: viemArbitrumSepolia,
24
+ chain: testViemChain,
20
25
  transport: http(),
21
26
  });
22
27
 
23
28
  const account = privateKeyToAccount(TEST_PRIVATE_KEY);
24
29
  walletClient = createWalletClient({
25
- chain: viemArbitrumSepolia,
30
+ chain: testViemChain,
26
31
  transport: http(),
27
32
  account,
28
33
  });
34
+ consumingContract = account.address;
29
35
  });
30
36
 
31
37
  it('should produce consistent output format regardless of worker usage', async () => {
32
38
  // Create two clients - one with workers, one without
33
39
  const configWithWorker = createCofheConfig({
34
- supportedChains: [cofheArbSepolia],
40
+ supportedChains: [testCofheChain],
35
41
  useWorkers: true,
36
42
  });
37
43
 
38
44
  const configWithoutWorker = createCofheConfig({
39
- supportedChains: [cofheArbSepolia],
45
+ supportedChains: [testCofheChain],
40
46
  useWorkers: false,
41
47
  });
42
48
 
@@ -49,34 +55,29 @@ describe('@cofhe/sdk/web - Worker vs Main Thread Output Validation', () => {
49
55
  const value = Encryptable.uint128(12345n);
50
56
 
51
57
  const [resultWithWorker, resultWithoutWorker] = await Promise.all([
52
- clientWithWorker.encryptInputs([value]).execute(),
53
- clientWithoutWorker.encryptInputs([value]).execute(),
58
+ clientWithWorker.encryptInputs([value]).setConsumingContract(consumingContract).execute(),
59
+ clientWithoutWorker.encryptInputs([value]).setConsumingContract(consumingContract).execute(),
54
60
  ]);
55
61
 
56
62
  // Both should succeed
57
63
  expect(resultWithWorker).toBeDefined();
58
64
  expect(resultWithoutWorker).toBeDefined();
59
65
 
60
- // Both should have same structure (but different encrypted values)
61
- const withWorker = resultWithWorker[0];
62
- const withoutWorker = resultWithoutWorker[0];
66
+ // Both should have same structure (but different encrypted values):
67
+ // [hash, signature] - one hash per input, followed by the shared batch signature.
68
+ expect(resultWithWorker.length).toBe(2);
69
+ expect(resultWithoutWorker.length).toBe(2);
63
70
 
64
- expect(withWorker).toHaveProperty('ctHash');
65
- expect(withWorker).toHaveProperty('signature');
66
- expect(withWorker).toHaveProperty('utype');
67
- expect(withWorker).toHaveProperty('securityZone');
68
- expect(withoutWorker).toHaveProperty('ctHash');
69
- expect(withoutWorker).toHaveProperty('signature');
70
- expect(withoutWorker).toHaveProperty('utype');
71
- expect(withoutWorker).toHaveProperty('securityZone');
71
+ const [hashWithWorker, signatureWithWorker] = resultWithWorker;
72
+ const [hashWithoutWorker, signatureWithoutWorker] = resultWithoutWorker;
72
73
 
73
74
  // Format should be identical
74
- expect(typeof withWorker.ctHash).toBe('bigint');
75
- expect(typeof withoutWorker.ctHash).toBe('bigint');
76
- expect(withWorker.signature.startsWith('0x')).toBe(true);
77
- expect(withoutWorker.signature.startsWith('0x')).toBe(true);
78
- expect(typeof withWorker.utype).toBe('number');
79
- expect(typeof withoutWorker.utype).toBe('number');
75
+ expect(typeof hashWithWorker).toBe('string');
76
+ expect(typeof hashWithoutWorker).toBe('string');
77
+ expect(hashWithWorker.startsWith('0x')).toBe(true);
78
+ expect(hashWithoutWorker.startsWith('0x')).toBe(true);
79
+ expect(signatureWithWorker.startsWith('0x')).toBe(true);
80
+ expect(signatureWithoutWorker.startsWith('0x')).toBe(true);
80
81
 
81
82
  // Note: The actual encrypted values will differ because of randomness
82
83
  // in the encryption process, so we don't check equality
@@ -1,67 +0,0 @@
1
- /* eslint-disable no-redeclare */
2
- import {
3
- type EncryptableItem,
4
- isEncryptableItem,
5
- type EncryptedItemInput,
6
- type EncryptedItemInputs,
7
- } from '../types.js';
8
-
9
- export function encryptExtract<T>(item: T): EncryptableItem[];
10
- export function encryptExtract<T extends any[]>(item: [...T]): EncryptableItem[];
11
- export function encryptExtract<T>(item: T) {
12
- if (isEncryptableItem(item)) {
13
- return item;
14
- }
15
-
16
- // Object | Array
17
- if (typeof item === 'object' && item !== null) {
18
- if (Array.isArray(item)) {
19
- // Array - recurse
20
- return item.flatMap((nestedItem) => encryptExtract(nestedItem));
21
- } else {
22
- // Object - recurse
23
- return Object.values(item).flatMap((value) => encryptExtract(value));
24
- }
25
- }
26
-
27
- return [];
28
- }
29
-
30
- export function encryptReplace<T>(
31
- item: T,
32
- encryptedItems: EncryptedItemInput[]
33
- ): [EncryptedItemInputs<T>, EncryptedItemInput[]];
34
- export function encryptReplace<T extends any[]>(
35
- item: [...T],
36
- encryptedItems: EncryptedItemInput[]
37
- ): [...EncryptedItemInputs<T>, EncryptedItemInput[]];
38
- export function encryptReplace<T>(item: T, encryptedItems: EncryptedItemInput[]) {
39
- if (isEncryptableItem(item)) {
40
- return [encryptedItems[0], encryptedItems.slice(1)];
41
- }
42
-
43
- // Object | Array
44
- if (typeof item === 'object' && item !== null) {
45
- if (Array.isArray(item)) {
46
- // Array - recurse
47
- return item.reduce<[any[], EncryptedItemInput[]]>(
48
- ([acc, remaining], item) => {
49
- const [newItem, newRemaining] = encryptReplace(item, remaining);
50
- return [[...acc, newItem], newRemaining];
51
- },
52
- [[], encryptedItems]
53
- );
54
- } else {
55
- // Object - recurse
56
- return Object.entries(item).reduce<[Record<string, any>, EncryptedItemInput[]]>(
57
- ([acc, remaining], [key, value]) => {
58
- const [newValue, newRemaining] = encryptReplace(value, remaining);
59
- return [{ ...acc, [key]: newValue }, newRemaining];
60
- },
61
- [{}, encryptedItems]
62
- );
63
- }
64
- }
65
-
66
- return [item, encryptedItems];
67
- }
package/core/permits.ts DELETED
@@ -1,216 +0,0 @@
1
- import {
2
- type ImportSharedPermitOptions,
3
- PermitUtils,
4
- type CreateSelfPermitOptions,
5
- type CreateSharingPermitOptions,
6
- type Permit,
7
- permitStore,
8
- type SerializedPermit,
9
- type SelfPermit,
10
- type RecipientPermit,
11
- type SharingPermit,
12
- type PermitHashFields,
13
- } from '@/permits';
14
-
15
- import { type PublicClient, type WalletClient } from 'viem';
16
-
17
- // HELPERS
18
-
19
- // Helper function to store permit as active permit
20
- const storeActivePermit = async (permit: Permit, publicClient: any, walletClient: any) => {
21
- const chainId = await publicClient.getChainId();
22
- const account = walletClient.account!.address;
23
-
24
- permitStore.setPermit(chainId, account, permit);
25
- permitStore.setActivePermitHash(chainId, account, permit.hash);
26
- };
27
-
28
- // Generic function to handle permit creation with error handling
29
- const createPermitWithSign = async <T, TPermit extends Permit>(
30
- options: T,
31
- publicClient: PublicClient,
32
- walletClient: WalletClient,
33
- permitMethod: (options: T, publicClient: PublicClient, walletClient: WalletClient) => Promise<TPermit>
34
- ): Promise<TPermit> => {
35
- const permit = await permitMethod(options, publicClient, walletClient);
36
- await storeActivePermit(permit, publicClient, walletClient);
37
- return permit;
38
- };
39
-
40
- // CREATE
41
-
42
- /**
43
- * Create a permit usable by the connected user
44
- * Stores the permit and selects it as the active permit
45
- * @param options - The options for creating a self permit
46
- * @returns The created permit or error
47
- */
48
- const createSelf = async (
49
- options: CreateSelfPermitOptions,
50
- publicClient: PublicClient,
51
- walletClient: WalletClient
52
- ): Promise<SelfPermit> => {
53
- return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSelfAndSign);
54
- };
55
-
56
- const createSharing = async (
57
- options: CreateSharingPermitOptions,
58
- publicClient: PublicClient,
59
- walletClient: WalletClient
60
- ): Promise<SharingPermit> => {
61
- return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSharingAndSign);
62
- };
63
-
64
- const importShared = async (
65
- options: ImportSharedPermitOptions | string,
66
- publicClient: PublicClient,
67
- walletClient: WalletClient
68
- ): Promise<RecipientPermit> => {
69
- return createPermitWithSign(options, publicClient, walletClient, PermitUtils.importSharedAndSign);
70
- };
71
-
72
- // PERMIT UTILS
73
-
74
- const getHash = (permit: PermitHashFields) => {
75
- return PermitUtils.getHash(permit);
76
- };
77
-
78
- const exportShared = (permit: Permit) => {
79
- return PermitUtils.export(permit);
80
- };
81
-
82
- const serialize = (permit: Permit) => {
83
- return PermitUtils.serialize(permit);
84
- };
85
-
86
- const deserialize = (serialized: SerializedPermit) => {
87
- return PermitUtils.deserialize(serialized);
88
- };
89
-
90
- // GET
91
-
92
- const getPermit = (chainId: number, account: string, hash: string): Permit | undefined => {
93
- return permitStore.getPermit(chainId, account, hash);
94
- };
95
-
96
- const getPermits = (chainId: number, account: string): Record<string, Permit> => {
97
- return permitStore.getPermits(chainId, account);
98
- };
99
-
100
- const getActivePermit = (chainId: number, account: string): Permit | undefined => {
101
- return permitStore.getActivePermit(chainId, account);
102
- };
103
-
104
- const getActivePermitHash = (chainId: number, account: string): string | undefined => {
105
- return permitStore.getActivePermitHash(chainId, account);
106
- };
107
-
108
- const selectActivePermit = (chainId: number, account: string, hash: string): void => {
109
- permitStore.setActivePermitHash(chainId, account, hash);
110
- };
111
-
112
- // GET OR CREATE
113
-
114
- /**
115
- * Get the active self permit if a valid one exists, otherwise create a new one.
116
- *
117
- * An active permit is reused only when it is a self permit and is still valid
118
- * (signed and not expired). An expired or otherwise invalid active permit is
119
- * treated as missing and a fresh permit is created.
120
- *
121
- * @param publicClient - The public client
122
- * @param walletClient - The wallet client
123
- * @param chainId - Optional chain ID (will use publicClient if not provided)
124
- * @param account - Optional account (will use walletClient if not provided)
125
- * @param options - The options for creating a self permit
126
- * @returns The existing valid permit or a newly created one
127
- */
128
- const getOrCreateSelfPermit = async (
129
- publicClient: PublicClient,
130
- walletClient: WalletClient,
131
- chainId?: number,
132
- account?: string,
133
- options?: CreateSelfPermitOptions
134
- ): Promise<Permit> => {
135
- const _chainId = chainId ?? (await publicClient.getChainId());
136
- const _account = account ?? walletClient.account!.address;
137
-
138
- // Try to get active permit first
139
- const activePermit = await getActivePermit(_chainId, _account);
140
-
141
- if (activePermit && activePermit.type === 'self' && PermitUtils.isValid(activePermit).valid) {
142
- return activePermit;
143
- }
144
-
145
- // No active permit, wrong type, or expired/invalid - create new one
146
- return createSelf(options ?? { issuer: _account, name: 'Autogenerated Self Permit' }, publicClient, walletClient);
147
- };
148
-
149
- /**
150
- * Get the active sharing permit if a valid one exists, otherwise create a new one.
151
- *
152
- * An active permit is reused only when it is a sharing permit and is still valid
153
- * (signed and not expired). An expired or otherwise invalid active permit is
154
- * treated as missing and a fresh permit is created.
155
- *
156
- * @param publicClient - The public client
157
- * @param walletClient - The wallet client
158
- * @param options - The options for creating a sharing permit (required)
159
- * @param chainId - Optional chain ID (will use publicClient if not provided)
160
- * @param account - Optional account (will use walletClient if not provided)
161
- * @returns The existing valid permit or a newly created one
162
- */
163
- const getOrCreateSharingPermit = async (
164
- publicClient: PublicClient,
165
- walletClient: WalletClient,
166
- options: CreateSharingPermitOptions,
167
- chainId?: number,
168
- account?: string
169
- ): Promise<Permit> => {
170
- const _chainId = chainId ?? (await publicClient.getChainId());
171
- const _account = account ?? walletClient.account!.address;
172
-
173
- // Try to get active permit first
174
- const activePermit = await getActivePermit(_chainId, _account);
175
-
176
- if (activePermit && activePermit.type === 'sharing' && PermitUtils.isValid(activePermit).valid) {
177
- return activePermit;
178
- }
179
-
180
- return createSharing(options, publicClient, walletClient);
181
- };
182
-
183
- // REMOVE
184
-
185
- const removePermit = async (chainId: number, account: string, hash: string): Promise<void> =>
186
- permitStore.removePermit(chainId, account, hash);
187
-
188
- const removeActivePermit = async (chainId: number, account: string): Promise<void> =>
189
- permitStore.removeActivePermitHash(chainId, account);
190
-
191
- // EXPORT
192
-
193
- export const permits = {
194
- getSnapshot: permitStore.store.getState,
195
- subscribe: permitStore.store.subscribe,
196
-
197
- createSelf,
198
- createSharing,
199
- importShared,
200
-
201
- getOrCreateSelfPermit,
202
- getOrCreateSharingPermit,
203
-
204
- getHash,
205
- export: exportShared,
206
- serialize,
207
- deserialize,
208
-
209
- getPermit,
210
- getPermits,
211
- getActivePermit,
212
- getActivePermitHash,
213
- removePermit,
214
- selectActivePermit,
215
- removeActivePermit,
216
- };