@cofhe/sdk 0.5.2 → 0.6.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.
@@ -302,15 +302,17 @@ type PermitsStore = {
302
302
  activePermitHash: ChainRecord<AccountRecord<string | undefined>>;
303
303
  };
304
304
  declare const PERMIT_STORE_DEFAULTS: PermitsStore;
305
- declare const _permitStore: Omit<zustand_vanilla.StoreApi<PermitsStore>, "persist"> & {
305
+ declare const _permitStore: Omit<zustand_vanilla.StoreApi<PermitsStore>, "setState" | "persist"> & {
306
+ setState(partial: PermitsStore | Partial<PermitsStore> | ((state: PermitsStore) => PermitsStore | Partial<PermitsStore>), replace?: false | undefined): unknown;
307
+ setState(state: PermitsStore | ((state: PermitsStore) => PermitsStore), replace: true): unknown;
306
308
  persist: {
307
- setOptions: (options: Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore>>) => void;
309
+ setOptions: (options: Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore, unknown>>) => void;
308
310
  clearStorage: () => void;
309
311
  rehydrate: () => Promise<void> | void;
310
312
  hasHydrated: () => boolean;
311
313
  onHydrate: (fn: (state: PermitsStore) => void) => () => void;
312
314
  onFinishHydration: (fn: (state: PermitsStore) => void) => () => void;
313
- getOptions: () => Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore>>;
315
+ getOptions: () => Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore, unknown>>;
314
316
  };
315
317
  };
316
318
  declare const clearStaleStore: () => void;
@@ -324,15 +326,17 @@ declare const setActivePermitHash: (chainId: number, account: string, hash: stri
324
326
  declare const removeActivePermitHash: (chainId: number, account: string) => void;
325
327
  declare const resetStore: () => void;
326
328
  declare const permitStore: {
327
- store: Omit<zustand_vanilla.StoreApi<PermitsStore>, "persist"> & {
329
+ store: Omit<zustand_vanilla.StoreApi<PermitsStore>, "setState" | "persist"> & {
330
+ setState(partial: PermitsStore | Partial<PermitsStore> | ((state: PermitsStore) => PermitsStore | Partial<PermitsStore>), replace?: false | undefined): unknown;
331
+ setState(state: PermitsStore | ((state: PermitsStore) => PermitsStore), replace: true): unknown;
328
332
  persist: {
329
- setOptions: (options: Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore>>) => void;
333
+ setOptions: (options: Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore, unknown>>) => void;
330
334
  clearStorage: () => void;
331
335
  rehydrate: () => Promise<void> | void;
332
336
  hasHydrated: () => boolean;
333
337
  onHydrate: (fn: (state: PermitsStore) => void) => () => void;
334
338
  onFinishHydration: (fn: (state: PermitsStore) => void) => () => void;
335
- getOptions: () => Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore>>;
339
+ getOptions: () => Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore, unknown>>;
336
340
  };
337
341
  };
338
342
  getPermit: (chainId: number | undefined, account: string | undefined, hash: string | undefined) => Permit | undefined;
package/dist/permits.d.ts CHANGED
@@ -302,15 +302,17 @@ type PermitsStore = {
302
302
  activePermitHash: ChainRecord<AccountRecord<string | undefined>>;
303
303
  };
304
304
  declare const PERMIT_STORE_DEFAULTS: PermitsStore;
305
- declare const _permitStore: Omit<zustand_vanilla.StoreApi<PermitsStore>, "persist"> & {
305
+ declare const _permitStore: Omit<zustand_vanilla.StoreApi<PermitsStore>, "setState" | "persist"> & {
306
+ setState(partial: PermitsStore | Partial<PermitsStore> | ((state: PermitsStore) => PermitsStore | Partial<PermitsStore>), replace?: false | undefined): unknown;
307
+ setState(state: PermitsStore | ((state: PermitsStore) => PermitsStore), replace: true): unknown;
306
308
  persist: {
307
- setOptions: (options: Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore>>) => void;
309
+ setOptions: (options: Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore, unknown>>) => void;
308
310
  clearStorage: () => void;
309
311
  rehydrate: () => Promise<void> | void;
310
312
  hasHydrated: () => boolean;
311
313
  onHydrate: (fn: (state: PermitsStore) => void) => () => void;
312
314
  onFinishHydration: (fn: (state: PermitsStore) => void) => () => void;
313
- getOptions: () => Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore>>;
315
+ getOptions: () => Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore, unknown>>;
314
316
  };
315
317
  };
316
318
  declare const clearStaleStore: () => void;
@@ -324,15 +326,17 @@ declare const setActivePermitHash: (chainId: number, account: string, hash: stri
324
326
  declare const removeActivePermitHash: (chainId: number, account: string) => void;
325
327
  declare const resetStore: () => void;
326
328
  declare const permitStore: {
327
- store: Omit<zustand_vanilla.StoreApi<PermitsStore>, "persist"> & {
329
+ store: Omit<zustand_vanilla.StoreApi<PermitsStore>, "setState" | "persist"> & {
330
+ setState(partial: PermitsStore | Partial<PermitsStore> | ((state: PermitsStore) => PermitsStore | Partial<PermitsStore>), replace?: false | undefined): unknown;
331
+ setState(state: PermitsStore | ((state: PermitsStore) => PermitsStore), replace: true): unknown;
328
332
  persist: {
329
- setOptions: (options: Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore>>) => void;
333
+ setOptions: (options: Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore, unknown>>) => void;
330
334
  clearStorage: () => void;
331
335
  rehydrate: () => Promise<void> | void;
332
336
  hasHydrated: () => boolean;
333
337
  onHydrate: (fn: (state: PermitsStore) => void) => () => void;
334
338
  onFinishHydration: (fn: (state: PermitsStore) => void) => () => void;
335
- getOptions: () => Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore>>;
339
+ getOptions: () => Partial<zustand_middleware.PersistOptions<PermitsStore, PermitsStore, unknown>>;
336
340
  };
337
341
  };
338
342
  getPermit: (chainId: number | undefined, account: string | undefined, hash: string | undefined) => Permit | undefined;
package/dist/permits.js CHANGED
@@ -1,2 +1,2 @@
1
- export { GenerateSealingKey, ImportPermitOptionsValidator, ImportPermitValidator, PERMIT_STORE_DEFAULTS, PermitUtils, SealingKey, SelfPermitOptionsValidator, SelfPermitValidator, SharingPermitOptionsValidator, SharingPermitValidator, SignatureTypes, SignatureUtils, ValidationUtils, _permitStore, addressNotZeroSchema, addressSchema, bytesNotEmptySchema, bytesSchema, clearStaleStore, getActivePermit, getActivePermitHash, getPermit, getPermits, getSignatureTypesAndMessage, permitStore, removeActivePermitHash, removePermit, resetStore, setActivePermitHash, setPermit, validateImportPermit, validateImportPermitOptions, validateSelfPermit, validateSelfPermitOptions, validateSharingPermit, validateSharingPermitOptions } from './chunk-MRCKUMOS.js';
2
- import './chunk-4FP4V35O.js';
1
+ export { GenerateSealingKey, ImportPermitOptionsValidator, ImportPermitValidator, PERMIT_STORE_DEFAULTS, PermitUtils, SealingKey, SelfPermitOptionsValidator, SelfPermitValidator, SharingPermitOptionsValidator, SharingPermitValidator, SignatureTypes, SignatureUtils, ValidationUtils, _permitStore, addressNotZeroSchema, addressSchema, bytesNotEmptySchema, bytesSchema, clearStaleStore, getActivePermit, getActivePermitHash, getPermit, getPermits, getSignatureTypesAndMessage, permitStore, removeActivePermitHash, removePermit, resetStore, setActivePermitHash, setPermit, validateImportPermit, validateImportPermitOptions, validateSelfPermit, validateSelfPermitOptions, validateSharingPermit, validateSharingPermitOptions } from './chunk-VB62WYPL.js';
2
+ import './chunk-ESMZCFJY.js';
package/dist/web.cjs CHANGED
@@ -393,7 +393,7 @@ var zkVerify = async (verifierUrl, serializedBytes, address, securityZone, chain
393
393
  }
394
394
  };
395
395
  var concatSigRecid = (signature, recid) => {
396
- return signature + (recid + 27).toString(16).padStart(2, "0");
396
+ return `${signature}${(recid + 27).toString(16).padStart(2, "0")}`;
397
397
  };
398
398
 
399
399
  // core/encrypt/MockZkVerifierAbi.ts
@@ -725,9 +725,9 @@ var hardhat2 = defineChain({
725
725
  name: "Hardhat",
726
726
  network: "localhost",
727
727
  // These are unused in the mock environment
728
- coFheUrl: "http://127.0.0.1:8448",
729
- verifierUrl: "http://127.0.0.1:3001",
730
- thresholdNetworkUrl: "http://127.0.0.1:3000",
728
+ coFheUrl: "http://ignored-in-mock-environment",
729
+ verifierUrl: "http://ignored-in-mock-environment",
730
+ thresholdNetworkUrl: "http://ignored-in-mock-environment",
731
731
  environment: "MOCK"
732
732
  });
733
733
  var CofheConfigSchema = zod.z.object({
@@ -1113,6 +1113,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1113
1113
  securityZone;
1114
1114
  stepCallback;
1115
1115
  inputItems;
1116
+ hpp = false;
1116
1117
  zkvWalletClient;
1117
1118
  tfhePublicKeyDeserializer;
1118
1119
  compactPkeCrsDeserializer;
@@ -1242,6 +1243,20 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1242
1243
  getSecurityZone() {
1243
1244
  return this.securityZone;
1244
1245
  }
1246
+ /**
1247
+ * Example:
1248
+ * ```typescript
1249
+ * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1250
+ * .asHashPlusProof()
1251
+ * .execute();
1252
+ * ```
1253
+ *
1254
+ * @returns Chainable EncryptInputsBuilder instance that will return a HashPlusProofResult instead of an array of EncryptedItemInputs.
1255
+ */
1256
+ asHashPlusProof() {
1257
+ this.hpp = true;
1258
+ return this;
1259
+ }
1245
1260
  /**
1246
1261
  * @param useWorker - Whether to use Web Workers for ZK proof generation.
1247
1262
  *
@@ -1523,6 +1538,15 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1523
1538
  this.fireStepEnd("verify" /* Verify */);
1524
1539
  return encryptedInputs;
1525
1540
  }
1541
+ structsToHashPlusProof(inItems) {
1542
+ let hashes = [];
1543
+ let proof = "";
1544
+ for (const item of inItems) {
1545
+ hashes.push("0x" + item.ctHash.toString(16).padStart(64, "0"));
1546
+ proof += item.signature;
1547
+ }
1548
+ return [...hashes, proof];
1549
+ }
1526
1550
  /**
1527
1551
  * Final step of the encryption process. MUST BE CALLED LAST IN THE CHAIN.
1528
1552
  *
@@ -1543,9 +1567,14 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1543
1567
  * @returns The encrypted inputs.
1544
1568
  */
1545
1569
  async execute() {
1570
+ let items;
1546
1571
  if (this.chainId === chains.hardhat.id)
1547
- return this.mocksExecute();
1548
- return this.productionExecute();
1572
+ items = await this.mocksExecute();
1573
+ else
1574
+ items = await this.productionExecute();
1575
+ if (this.hpp)
1576
+ return this.structsToHashPlusProof(items);
1577
+ return items;
1549
1578
  }
1550
1579
  };
1551
1580
 
package/dist/web.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { I as IStorage, C as CofheInputConfig, a as CofheConfig, b as CofheClient, E as EncryptableItem } from './clientTypes-BJbFeeno.cjs';
1
+ import { I as IStorage, C as CofheInputConfig, a as CofheConfig, b as CofheClient, E as EncryptableItem } from './clientTypes-BDy1qIBu.cjs';
2
2
  import 'viem';
3
3
  import './types-C07FK-cL.cjs';
4
4
  import 'zod';
package/dist/web.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { I as IStorage, C as CofheInputConfig, a as CofheConfig, b as CofheClient, E as EncryptableItem } from './clientTypes-CEno_BEf.js';
1
+ import { I as IStorage, C as CofheInputConfig, a as CofheConfig, b as CofheClient, E as EncryptableItem } from './clientTypes-CyUvRRzA.js';
2
2
  import 'viem';
3
3
  import './types-C07FK-cL.js';
4
4
  import 'zod';
package/dist/web.js CHANGED
@@ -1,7 +1,7 @@
1
- import { createCofheConfigBase, createCofheClientBase, fheTypeToString } from './chunk-YDOK4BDL.js';
2
- import './chunk-TBLR7NNE.js';
3
- import './chunk-MRCKUMOS.js';
4
- import { TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT } from './chunk-4FP4V35O.js';
1
+ import { createCofheConfigBase, createCofheClientBase, fheTypeToString } from './chunk-PE5V5CCV.js';
2
+ import './chunk-MTRAXQXC.js';
3
+ import './chunk-VB62WYPL.js';
4
+ import { TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT } from './chunk-ESMZCFJY.js';
5
5
  import { constructClient } from 'iframe-shared-storage';
6
6
 
7
7
  // web/const.ts
@@ -1,4 +1,4 @@
1
- import { TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT } from './chunk-4FP4V35O.js';
1
+ import { TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT } from './chunk-ESMZCFJY.js';
2
2
 
3
3
  // web/zkProve.worker.ts
4
4
  var tfheModule = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cofhe/sdk",
3
- "version": "0.5.2",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "description": "SDK for Fhenix COFHE coprocessor interaction",
6
6
  "main": "./dist/core.cjs",
@@ -64,7 +64,7 @@
64
64
  "tweetnacl": "1.0.3",
65
65
  "viem": "2.38.6",
66
66
  "zod": "4.0.0",
67
- "zustand": "5.0.1"
67
+ "zustand": "5.0.13"
68
68
  },
69
69
  "peerDependencies": {
70
70
  "@nomicfoundation/hardhat-ethers": "^3.0.0",
package/permits/store.ts CHANGED
@@ -19,6 +19,7 @@ export const PERMIT_STORE_DEFAULTS: PermitsStore = {
19
19
  permits: {},
20
20
  activePermitHash: {},
21
21
  };
22
+
22
23
  export const _permitStore = createStore<PermitsStore>()(
23
24
  persist(() => PERMIT_STORE_DEFAULTS, { name: 'cofhesdk-permits' })
24
25
  );
@@ -0,0 +1,23 @@
1
+ import { describe, expect, it, vi, afterEach } from 'vitest';
2
+
3
+ describe('@cofhe/sdk/web SSR smoke', () => {
4
+ afterEach(() => {
5
+ vi.restoreAllMocks();
6
+ });
7
+
8
+ it('imports and creates config in a Node SSR environment', async () => {
9
+ const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
10
+
11
+ expect((globalThis as { window?: unknown }).window).toBeUndefined();
12
+ expect((globalThis as { document?: unknown }).document).toBeUndefined();
13
+
14
+ const web = await import('../index');
15
+ const config = web.createCofheConfig({ supportedChains: [] });
16
+
17
+ expect(web.hasDOM).toBe(false);
18
+ expect(config.environment).toBe('web');
19
+ expect(config.fheKeyStorage).not.toBeNull();
20
+ expect(() => web.createCofheClient(config)).not.toThrow();
21
+ expect(warnSpy).toHaveBeenCalledWith('using no-op server-side SSR storage');
22
+ });
23
+ });
@@ -1,5 +1,5 @@
1
1
  import { arbSepolia as cofheArbSepolia } from '@/chains';
2
- import { Encryptable, FheTypes, type CofheClient, CofheErrorCode, CofheError } from '@/core';
2
+ import { Encryptable, type CofheClient } from '@/core';
3
3
 
4
4
  import { describe, it, expect, beforeAll, beforeEach } from 'vitest';
5
5
  import type { PublicClient, WalletClient } from 'viem';
@@ -11,6 +11,39 @@ import { createCofheClient, createCofheConfig } from '../index.js';
11
11
  // Real test setup - runs in browser with real tfhe
12
12
  const TEST_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
13
13
 
14
+ // Logs per-step durations using the built-in `context.duration` provided by the SDK.
15
+ // Each encryption run is a separate entry so multi-encrypt tests show per-run breakdowns.
16
+ function makeStepLogger(testName: string) {
17
+ const runs: Array<Record<string, number>> = [];
18
+ let current: Record<string, number> = {};
19
+
20
+ function onStep(step: string, context?: Record<string, unknown>) {
21
+ if (!context?.isEnd) return;
22
+ current[step] = (context.duration as number) ?? 0;
23
+ }
24
+
25
+ function nextRun() {
26
+ if (Object.keys(current).length > 0) runs.push(current);
27
+ current = {};
28
+ }
29
+
30
+ function log() {
31
+ if (Object.keys(current).length > 0) runs.push(current);
32
+ console.log(`\n[TFHE Timing] ${testName}`);
33
+ runs.forEach((run, i) => {
34
+ const label = runs.length > 1 ? ` run ${i + 1}` : '';
35
+ const total = Object.values(run).reduce((a, b) => a + b, 0);
36
+ for (const [step, ms] of Object.entries(run)) {
37
+ console.log(` [${label.trim() || 'run'}] ${step}: ${ms}ms`);
38
+ }
39
+ console.log(` [${label.trim() || 'run'}] total: ${total}ms`);
40
+ });
41
+ console.log('');
42
+ }
43
+
44
+ return { onStep, nextRun, log };
45
+ }
46
+
14
47
  describe('@cofhe/web - TFHE Initialization Browser Tests', () => {
15
48
  let cofheClient: CofheClient;
16
49
  let publicClient: PublicClient;
@@ -42,21 +75,64 @@ describe('@cofhe/web - TFHE Initialization Browser Tests', () => {
42
75
  it('should initialize tfhe on first encryption', async () => {
43
76
  await cofheClient.connect(publicClient, walletClient);
44
77
 
78
+ const logger = makeStepLogger('should initialize tfhe on first encryption');
79
+ let initTfheContext: Record<string, unknown> | undefined;
80
+
45
81
  // This will trigger real TFHE initialization in browser
46
- const result = await cofheClient.encryptInputs([Encryptable.uint128(100n)]).execute();
82
+ const result = await cofheClient
83
+ .encryptInputs([Encryptable.uint128(100n)])
84
+ .onStep((step, context) => {
85
+ logger.onStep(step, context);
86
+ if (step === 'initTfhe' && context?.isEnd) {
87
+ initTfheContext = context;
88
+ }
89
+ })
90
+ .execute();
91
+
92
+ logger.log();
47
93
 
48
94
  // If we get here, TFHE was initialized successfully
49
95
  expect(result).toBeDefined();
96
+ expect(initTfheContext).toBeDefined();
97
+ expect(initTfheContext?.tfheInitializationExecuted).toBe(true);
50
98
  }, 60000); // Longer timeout for real operations
51
99
 
52
100
  it('should handle multiple encryptions without re-initializing', async () => {
53
101
  await cofheClient.connect(publicClient, walletClient);
54
102
 
103
+ const logger = makeStepLogger('should handle multiple encryptions without re-initializing');
104
+ const initTfheContexts: Array<Record<string, unknown>> = [];
105
+
55
106
  // First encryption
56
- await expect(cofheClient.encryptInputs([Encryptable.uint128(100n)]).execute()).resolves.not.toThrow();
107
+ const firstResult = await cofheClient
108
+ .encryptInputs([Encryptable.uint128(100n)])
109
+ .onStep((step, context) => {
110
+ logger.onStep(step, context);
111
+ if (step === 'initTfhe' && context?.isEnd) {
112
+ initTfheContexts.push(context);
113
+ }
114
+ })
115
+ .execute();
116
+
117
+ logger.nextRun();
57
118
 
58
119
  // Second encryption should reuse initialization
59
- await expect(cofheClient.encryptInputs([Encryptable.uint64(50n)]).execute()).resolves.not.toThrow();
60
- }, 120000);
120
+ const secondResult = await cofheClient
121
+ .encryptInputs([Encryptable.uint64(50n)])
122
+ .onStep((step, context) => {
123
+ logger.onStep(step, context);
124
+ if (step === 'initTfhe' && context?.isEnd) {
125
+ initTfheContexts.push(context);
126
+ }
127
+ })
128
+ .execute();
129
+
130
+ logger.log();
131
+
132
+ expect(firstResult).toBeDefined();
133
+ expect(secondResult).toBeDefined();
134
+ expect(initTfheContexts).toHaveLength(2);
135
+ expect(initTfheContexts[1].tfheInitializationExecuted).toBe(false);
136
+ }, 120000); // Two full encryptions on real network; CI runners can be slow
61
137
  });
62
138
  });