@cofhe/sdk 0.2.0 → 0.2.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 (57) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/chains/defineChain.ts +2 -2
  3. package/chains/types.ts +3 -3
  4. package/core/client.test.ts +111 -0
  5. package/core/client.ts +22 -2
  6. package/core/clientTypes.ts +7 -1
  7. package/core/config.test.ts +8 -0
  8. package/core/config.ts +10 -4
  9. package/core/consts.ts +18 -0
  10. package/core/decrypt/cofheMocksSealOutput.ts +2 -4
  11. package/core/encrypt/cofheMocksZkVerifySign.ts +4 -11
  12. package/core/index.ts +9 -1
  13. package/core/permits.test.ts +5 -6
  14. package/core/permits.ts +5 -4
  15. package/dist/chains.cjs +4 -7
  16. package/dist/chains.d.cts +12 -12
  17. package/dist/chains.d.ts +12 -12
  18. package/dist/chains.js +1 -1
  19. package/dist/{chunk-WGCRJCBR.js → chunk-I5WFEYXX.js} +33 -19
  20. package/dist/{chunk-UGBVZNRT.js → chunk-R3B5TMVX.js} +308 -189
  21. package/dist/{chunk-WEAZ25JO.js → chunk-TBLR7NNE.js} +4 -7
  22. package/dist/{clientTypes-Es7fyi65.d.ts → clientTypes-RqkgkV2i.d.ts} +34 -93
  23. package/dist/{clientTypes-5_1nwtUe.d.cts → clientTypes-e4filDzK.d.cts} +34 -93
  24. package/dist/core.cjs +343 -208
  25. package/dist/core.d.cts +17 -6
  26. package/dist/core.d.ts +17 -6
  27. package/dist/core.js +3 -3
  28. package/dist/node.cjs +337 -208
  29. package/dist/node.d.cts +3 -3
  30. package/dist/node.d.ts +3 -3
  31. package/dist/node.js +3 -3
  32. package/dist/{permit-fUSe6KKq.d.cts → permit-MZ502UBl.d.cts} +30 -33
  33. package/dist/{permit-fUSe6KKq.d.ts → permit-MZ502UBl.d.ts} +30 -33
  34. package/dist/permits.cjs +305 -187
  35. package/dist/permits.d.cts +111 -812
  36. package/dist/permits.d.ts +111 -812
  37. package/dist/permits.js +1 -1
  38. package/dist/types-YiAC4gig.d.cts +33 -0
  39. package/dist/types-YiAC4gig.d.ts +33 -0
  40. package/dist/web.cjs +337 -208
  41. package/dist/web.d.cts +3 -3
  42. package/dist/web.d.ts +3 -3
  43. package/dist/web.js +3 -3
  44. package/package.json +3 -3
  45. package/permits/localstorage.test.ts +9 -13
  46. package/permits/onchain-utils.ts +221 -0
  47. package/permits/permit.test.ts +51 -5
  48. package/permits/permit.ts +28 -74
  49. package/permits/store.test.ts +10 -50
  50. package/permits/store.ts +4 -14
  51. package/permits/test-utils.ts +10 -2
  52. package/permits/types.ts +22 -9
  53. package/permits/utils.ts +0 -4
  54. package/permits/validation.test.ts +29 -32
  55. package/permits/validation.ts +112 -194
  56. package/dist/types-KImPrEIe.d.cts +0 -48
  57. package/dist/types-KImPrEIe.d.ts +0 -48
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @cofhe/sdk Changelog
2
2
 
3
+ ## 0.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 409bfdf: Add `hash` field to permits, calculated at permit creation time. Replaces `PermitUtils.getHash(permit)` with `permit.hash`.
8
+ - ac47e2f: Add `PermitUtils.checkValidityOnChain` to validate permits against the on-chain deployed ACL (source of truth).
9
+ - 8af1b70: Updated to Zod 4 for improved performance and type safety. Includes internal changes to validation schemas and error handling that should not affect external API usage.
10
+
3
11
  ## 0.2.0
4
12
 
5
13
  ### Minor Changes
@@ -1,4 +1,5 @@
1
1
  import { CofheChainSchema, type CofheChain } from './types.js';
2
+ import { z } from 'zod';
2
3
 
3
4
  /**
4
5
  * Defines and validates a CofheChain configuration
@@ -10,8 +11,7 @@ export function defineChain(chainConfig: CofheChain): CofheChain {
10
11
  const result = CofheChainSchema.safeParse(chainConfig);
11
12
 
12
13
  if (!result.success) {
13
- const errorMessages = result.error.errors.map((err) => `${err.path.join('.')}: ${err.message}`);
14
- throw new Error(`Invalid chain configuration: ${errorMessages.join(', ')}`);
14
+ throw new Error(`Invalid chain configuration: ${z.prettifyError(result.error)}`, { cause: result.error });
15
15
  }
16
16
 
17
17
  return result.data;
package/chains/types.ts CHANGED
@@ -16,11 +16,11 @@ export const CofheChainSchema = z.object({
16
16
  /** Network identifier */
17
17
  network: z.string().min(1),
18
18
  /** coFhe service URL */
19
- coFheUrl: z.string().url(),
19
+ coFheUrl: z.url(),
20
20
  /** Verifier service URL */
21
- verifierUrl: z.string().url(),
21
+ verifierUrl: z.url(),
22
22
  /** Threshold network service URL */
23
- thresholdNetworkUrl: z.string().url(),
23
+ thresholdNetworkUrl: z.url(),
24
24
  /** Environment type */
25
25
  environment: EnvironmentSchema,
26
26
  });
@@ -176,6 +176,97 @@ describe('createCofhesdkClientBase', () => {
176
176
  await promise1;
177
177
  });
178
178
 
179
+ it('should ensure the latest connection attempt wins when connecting twice', async () => {
180
+ let resolveChainId1: (value: number) => void;
181
+ let resolveAddresses1: (value: string[]) => void;
182
+ let resolveChainId2: (value: number) => void;
183
+ let resolveAddresses2: (value: string[]) => void;
184
+
185
+ const chainIdPromise1 = new Promise<number>((resolve) => {
186
+ resolveChainId1 = resolve;
187
+ });
188
+ const addressesPromise1 = new Promise<string[]>((resolve) => {
189
+ resolveAddresses1 = resolve;
190
+ });
191
+
192
+ const chainIdPromise2 = new Promise<number>((resolve) => {
193
+ resolveChainId2 = resolve;
194
+ });
195
+ const addressesPromise2 = new Promise<string[]>((resolve) => {
196
+ resolveAddresses2 = resolve;
197
+ });
198
+
199
+ const publicClient1 = createMockPublicClient() as any;
200
+ publicClient1.getChainId = vi.fn().mockReturnValue(chainIdPromise1);
201
+ const walletClient1 = createMockWalletClient() as any;
202
+ walletClient1.getAddresses = vi.fn().mockReturnValue(addressesPromise1);
203
+
204
+ const publicClient2 = createMockPublicClient() as any;
205
+ publicClient2.getChainId = vi.fn().mockReturnValue(chainIdPromise2);
206
+ const walletClient2 = createMockWalletClient() as any;
207
+ walletClient2.getAddresses = vi.fn().mockReturnValue(addressesPromise2);
208
+
209
+ const promise1 = client.connect(publicClient1, walletClient1);
210
+ expect(client.connecting).toBe(true);
211
+
212
+ const promise2 = client.connect(publicClient2, walletClient2);
213
+
214
+ // Resolve the second connect first
215
+ resolveChainId2!(222);
216
+ resolveAddresses2!(['0x2222222222222222222222222222222222222222']);
217
+ await promise2;
218
+
219
+ expect(client.connected).toBe(true);
220
+ expect(client.connecting).toBe(false);
221
+ expect(client.getSnapshot().chainId).toBe(222);
222
+ expect(client.getSnapshot().account).toBe('0x2222222222222222222222222222222222222222');
223
+ expect(client.getSnapshot().publicClient).toBe(publicClient2);
224
+ expect(client.getSnapshot().walletClient).toBe(walletClient2);
225
+
226
+ // Now resolve the first connect; it must not overwrite the latest state.
227
+ resolveChainId1!(111);
228
+ resolveAddresses1!(['0x1111111111111111111111111111111111111111']);
229
+ await promise1;
230
+
231
+ expect(client.getSnapshot().chainId).toBe(222);
232
+ expect(client.getSnapshot().account).toBe('0x2222222222222222222222222222222222222222');
233
+ expect(client.getSnapshot().publicClient).toBe(publicClient2);
234
+ expect(client.getSnapshot().walletClient).toBe(walletClient2);
235
+ });
236
+
237
+ it('should allow disconnect while connecting and never end up connected afterwards', async () => {
238
+ let resolveChainId: (value: number) => void;
239
+ let resolveAddresses: (value: string[]) => void;
240
+
241
+ const chainIdPromise = new Promise<number>((resolve) => {
242
+ resolveChainId = resolve;
243
+ });
244
+ const addressesPromise = new Promise<string[]>((resolve) => {
245
+ resolveAddresses = resolve;
246
+ });
247
+
248
+ const publicClient = createMockPublicClient() as any;
249
+ publicClient.getChainId = vi.fn().mockReturnValue(chainIdPromise);
250
+
251
+ const walletClient = createMockWalletClient() as any;
252
+ walletClient.getAddresses = vi.fn().mockReturnValue(addressesPromise);
253
+
254
+ const connectPromise = client.connect(publicClient, walletClient);
255
+ expect(client.connecting).toBe(true);
256
+
257
+ client.disconnect();
258
+ expect(client.connected).toBe(false);
259
+ expect(client.connecting).toBe(false);
260
+
261
+ resolveChainId!(11155111);
262
+ resolveAddresses!(['0x1234567890123456789012345678901234567890']);
263
+
264
+ await connectPromise;
265
+
266
+ expect(client.connected).toBe(false);
267
+ expect(client.connecting).toBe(false);
268
+ });
269
+
179
270
  it('should handle publicClient.getChainId throwing an error', async () => {
180
271
  const publicClient = createMockPublicClient();
181
272
  const getChainIdError = new Error('Network error');
@@ -264,6 +355,26 @@ describe('createCofhesdkClientBase', () => {
264
355
  expect((error as CofhesdkError).cause).toBe(getChainIdError);
265
356
  }
266
357
  });
358
+
359
+ it('should disconnect and clear connection state', async () => {
360
+ const publicClient = createMockPublicClient(11155111);
361
+ const walletClient = createMockWalletClient(['0xabcd']);
362
+
363
+ await client.connect(publicClient, walletClient);
364
+ expect(client.connected).toBe(true);
365
+
366
+ client.disconnect();
367
+
368
+ expect(client.connected).toBe(false);
369
+ expect(client.connecting).toBe(false);
370
+
371
+ const snapshot = client.getSnapshot();
372
+ expect(snapshot.chainId).toBe(undefined);
373
+ expect(snapshot.account).toBe(undefined);
374
+ expect(snapshot.publicClient).toBe(undefined);
375
+ expect(snapshot.walletClient).toBe(undefined);
376
+ expect(snapshot.connectError).toBe(undefined);
377
+ });
267
378
  });
268
379
 
269
380
  describe('encryptInputs', () => {
package/core/client.ts CHANGED
@@ -42,6 +42,10 @@ export function createCofhesdkClientBase<TConfig extends CofhesdkConfig>(
42
42
 
43
43
  const connectStore = createStore<CofhesdkClientConnectionState>(() => InitialConnectStore);
44
44
 
45
+ // Minimal cancellation mechanism: incremented on each connect/disconnect.
46
+ // If a connect finishes after a disconnect, it must not overwrite the disconnected state.
47
+ let connectAttemptId = 0;
48
+
45
49
  // Helper to update state
46
50
  const updateConnectState = (partial: Partial<CofhesdkClientConnectionState>) => {
47
51
  connectStore.setState((state) => ({ ...state, ...partial }));
@@ -76,6 +80,9 @@ export function createCofhesdkClientBase<TConfig extends CofhesdkConfig>(
76
80
  // Exit if already connected and clients are the same
77
81
  if (state.connected && state.publicClient === publicClient && state.walletClient === walletClient) return;
78
82
 
83
+ connectAttemptId += 1;
84
+ const localAttemptId = connectAttemptId;
85
+
79
86
  // Set connecting state
80
87
  updateConnectState({
81
88
  ...InitialConnectStore,
@@ -86,6 +93,10 @@ export function createCofhesdkClientBase<TConfig extends CofhesdkConfig>(
86
93
  try {
87
94
  const chainId = await getPublicClientChainID(publicClient);
88
95
  const account = await getWalletClientAccount(walletClient);
96
+
97
+ // If a disconnect (or a newer connect) happened while awaiting, ignore this completion.
98
+ if (localAttemptId !== connectAttemptId) return;
99
+
89
100
  updateConnectState({
90
101
  connected: true,
91
102
  connecting: false,
@@ -96,6 +107,9 @@ export function createCofhesdkClientBase<TConfig extends CofhesdkConfig>(
96
107
  walletClient,
97
108
  });
98
109
  } catch (e) {
110
+ // Ignore stale errors too.
111
+ if (localAttemptId !== connectAttemptId) return;
112
+
99
113
  updateConnectState({
100
114
  ...InitialConnectStore,
101
115
  connectError: e,
@@ -104,6 +118,11 @@ export function createCofhesdkClientBase<TConfig extends CofhesdkConfig>(
104
118
  }
105
119
  }
106
120
 
121
+ function disconnect() {
122
+ connectAttemptId += 1;
123
+ updateConnectState({ ...InitialConnectStore });
124
+ }
125
+
107
126
  // CLIENT OPERATIONS
108
127
 
109
128
  function encryptInputs<T extends EncryptableItem[]>(inputs: [...T]): EncryptInputsBuilder<[...T]> {
@@ -245,9 +264,9 @@ export function createCofhesdkClientBase<TConfig extends CofhesdkConfig>(
245
264
  return permits.selectActivePermit(_chainId, _account, hash);
246
265
  },
247
266
 
248
- removePermit: async (hash: string, chainId?: number, account?: string, force?: boolean) => {
267
+ removePermit: async (hash: string, chainId?: number, account?: string) => {
249
268
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
250
- return permits.removePermit(_chainId, _account, hash, force);
269
+ return permits.removePermit(_chainId, _account, hash);
251
270
  },
252
271
 
253
272
  removeActivePermit: async (chainId?: number, account?: string) => {
@@ -278,6 +297,7 @@ export function createCofhesdkClientBase<TConfig extends CofhesdkConfig>(
278
297
  config: opts.config,
279
298
 
280
299
  connect,
300
+ disconnect,
281
301
  encryptInputs,
282
302
  decryptHandle,
283
303
  permits: clientPermits,
@@ -33,6 +33,12 @@ export type CofhesdkClient<TConfig extends CofhesdkConfig = CofhesdkConfig> = {
33
33
  readonly config: TConfig;
34
34
 
35
35
  connect(publicClient: PublicClient, walletClient: WalletClient): Promise<void>;
36
+ /**
37
+ * Clears the current connection state (account/chainId/clients) and marks the client as disconnected.
38
+ *
39
+ * This does not delete persisted permits or stored FHE keys; it only resets the in-memory connection.
40
+ */
41
+ disconnect(): void;
36
42
  /**
37
43
  * Types docstring
38
44
  */
@@ -89,7 +95,7 @@ export type CofhesdkClientPermits = {
89
95
 
90
96
  // Mutation methods (chainId/account optional)
91
97
  selectActivePermit: (hash: string, chainId?: number, account?: string) => void;
92
- removePermit: (hash: string, chainId?: number, account?: string, force?: boolean) => void;
98
+ removePermit: (hash: string, chainId?: number, account?: string) => void;
93
99
  removeActivePermit: (chainId?: number, account?: string) => void;
94
100
 
95
101
  // Utils
@@ -126,6 +126,14 @@ describe('createCofhesdkConfigBase', () => {
126
126
  expect(getItemCalled).toBe(true);
127
127
  expect(setItemCalled).toBe(true);
128
128
  expect(removeItemCalled).toBe(true);
129
+
130
+ const invalidStorageNotAFunction = {
131
+ getItem: 'not-a-function',
132
+ setItem: 'not-a-function',
133
+ removeItem: 'not-a-function',
134
+ };
135
+
136
+ expectInvalidConfigItem('fheKeyStorage', invalidStorageNotAFunction);
129
137
  });
130
138
 
131
139
  it('mocks', () => {
package/core/config.ts CHANGED
@@ -70,9 +70,15 @@ export const CofhesdkConfigSchema = z.object({
70
70
  /** Storage method for fhe keys (defaults to indexedDB on web, filesystem on node) */
71
71
  fheKeyStorage: z
72
72
  .object({
73
- getItem: z.function().args(z.string()).returns(z.promise(z.any())),
74
- setItem: z.function().args(z.string(), z.any()).returns(z.promise(z.void())),
75
- removeItem: z.function().args(z.string()).returns(z.promise(z.void())),
73
+ getItem: z.custom<IStorage['getItem']>((val) => typeof val === 'function', {
74
+ message: 'getItem must be a function',
75
+ }),
76
+ setItem: z.custom<IStorage['setItem']>((val) => typeof val === 'function', {
77
+ message: 'setItem must be a function',
78
+ }),
79
+ removeItem: z.custom<IStorage['removeItem']>((val) => typeof val === 'function', {
80
+ message: 'removeItem must be a function',
81
+ }),
76
82
  })
77
83
  .or(z.null())
78
84
  .default(null),
@@ -108,7 +114,7 @@ export function createCofhesdkConfigBase(config: CofhesdkInputConfig): CofhesdkC
108
114
  const result = CofhesdkConfigSchema.safeParse(config);
109
115
 
110
116
  if (!result.success) {
111
- throw new Error(`Invalid cofhesdk configuration: ${result.error.message}`);
117
+ throw new Error(`Invalid cofhesdk configuration: ${z.prettifyError(result.error)}`, { cause: result.error });
112
118
  }
113
119
 
114
120
  return result.data;
package/core/consts.ts ADDED
@@ -0,0 +1,18 @@
1
+ /** Main Task Manager contract address */
2
+ export const TASK_MANAGER_ADDRESS = '0xeA30c4B8b44078Bbf8a6ef5b9f1eC1626C7848D9' as const;
3
+
4
+ /** Mock ZK Verifier contract address (used for testing) */
5
+ export const MOCKS_ZK_VERIFIER_ADDRESS = '0x0000000000000000000000000000000000005001' as const;
6
+
7
+ /** Mock Query Decrypter contract address (used for testing) */
8
+ export const MOCKS_QUERY_DECRYPTER_ADDRESS = '0x0000000000000000000000000000000000005002' as const;
9
+
10
+ /** Test Bed contract address (used for testing) */
11
+ export const TEST_BED_ADDRESS = '0x0000000000000000000000000000000000005003' as const;
12
+
13
+ /** Private key for the Mock ZK Verifier signer account */
14
+ export const MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY =
15
+ '0x6C8D7F768A6BB4AAFE85E8A2F5A9680355239C7E14646ED62B044E39DE154512' as const;
16
+
17
+ /** Address for the Mock ZK Verifier signer account */
18
+ export const MOCKS_ZK_VERIFIER_SIGNER_ADDRESS = '0x6E12D8C87503D4287c294f2Fdef96ACd9DFf6bd2' as const;
@@ -5,9 +5,7 @@ import { sleep } from '../utils.js';
5
5
  import { MockQueryDecrypterAbi } from './MockQueryDecrypterAbi.js';
6
6
  import { FheTypes } from '../types.js';
7
7
  import { CofhesdkError, CofhesdkErrorCode } from '../error.js';
8
-
9
- // Address the Mock Query Decrypter contract is deployed to on the Hardhat chain
10
- export const MockQueryDecrypterAddress = '0x0000000000000000000000000000000000000200';
8
+ import { MOCKS_QUERY_DECRYPTER_ADDRESS } from '../consts.js';
11
9
 
12
10
  export async function cofheMocksSealOutput(
13
11
  ctHash: bigint,
@@ -29,7 +27,7 @@ export async function cofheMocksSealOutput(
29
27
  };
30
28
 
31
29
  const [allowed, error, result] = await publicClient.readContract({
32
- address: MockQueryDecrypterAddress,
30
+ address: MOCKS_QUERY_DECRYPTER_ADDRESS,
33
31
  abi: MockQueryDecrypterAbi,
34
32
  functionName: 'querySealOutput',
35
33
  args: [ctHash, BigInt(utype), permissionWithBigInts],
@@ -14,14 +14,7 @@ import { MockZkVerifierAbi } from './MockZkVerifierAbi.js';
14
14
  import { hardhat } from 'viem/chains';
15
15
  import { CofhesdkError, CofhesdkErrorCode } from '../error.js';
16
16
  import { privateKeyToAccount } from 'viem/accounts';
17
-
18
- // Address the Mock ZkVerifier contract is deployed to on the Hardhat chain
19
- export const MocksZkVerifierAddress = '0x0000000000000000000000000000000000000100';
20
-
21
- // PK & address pair for zk verifier
22
- export const MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY =
23
- '0x6C8D7F768A6BB4AAFE85E8A2F5A9680355239C7E14646ED62B044E39DE154512';
24
- export const MOCKS_ZK_VERIFIER_SIGNER_ADDRESS = '0x6E12D8C87503D4287c294f2Fdef96ACd9DFf6bd2';
17
+ import { MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY, MOCKS_ZK_VERIFIER_ADDRESS } from '../consts.js';
25
18
 
26
19
  type EncryptableItemWithCtHash = EncryptableItem & {
27
20
  ctHash: bigint;
@@ -111,7 +104,7 @@ async function calcCtHashes(
111
104
 
112
105
  try {
113
106
  ctHashes = (await publicClient.readContract({
114
- address: MocksZkVerifierAddress,
107
+ address: MOCKS_ZK_VERIFIER_ADDRESS,
115
108
  abi: MockZkVerifierAbi,
116
109
  functionName: 'zkVerifyCalcCtHashesPacked',
117
110
  args: calcCtHashesArgs,
@@ -122,7 +115,7 @@ async function calcCtHashes(
122
115
  message: `mockZkVerifySign calcCtHashes failed while calling zkVerifyCalcCtHashesPacked`,
123
116
  cause: err instanceof Error ? err : undefined,
124
117
  context: {
125
- address: MocksZkVerifierAddress,
118
+ address: MOCKS_ZK_VERIFIER_ADDRESS,
126
119
  items,
127
120
  account,
128
121
  securityZone,
@@ -163,7 +156,7 @@ async function insertCtHashes(items: EncryptableItemWithCtHash[], walletClient:
163
156
  const account = walletClient.account!;
164
157
 
165
158
  await walletClient.writeContract({
166
- address: MocksZkVerifierAddress,
159
+ address: MOCKS_ZK_VERIFIER_ADDRESS,
167
160
  abi: MockZkVerifierAbi,
168
161
  functionName: 'insertPackedCtHashes',
169
162
  args: insertPackedCtHashesArgs,
package/core/index.ts CHANGED
@@ -83,7 +83,15 @@ export type {
83
83
  } from './encrypt/zkPackProveVerify.js';
84
84
  export { zkProveWithWorker } from './encrypt/zkPackProveVerify.js';
85
85
 
86
- export { MOCKS_ZK_VERIFIER_SIGNER_ADDRESS } from './encrypt/cofheMocksZkVerifySign.js';
86
+ // Contract addresses
87
+ export {
88
+ TASK_MANAGER_ADDRESS,
89
+ MOCKS_ZK_VERIFIER_ADDRESS,
90
+ MOCKS_ZK_VERIFIER_SIGNER_ADDRESS,
91
+ MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY,
92
+ MOCKS_QUERY_DECRYPTER_ADDRESS,
93
+ TEST_BED_ADDRESS,
94
+ } from './consts.js';
87
95
 
88
96
  // Utils
89
97
  export { fheTypeToString } from './utils.js';
@@ -151,7 +151,7 @@ describe('Core Permits Tests', () => {
151
151
  publicClient,
152
152
  bobWalletClient
153
153
  );
154
- permitHash = permits.getHash(createdPermit);
154
+ permitHash = createdPermit.hash;
155
155
  });
156
156
 
157
157
  it('should get permit by hash', async () => {
@@ -195,9 +195,8 @@ describe('Core Permits Tests', () => {
195
195
  const permitKeys = Object.keys(parsedData.state.permits[chainId][bobAddress]);
196
196
  expect(permitKeys.length).toBeGreaterThan(0);
197
197
 
198
- const permitHash = permits.getHash(createdPermit);
199
198
  const serializedPermit = permits.serialize(createdPermit);
200
- expect(parsedData.state.permits[chainId][bobAddress][permitHash]).toEqual(serializedPermit);
199
+ expect(parsedData.state.permits[chainId][bobAddress][createdPermit.hash]).toEqual(serializedPermit);
201
200
  });
202
201
  });
203
202
 
@@ -272,7 +271,7 @@ describe('Core Permits Tests', () => {
272
271
  });
273
272
 
274
273
  expect(permit.name).toBe('First Self Permit');
275
- expect(permits.getHash(permit)).toBe(permits.getHash(firstPermit));
274
+ expect(permit.hash).toBe(firstPermit.hash);
276
275
 
277
276
  // Verify no new permit was created
278
277
  const allPermits = await permits.getPermits(chainId, bobAddress);
@@ -381,7 +380,7 @@ describe('Core Permits Tests', () => {
381
380
  );
382
381
 
383
382
  expect(permit.name).toBe('First Sharing Permit');
384
- expect(permits.getHash(permit)).toBe(permits.getHash(firstPermit));
383
+ expect(permit.hash).toBe(firstPermit.hash);
385
384
 
386
385
  // Verify no new permit was created
387
386
  const allPermits = await permits.getPermits(chainId, bobAddress);
@@ -483,7 +482,7 @@ describe('Core Permits Tests', () => {
483
482
  });
484
483
 
485
484
  // Should be the same permit
486
- expect(permits.getHash(permit1)).toBe(permits.getHash(permit2));
485
+ expect(permit1.hash).toBe(permit2.hash);
487
486
  expect(permit2.name).toBe('Permit 1'); // Original name
488
487
 
489
488
  // Only one permit should exist
package/core/permits.ts CHANGED
@@ -9,6 +9,7 @@ import {
9
9
  type SelfPermit,
10
10
  type RecipientPermit,
11
11
  type SharingPermit,
12
+ type PermitHashFields,
12
13
  } from '@/permits';
13
14
 
14
15
  import { type PublicClient, type WalletClient } from 'viem';
@@ -21,7 +22,7 @@ const storeActivePermit = async (permit: Permit, publicClient: any, walletClient
21
22
  const account = walletClient.account!.address;
22
23
 
23
24
  permitStore.setPermit(chainId, account, permit);
24
- permitStore.setActivePermitHash(chainId, account, PermitUtils.getHash(permit));
25
+ permitStore.setActivePermitHash(chainId, account, permit.hash);
25
26
  };
26
27
 
27
28
  // Generic function to handle permit creation with error handling
@@ -70,7 +71,7 @@ const importShared = async (
70
71
 
71
72
  // PERMIT UTILS
72
73
 
73
- const getHash = (permit: Permit) => {
74
+ const getHash = (permit: PermitHashFields) => {
74
75
  return PermitUtils.getHash(permit);
75
76
  };
76
77
 
@@ -167,8 +168,8 @@ const getOrCreateSharingPermit = async (
167
168
 
168
169
  // REMOVE
169
170
 
170
- const removePermit = async (chainId: number, account: string, hash: string, force?: boolean): Promise<void> =>
171
- permitStore.removePermit(chainId, account, hash, force);
171
+ const removePermit = async (chainId: number, account: string, hash: string): Promise<void> =>
172
+ permitStore.removePermit(chainId, account, hash);
172
173
 
173
174
  const removeActivePermit = async (chainId: number, account: string): Promise<void> =>
174
175
  permitStore.removeActivePermitHash(chainId, account);
package/dist/chains.cjs CHANGED
@@ -12,21 +12,18 @@ var CofheChainSchema = zod.z.object({
12
12
  /** Network identifier */
13
13
  network: zod.z.string().min(1),
14
14
  /** coFhe service URL */
15
- coFheUrl: zod.z.string().url(),
15
+ coFheUrl: zod.z.url(),
16
16
  /** Verifier service URL */
17
- verifierUrl: zod.z.string().url(),
17
+ verifierUrl: zod.z.url(),
18
18
  /** Threshold network service URL */
19
- thresholdNetworkUrl: zod.z.string().url(),
19
+ thresholdNetworkUrl: zod.z.url(),
20
20
  /** Environment type */
21
21
  environment: EnvironmentSchema
22
22
  });
23
-
24
- // chains/defineChain.ts
25
23
  function defineChain(chainConfig) {
26
24
  const result = CofheChainSchema.safeParse(chainConfig);
27
25
  if (!result.success) {
28
- const errorMessages = result.error.errors.map((err) => `${err.path.join(".")}: ${err.message}`);
29
- throw new Error(`Invalid chain configuration: ${errorMessages.join(", ")}`);
26
+ throw new Error(`Invalid chain configuration: ${zod.z.prettifyError(result.error)}`, { cause: result.error });
30
27
  }
31
28
  return result.data;
32
29
  }
package/dist/chains.d.cts CHANGED
@@ -1,13 +1,13 @@
1
- import { C as CofheChain } from './types-KImPrEIe.cjs';
2
- export { E as Environment } from './types-KImPrEIe.cjs';
1
+ import { C as CofheChain } from './types-YiAC4gig.cjs';
2
+ export { E as Environment } from './types-YiAC4gig.cjs';
3
3
  import 'zod';
4
4
 
5
5
  /**
6
6
  * Sepolia testnet chain configuration
7
7
  */
8
8
  declare const sepolia: {
9
- name: string;
10
9
  id: number;
10
+ name: string;
11
11
  network: string;
12
12
  coFheUrl: string;
13
13
  verifierUrl: string;
@@ -19,8 +19,8 @@ declare const sepolia: {
19
19
  * Arbitrum Sepolia testnet chain configuration
20
20
  */
21
21
  declare const arbSepolia: {
22
- name: string;
23
22
  id: number;
23
+ name: string;
24
24
  network: string;
25
25
  coFheUrl: string;
26
26
  verifierUrl: string;
@@ -32,8 +32,8 @@ declare const arbSepolia: {
32
32
  * Base Sepolia testnet chain configuration
33
33
  */
34
34
  declare const baseSepolia: {
35
- name: string;
36
35
  id: number;
36
+ name: string;
37
37
  network: string;
38
38
  coFheUrl: string;
39
39
  verifierUrl: string;
@@ -45,8 +45,8 @@ declare const baseSepolia: {
45
45
  * Hardhat local development chain configuration
46
46
  */
47
47
  declare const hardhat: {
48
- name: string;
49
48
  id: number;
49
+ name: string;
50
50
  network: string;
51
51
  coFheUrl: string;
52
52
  verifierUrl: string;
@@ -58,8 +58,8 @@ declare const hardhat: {
58
58
  * Localcofhe chain configuration
59
59
  */
60
60
  declare const localcofhe: {
61
- name: string;
62
61
  id: number;
62
+ name: string;
63
63
  network: string;
64
64
  coFheUrl: string;
65
65
  verifierUrl: string;
@@ -69,8 +69,8 @@ declare const localcofhe: {
69
69
 
70
70
  declare const chains: {
71
71
  readonly sepolia: {
72
- name: string;
73
72
  id: number;
73
+ name: string;
74
74
  network: string;
75
75
  coFheUrl: string;
76
76
  verifierUrl: string;
@@ -78,8 +78,8 @@ declare const chains: {
78
78
  environment: "MOCK" | "TESTNET" | "MAINNET";
79
79
  };
80
80
  readonly arbSepolia: {
81
- name: string;
82
81
  id: number;
82
+ name: string;
83
83
  network: string;
84
84
  coFheUrl: string;
85
85
  verifierUrl: string;
@@ -87,8 +87,8 @@ declare const chains: {
87
87
  environment: "MOCK" | "TESTNET" | "MAINNET";
88
88
  };
89
89
  readonly baseSepolia: {
90
- name: string;
91
90
  id: number;
91
+ name: string;
92
92
  network: string;
93
93
  coFheUrl: string;
94
94
  verifierUrl: string;
@@ -96,8 +96,8 @@ declare const chains: {
96
96
  environment: "MOCK" | "TESTNET" | "MAINNET";
97
97
  };
98
98
  readonly hardhat: {
99
- name: string;
100
99
  id: number;
100
+ name: string;
101
101
  network: string;
102
102
  coFheUrl: string;
103
103
  verifierUrl: string;
@@ -105,8 +105,8 @@ declare const chains: {
105
105
  environment: "MOCK" | "TESTNET" | "MAINNET";
106
106
  };
107
107
  readonly localcofhe: {
108
- name: string;
109
108
  id: number;
109
+ name: string;
110
110
  network: string;
111
111
  coFheUrl: string;
112
112
  verifierUrl: string;