@cofhe/sdk 0.0.0-alpha-20260409113701

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 (132) hide show
  1. package/CHANGELOG.md +146 -0
  2. package/adapters/ethers5.test.ts +174 -0
  3. package/adapters/ethers5.ts +36 -0
  4. package/adapters/ethers6.test.ts +169 -0
  5. package/adapters/ethers6.ts +36 -0
  6. package/adapters/hardhat-node.ts +167 -0
  7. package/adapters/hardhat.hh2.test.ts +159 -0
  8. package/adapters/hardhat.ts +36 -0
  9. package/adapters/index.test.ts +20 -0
  10. package/adapters/index.ts +5 -0
  11. package/adapters/smartWallet.ts +99 -0
  12. package/adapters/test-utils.ts +53 -0
  13. package/adapters/types.ts +6 -0
  14. package/adapters/wagmi.test.ts +156 -0
  15. package/adapters/wagmi.ts +17 -0
  16. package/chains/chains/arbSepolia.ts +14 -0
  17. package/chains/chains/baseSepolia.ts +14 -0
  18. package/chains/chains/hardhat.ts +15 -0
  19. package/chains/chains/localcofhe.ts +14 -0
  20. package/chains/chains/sepolia.ts +14 -0
  21. package/chains/chains.test.ts +50 -0
  22. package/chains/defineChain.ts +18 -0
  23. package/chains/index.ts +35 -0
  24. package/chains/types.ts +32 -0
  25. package/core/baseBuilder.ts +119 -0
  26. package/core/client.test.ts +429 -0
  27. package/core/client.ts +341 -0
  28. package/core/clientTypes.ts +119 -0
  29. package/core/config.test.ts +242 -0
  30. package/core/config.ts +225 -0
  31. package/core/consts.ts +22 -0
  32. package/core/decrypt/MockThresholdNetworkAbi.ts +179 -0
  33. package/core/decrypt/cofheMocksDecryptForTx.ts +84 -0
  34. package/core/decrypt/cofheMocksDecryptForView.ts +48 -0
  35. package/core/decrypt/decryptForTxBuilder.ts +359 -0
  36. package/core/decrypt/decryptForViewBuilder.ts +332 -0
  37. package/core/decrypt/decryptUtils.ts +28 -0
  38. package/core/decrypt/pollCallbacks.test.ts +194 -0
  39. package/core/decrypt/polling.ts +14 -0
  40. package/core/decrypt/tnDecryptUtils.ts +65 -0
  41. package/core/decrypt/tnDecryptV1.ts +171 -0
  42. package/core/decrypt/tnDecryptV2.ts +365 -0
  43. package/core/decrypt/tnSealOutputV1.ts +59 -0
  44. package/core/decrypt/tnSealOutputV2.ts +324 -0
  45. package/core/decrypt/verifyDecryptResult.ts +52 -0
  46. package/core/encrypt/MockZkVerifierAbi.ts +106 -0
  47. package/core/encrypt/cofheMocksZkVerifySign.ts +281 -0
  48. package/core/encrypt/encryptInputsBuilder.test.ts +747 -0
  49. package/core/encrypt/encryptInputsBuilder.ts +583 -0
  50. package/core/encrypt/encryptUtils.ts +67 -0
  51. package/core/encrypt/zkPackProveVerify.ts +335 -0
  52. package/core/error.ts +168 -0
  53. package/core/fetchKeys.test.ts +195 -0
  54. package/core/fetchKeys.ts +144 -0
  55. package/core/index.ts +106 -0
  56. package/core/keyStore.test.ts +226 -0
  57. package/core/keyStore.ts +154 -0
  58. package/core/permits.test.ts +493 -0
  59. package/core/permits.ts +201 -0
  60. package/core/types.ts +419 -0
  61. package/core/utils.ts +130 -0
  62. package/dist/adapters.cjs +88 -0
  63. package/dist/adapters.d.cts +14576 -0
  64. package/dist/adapters.d.ts +14576 -0
  65. package/dist/adapters.js +83 -0
  66. package/dist/chains.cjs +111 -0
  67. package/dist/chains.d.cts +121 -0
  68. package/dist/chains.d.ts +121 -0
  69. package/dist/chains.js +1 -0
  70. package/dist/chunk-36FBWLUS.js +3310 -0
  71. package/dist/chunk-7HLGHV67.js +990 -0
  72. package/dist/chunk-TBLR7NNE.js +102 -0
  73. package/dist/clientTypes-AVSCBet7.d.cts +998 -0
  74. package/dist/clientTypes-flH1ju82.d.ts +998 -0
  75. package/dist/core.cjs +4362 -0
  76. package/dist/core.d.cts +138 -0
  77. package/dist/core.d.ts +138 -0
  78. package/dist/core.js +3 -0
  79. package/dist/node.cjs +4225 -0
  80. package/dist/node.d.cts +22 -0
  81. package/dist/node.d.ts +22 -0
  82. package/dist/node.js +91 -0
  83. package/dist/permit-jRirYqFt.d.cts +376 -0
  84. package/dist/permit-jRirYqFt.d.ts +376 -0
  85. package/dist/permits.cjs +1025 -0
  86. package/dist/permits.d.cts +353 -0
  87. package/dist/permits.d.ts +353 -0
  88. package/dist/permits.js +1 -0
  89. package/dist/types-YiAC4gig.d.cts +33 -0
  90. package/dist/types-YiAC4gig.d.ts +33 -0
  91. package/dist/web.cjs +4434 -0
  92. package/dist/web.d.cts +42 -0
  93. package/dist/web.d.ts +42 -0
  94. package/dist/web.js +256 -0
  95. package/dist/zkProve.worker.cjs +93 -0
  96. package/dist/zkProve.worker.d.cts +2 -0
  97. package/dist/zkProve.worker.d.ts +2 -0
  98. package/dist/zkProve.worker.js +91 -0
  99. package/node/client.test.ts +159 -0
  100. package/node/config.test.ts +68 -0
  101. package/node/encryptInputs.test.ts +155 -0
  102. package/node/index.ts +97 -0
  103. package/node/storage.ts +51 -0
  104. package/package.json +121 -0
  105. package/permits/index.ts +68 -0
  106. package/permits/localstorage.test.ts +113 -0
  107. package/permits/onchain-utils.ts +221 -0
  108. package/permits/permit.test.ts +534 -0
  109. package/permits/permit.ts +386 -0
  110. package/permits/sealing.test.ts +84 -0
  111. package/permits/sealing.ts +131 -0
  112. package/permits/signature.ts +79 -0
  113. package/permits/store.test.ts +88 -0
  114. package/permits/store.ts +156 -0
  115. package/permits/test-utils.ts +28 -0
  116. package/permits/types.ts +204 -0
  117. package/permits/utils.ts +58 -0
  118. package/permits/validation.test.ts +361 -0
  119. package/permits/validation.ts +327 -0
  120. package/web/client.web.test.ts +159 -0
  121. package/web/config.web.test.ts +69 -0
  122. package/web/const.ts +2 -0
  123. package/web/encryptInputs.web.test.ts +172 -0
  124. package/web/index.ts +166 -0
  125. package/web/storage.ts +49 -0
  126. package/web/worker.builder.web.test.ts +148 -0
  127. package/web/worker.config.web.test.ts +329 -0
  128. package/web/worker.output.web.test.ts +84 -0
  129. package/web/workerManager.test.ts +80 -0
  130. package/web/workerManager.ts +214 -0
  131. package/web/workerManager.web.test.ts +114 -0
  132. package/web/zkProve.worker.ts +133 -0
package/dist/web.d.cts ADDED
@@ -0,0 +1,42 @@
1
+ import { I as IStorage, C as CofheInputConfig, a as CofheConfig, b as CofheClient, E as EncryptableItem } from './clientTypes-AVSCBet7.cjs';
2
+ import 'viem';
3
+ import './types-YiAC4gig.cjs';
4
+ import 'zod';
5
+ import './permit-jRirYqFt.cjs';
6
+ import 'zustand/vanilla';
7
+
8
+ declare function createSsrStorage(): IStorage;
9
+
10
+ /**
11
+ * Terminate the worker
12
+ */
13
+ declare function terminateWorker(): void;
14
+ /**
15
+ * Check if workers are available
16
+ */
17
+ declare function areWorkersAvailable(): boolean;
18
+
19
+ declare const hasDOM: boolean;
20
+
21
+ /**
22
+ * Creates a CoFHE configuration for web with IndexedDB storage as default
23
+ * @param config - The CoFHE input configuration (fheKeyStorage will default to IndexedDB if not provided)
24
+ * @returns The CoFHE configuration with web defaults applied
25
+ */
26
+ declare function createCofheConfig(config: CofheInputConfig): CofheConfig;
27
+ /**
28
+ * Creates a CoFHE client instance for web with TFHE automatically configured
29
+ * TFHE will be initialized automatically on first encryption - no manual setup required
30
+ * Workers are automatically enabled if available (can be disabled via config.useWorkers)
31
+ * @param config - The CoFHE configuration (use createCofheConfig to create with web defaults)
32
+ * @returns The CoFHE client instance
33
+ */
34
+ declare function createCofheClient<TConfig extends CofheConfig>(config: TConfig): CofheClient<TConfig>;
35
+
36
+ /**
37
+ * Test helper: Create a client with custom worker function (for testing fallback behavior)
38
+ * @internal - Only for testing purposes
39
+ */
40
+ declare function createCofheClientWithCustomWorker(config: CofheConfig, customZkProveWorkerFn: (fheKeyHex: string, crsHex: string, items: EncryptableItem[], metadata: Uint8Array) => Promise<Uint8Array>): CofheClient;
41
+
42
+ export { areWorkersAvailable, createCofheClient, createCofheClientWithCustomWorker, createCofheConfig, createSsrStorage, hasDOM, terminateWorker };
package/dist/web.d.ts ADDED
@@ -0,0 +1,42 @@
1
+ import { I as IStorage, C as CofheInputConfig, a as CofheConfig, b as CofheClient, E as EncryptableItem } from './clientTypes-flH1ju82.js';
2
+ import 'viem';
3
+ import './types-YiAC4gig.js';
4
+ import 'zod';
5
+ import './permit-jRirYqFt.js';
6
+ import 'zustand/vanilla';
7
+
8
+ declare function createSsrStorage(): IStorage;
9
+
10
+ /**
11
+ * Terminate the worker
12
+ */
13
+ declare function terminateWorker(): void;
14
+ /**
15
+ * Check if workers are available
16
+ */
17
+ declare function areWorkersAvailable(): boolean;
18
+
19
+ declare const hasDOM: boolean;
20
+
21
+ /**
22
+ * Creates a CoFHE configuration for web with IndexedDB storage as default
23
+ * @param config - The CoFHE input configuration (fheKeyStorage will default to IndexedDB if not provided)
24
+ * @returns The CoFHE configuration with web defaults applied
25
+ */
26
+ declare function createCofheConfig(config: CofheInputConfig): CofheConfig;
27
+ /**
28
+ * Creates a CoFHE client instance for web with TFHE automatically configured
29
+ * TFHE will be initialized automatically on first encryption - no manual setup required
30
+ * Workers are automatically enabled if available (can be disabled via config.useWorkers)
31
+ * @param config - The CoFHE configuration (use createCofheConfig to create with web defaults)
32
+ * @returns The CoFHE client instance
33
+ */
34
+ declare function createCofheClient<TConfig extends CofheConfig>(config: TConfig): CofheClient<TConfig>;
35
+
36
+ /**
37
+ * Test helper: Create a client with custom worker function (for testing fallback behavior)
38
+ * @internal - Only for testing purposes
39
+ */
40
+ declare function createCofheClientWithCustomWorker(config: CofheConfig, customZkProveWorkerFn: (fheKeyHex: string, crsHex: string, items: EncryptableItem[], metadata: Uint8Array) => Promise<Uint8Array>): CofheClient;
41
+
42
+ export { areWorkersAvailable, createCofheClient, createCofheClientWithCustomWorker, createCofheConfig, createSsrStorage, hasDOM, terminateWorker };
package/dist/web.js ADDED
@@ -0,0 +1,256 @@
1
+ import { createCofheConfigBase, createCofheClientBase, fheTypeToString } from './chunk-36FBWLUS.js';
2
+ import './chunk-TBLR7NNE.js';
3
+ import './chunk-7HLGHV67.js';
4
+ import { constructClient } from 'iframe-shared-storage';
5
+ import init, { init_panic_hook, TfheCompactPublicKey, CompactPkeCrs, ProvenCompactCiphertextList } from 'tfhe';
6
+
7
+ // web/const.ts
8
+ var hasDOM = typeof globalThis?.document !== "undefined" && typeof globalThis?.window !== "undefined";
9
+
10
+ // web/storage.ts
11
+ var createWebStorage = (opts = { enableLog: false }) => {
12
+ if (!hasDOM)
13
+ throw new Error("createWebStorage can only be used in a browser environment");
14
+ const client = constructClient({
15
+ iframe: {
16
+ src: "https://iframe-shared-storage.vercel.app/hub.html",
17
+ messagingOptions: {
18
+ enableLog: opts.enableLog ? "both" : void 0
19
+ },
20
+ iframeReadyTimeoutMs: 3e4,
21
+ // if the iframe is not initied during this interval AND a reuqest is made, such request will throw an error
22
+ methodCallTimeoutMs: 1e4,
23
+ // if a method call is not answered during this interval, the call will throw an error
24
+ methodCallRetries: 3
25
+ // number of retries for a method call if it times out
26
+ }
27
+ });
28
+ const indexedDBKeyval = client.indexedDBKeyval;
29
+ return {
30
+ getItem: async (name) => {
31
+ return await indexedDBKeyval.get(name) ?? null;
32
+ },
33
+ setItem: async (name, value) => {
34
+ await indexedDBKeyval.set(name, value);
35
+ },
36
+ removeItem: async (name) => {
37
+ await indexedDBKeyval.del(name);
38
+ }
39
+ };
40
+ };
41
+ function createSsrStorage() {
42
+ console.warn("using no-op server-side SSR storage");
43
+ return {
44
+ getItem: async () => null,
45
+ setItem: async () => {
46
+ },
47
+ removeItem: async () => {
48
+ }
49
+ };
50
+ }
51
+
52
+ // web/workerManager.ts
53
+ var ZkProveWorkerManager = class {
54
+ worker = null;
55
+ pendingRequests = /* @__PURE__ */ new Map();
56
+ requestCounter = 0;
57
+ workerReady = false;
58
+ initializationPromise = null;
59
+ /**
60
+ * Initialize the worker
61
+ */
62
+ async initializeWorker() {
63
+ if (this.worker && this.workerReady) {
64
+ return;
65
+ }
66
+ if (this.initializationPromise) {
67
+ return this.initializationPromise;
68
+ }
69
+ this.initializationPromise = new Promise((resolve, reject) => {
70
+ try {
71
+ if (typeof Worker === "undefined") {
72
+ reject(new Error("Web Workers not supported"));
73
+ return;
74
+ }
75
+ try {
76
+ this.worker = new Worker(new URL("./zkProve.worker.js", import.meta.url), { type: "module" });
77
+ } catch (error) {
78
+ reject(new Error(`Failed to create worker: ${error}`));
79
+ return;
80
+ }
81
+ this.worker.onmessage = (event) => {
82
+ const { id, type, result, error } = event.data;
83
+ if (type === "ready") {
84
+ this.workerReady = true;
85
+ resolve();
86
+ return;
87
+ }
88
+ const pending = this.pendingRequests.get(id);
89
+ if (!pending) {
90
+ console.warn("[Worker Manager] Received response for unknown request:", id);
91
+ return;
92
+ }
93
+ clearTimeout(pending.timeoutId);
94
+ this.pendingRequests.delete(id);
95
+ if (type === "success" && result) {
96
+ pending.resolve(new Uint8Array(result));
97
+ } else if (type === "error") {
98
+ pending.reject(new Error(error || "Worker error"));
99
+ } else {
100
+ pending.reject(new Error("Invalid response from worker"));
101
+ }
102
+ };
103
+ this.worker.onerror = (error) => {
104
+ console.error("[Worker Manager] Worker error event:", error);
105
+ console.error("[Worker Manager] Error message:", error.message);
106
+ console.error("[Worker Manager] Error filename:", error.filename);
107
+ console.error("[Worker Manager] Error lineno:", error.lineno);
108
+ if (!this.workerReady) {
109
+ reject(new Error(`Worker failed to initialize: ${error.message || "Unknown error"}`));
110
+ }
111
+ this.pendingRequests.forEach(({ reject: reject2, timeoutId }) => {
112
+ clearTimeout(timeoutId);
113
+ reject2(new Error("Worker encountered an error"));
114
+ });
115
+ this.pendingRequests.clear();
116
+ };
117
+ setTimeout(() => {
118
+ if (!this.workerReady) {
119
+ reject(new Error("Worker initialization timeout"));
120
+ }
121
+ }, 5e3);
122
+ } catch (error) {
123
+ reject(error);
124
+ }
125
+ });
126
+ return this.initializationPromise;
127
+ }
128
+ /**
129
+ * Submit a proof generation request to the worker
130
+ */
131
+ async submitProof(fheKeyHex, crsHex, items, metadata) {
132
+ await this.initializeWorker();
133
+ const id = `zkprove-${Date.now()}-${this.requestCounter++}`;
134
+ return new Promise((resolve, reject) => {
135
+ const timeoutId = setTimeout(() => {
136
+ this.pendingRequests.delete(id);
137
+ reject(new Error("Worker request timeout (30s)"));
138
+ }, 3e4);
139
+ this.pendingRequests.set(id, { resolve, reject, timeoutId });
140
+ const message = {
141
+ id,
142
+ type: "zkProve",
143
+ fheKeyHex,
144
+ crsHex,
145
+ items,
146
+ metadata: Array.from(metadata)
147
+ };
148
+ this.worker.postMessage(message);
149
+ });
150
+ }
151
+ /**
152
+ * Terminate the worker and clean up
153
+ */
154
+ terminate() {
155
+ if (this.worker) {
156
+ this.worker.terminate();
157
+ this.worker = null;
158
+ this.workerReady = false;
159
+ this.initializationPromise = null;
160
+ }
161
+ this.pendingRequests.forEach(({ reject, timeoutId }) => {
162
+ clearTimeout(timeoutId);
163
+ reject(new Error("Worker terminated"));
164
+ });
165
+ this.pendingRequests.clear();
166
+ }
167
+ /**
168
+ * Check if worker is available
169
+ */
170
+ isAvailable() {
171
+ return typeof Worker !== "undefined";
172
+ }
173
+ };
174
+ var workerManager = null;
175
+ function getWorkerManager() {
176
+ if (!workerManager) {
177
+ workerManager = new ZkProveWorkerManager();
178
+ }
179
+ return workerManager;
180
+ }
181
+ function terminateWorker() {
182
+ if (workerManager) {
183
+ workerManager.terminate();
184
+ workerManager = null;
185
+ }
186
+ }
187
+ function areWorkersAvailable() {
188
+ return typeof Worker !== "undefined";
189
+ }
190
+ var tfheInitialized = false;
191
+ async function initTfhe() {
192
+ if (tfheInitialized)
193
+ return false;
194
+ await init();
195
+ await init_panic_hook();
196
+ tfheInitialized = true;
197
+ return true;
198
+ }
199
+ var fromHexString = (hexString) => {
200
+ const cleanString = hexString.length % 2 === 1 ? `0${hexString}` : hexString;
201
+ const arr = cleanString.replace(/^0x/, "").match(/.{1,2}/g);
202
+ if (!arr)
203
+ return new Uint8Array();
204
+ return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
205
+ };
206
+ var tfhePublicKeyDeserializer = (buff) => {
207
+ TfheCompactPublicKey.deserialize(fromHexString(buff));
208
+ };
209
+ var compactPkeCrsDeserializer = (buff) => {
210
+ CompactPkeCrs.deserialize(fromHexString(buff));
211
+ };
212
+ var zkBuilderAndCrsGenerator = (fhe, crs) => {
213
+ const fhePublicKey = TfheCompactPublicKey.deserialize(fromHexString(fhe));
214
+ const zkBuilder = ProvenCompactCiphertextList.builder(fhePublicKey);
215
+ const zkCrs = CompactPkeCrs.deserialize(fromHexString(crs));
216
+ return { zkBuilder, zkCrs };
217
+ };
218
+ async function zkProveWithWorker(fheKeyHex, crsHex, items, metadata) {
219
+ const serializedItems = items.map((item) => ({
220
+ utype: fheTypeToString(item.utype),
221
+ data: typeof item.data === "bigint" ? item.data.toString() : item.data
222
+ }));
223
+ const workerManager2 = getWorkerManager();
224
+ return await workerManager2.submitProof(fheKeyHex, crsHex, serializedItems, metadata);
225
+ }
226
+ function createCofheConfig(config) {
227
+ return createCofheConfigBase({
228
+ environment: "web",
229
+ ...config,
230
+ fheKeyStorage: config.fheKeyStorage === null ? null : config.fheKeyStorage ?? (hasDOM ? createWebStorage() : createSsrStorage())
231
+ });
232
+ }
233
+ function createCofheClient(config) {
234
+ return createCofheClientBase({
235
+ config,
236
+ zkBuilderAndCrsGenerator,
237
+ tfhePublicKeyDeserializer,
238
+ compactPkeCrsDeserializer,
239
+ initTfhe,
240
+ // Always provide the worker function if available - config.useWorkers controls usage
241
+ // areWorkersAvailable will return true if the Worker API is available and false in Node.js
242
+ zkProveWorkerFn: areWorkersAvailable() ? zkProveWithWorker : void 0
243
+ });
244
+ }
245
+ function createCofheClientWithCustomWorker(config, customZkProveWorkerFn) {
246
+ return createCofheClientBase({
247
+ config,
248
+ zkBuilderAndCrsGenerator,
249
+ tfhePublicKeyDeserializer,
250
+ compactPkeCrsDeserializer,
251
+ initTfhe,
252
+ zkProveWorkerFn: customZkProveWorkerFn
253
+ });
254
+ }
255
+
256
+ export { areWorkersAvailable, createCofheClient, createCofheClientWithCustomWorker, createCofheConfig, createSsrStorage, hasDOM, terminateWorker };
@@ -0,0 +1,93 @@
1
+ 'use strict';
2
+
3
+ // web/zkProve.worker.ts
4
+ var tfheModule = null;
5
+ var initialized = false;
6
+ async function initTfhe() {
7
+ if (initialized)
8
+ return;
9
+ try {
10
+ tfheModule = await import('tfhe');
11
+ await tfheModule.default();
12
+ await tfheModule.init_panic_hook();
13
+ initialized = true;
14
+ console.log("[Worker] TFHE initialized");
15
+ } catch (error) {
16
+ console.error("[Worker] Failed to initialize TFHE:", error);
17
+ throw error;
18
+ }
19
+ }
20
+ function fromHexString(hexString) {
21
+ const cleanString = hexString.length % 2 === 1 ? `0${hexString}` : hexString;
22
+ const arr = cleanString.replace(/^0x/, "").match(/.{1,2}/g);
23
+ if (!arr)
24
+ return new Uint8Array();
25
+ return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
26
+ }
27
+ self.onmessage = async (event) => {
28
+ const { id, type, fheKeyHex, crsHex, items, metadata } = event.data;
29
+ if (type !== "zkProve") {
30
+ self.postMessage({
31
+ id,
32
+ type: "error",
33
+ error: "Invalid message type"
34
+ });
35
+ return;
36
+ }
37
+ try {
38
+ await initTfhe();
39
+ if (!tfheModule) {
40
+ throw new Error("TFHE module not initialized");
41
+ }
42
+ const fheKeyBytes = fromHexString(fheKeyHex);
43
+ const crsBytes = fromHexString(crsHex);
44
+ const fheKey = tfheModule.TfheCompactPublicKey.deserialize(fheKeyBytes);
45
+ const crs = tfheModule.CompactPkeCrs.deserialize(crsBytes);
46
+ const builder = tfheModule.ProvenCompactCiphertextList.builder(fheKey);
47
+ for (const item of items) {
48
+ switch (item.utype) {
49
+ case "bool":
50
+ builder.push_boolean(Boolean(item.data));
51
+ break;
52
+ case "uint8":
53
+ builder.push_u8(Number(item.data));
54
+ break;
55
+ case "uint16":
56
+ builder.push_u16(Number(item.data));
57
+ break;
58
+ case "uint32":
59
+ builder.push_u32(Number(item.data));
60
+ break;
61
+ case "uint64":
62
+ builder.push_u64(BigInt(item.data));
63
+ break;
64
+ case "uint128":
65
+ builder.push_u128(BigInt(item.data));
66
+ break;
67
+ case "uint160":
68
+ builder.push_u160(BigInt(item.data));
69
+ break;
70
+ default:
71
+ throw new Error(`Unsupported type: ${item.utype}`);
72
+ }
73
+ }
74
+ const metadataBytes = new Uint8Array(metadata);
75
+ const compactList = builder.build_with_proof_packed(crs, metadataBytes, 1);
76
+ const result = compactList.serialize();
77
+ self.postMessage({
78
+ id,
79
+ type: "success",
80
+ result: Array.from(result)
81
+ });
82
+ } catch (error) {
83
+ self.postMessage({
84
+ id,
85
+ type: "error",
86
+ error: error instanceof Error ? error.message : String(error)
87
+ });
88
+ }
89
+ };
90
+ self.postMessage({
91
+ id: "init",
92
+ type: "ready"
93
+ });
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,91 @@
1
+ // web/zkProve.worker.ts
2
+ var tfheModule = null;
3
+ var initialized = false;
4
+ async function initTfhe() {
5
+ if (initialized)
6
+ return;
7
+ try {
8
+ tfheModule = await import('tfhe');
9
+ await tfheModule.default();
10
+ await tfheModule.init_panic_hook();
11
+ initialized = true;
12
+ console.log("[Worker] TFHE initialized");
13
+ } catch (error) {
14
+ console.error("[Worker] Failed to initialize TFHE:", error);
15
+ throw error;
16
+ }
17
+ }
18
+ function fromHexString(hexString) {
19
+ const cleanString = hexString.length % 2 === 1 ? `0${hexString}` : hexString;
20
+ const arr = cleanString.replace(/^0x/, "").match(/.{1,2}/g);
21
+ if (!arr)
22
+ return new Uint8Array();
23
+ return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
24
+ }
25
+ self.onmessage = async (event) => {
26
+ const { id, type, fheKeyHex, crsHex, items, metadata } = event.data;
27
+ if (type !== "zkProve") {
28
+ self.postMessage({
29
+ id,
30
+ type: "error",
31
+ error: "Invalid message type"
32
+ });
33
+ return;
34
+ }
35
+ try {
36
+ await initTfhe();
37
+ if (!tfheModule) {
38
+ throw new Error("TFHE module not initialized");
39
+ }
40
+ const fheKeyBytes = fromHexString(fheKeyHex);
41
+ const crsBytes = fromHexString(crsHex);
42
+ const fheKey = tfheModule.TfheCompactPublicKey.deserialize(fheKeyBytes);
43
+ const crs = tfheModule.CompactPkeCrs.deserialize(crsBytes);
44
+ const builder = tfheModule.ProvenCompactCiphertextList.builder(fheKey);
45
+ for (const item of items) {
46
+ switch (item.utype) {
47
+ case "bool":
48
+ builder.push_boolean(Boolean(item.data));
49
+ break;
50
+ case "uint8":
51
+ builder.push_u8(Number(item.data));
52
+ break;
53
+ case "uint16":
54
+ builder.push_u16(Number(item.data));
55
+ break;
56
+ case "uint32":
57
+ builder.push_u32(Number(item.data));
58
+ break;
59
+ case "uint64":
60
+ builder.push_u64(BigInt(item.data));
61
+ break;
62
+ case "uint128":
63
+ builder.push_u128(BigInt(item.data));
64
+ break;
65
+ case "uint160":
66
+ builder.push_u160(BigInt(item.data));
67
+ break;
68
+ default:
69
+ throw new Error(`Unsupported type: ${item.utype}`);
70
+ }
71
+ }
72
+ const metadataBytes = new Uint8Array(metadata);
73
+ const compactList = builder.build_with_proof_packed(crs, metadataBytes, 1);
74
+ const result = compactList.serialize();
75
+ self.postMessage({
76
+ id,
77
+ type: "success",
78
+ result: Array.from(result)
79
+ });
80
+ } catch (error) {
81
+ self.postMessage({
82
+ id,
83
+ type: "error",
84
+ error: error instanceof Error ? error.message : String(error)
85
+ });
86
+ }
87
+ };
88
+ self.postMessage({
89
+ id: "init",
90
+ type: "ready"
91
+ });
@@ -0,0 +1,159 @@
1
+ import { type CofheClient, CofheError, CofheErrorCode } from '@/core';
2
+ import { arbSepolia as cofheArbSepolia } from '@/chains';
3
+
4
+ import { describe, it, expect, beforeAll, beforeEach, vi } from 'vitest';
5
+ import type { PublicClient, WalletClient } from 'viem';
6
+ import { createPublicClient, createWalletClient, http } from 'viem';
7
+ import { privateKeyToAccount } from 'viem/accounts';
8
+ import { arbitrumSepolia as viemArbitrumSepolia } from 'viem/chains';
9
+ import { createCofheClient, createCofheConfig } from './index.js';
10
+
11
+ // Real test setup - no mocks
12
+ const TEST_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
13
+ const TEST_ACCOUNT = privateKeyToAccount(TEST_PRIVATE_KEY).address;
14
+
15
+ describe('@cofhe/node - Client Integration Tests', () => {
16
+ let cofheClient: CofheClient;
17
+ let publicClient: PublicClient;
18
+ let walletClient: WalletClient;
19
+
20
+ beforeAll(() => {
21
+ // Create real viem clients
22
+ publicClient = createPublicClient({
23
+ chain: viemArbitrumSepolia,
24
+ transport: http(),
25
+ });
26
+
27
+ const account = privateKeyToAccount(TEST_PRIVATE_KEY);
28
+ walletClient = createWalletClient({
29
+ chain: viemArbitrumSepolia,
30
+ transport: http(),
31
+ account,
32
+ });
33
+ });
34
+
35
+ beforeEach(() => {
36
+ const config = createCofheConfig({
37
+ supportedChains: [cofheArbSepolia],
38
+ });
39
+ cofheClient = createCofheClient(config);
40
+ });
41
+
42
+ describe('Real Client Initialization', () => {
43
+ it('should create a client with real node-tfhe', () => {
44
+ expect(cofheClient).toBeDefined();
45
+ expect(cofheClient.config).toBeDefined();
46
+ expect(cofheClient.connected).toBe(false);
47
+ });
48
+
49
+ it('should automatically use filesystem storage as default', () => {
50
+ expect(cofheClient.config.fheKeyStorage).toBeDefined();
51
+ expect(cofheClient.config.fheKeyStorage).not.toBeNull();
52
+ });
53
+
54
+ it('should have all expected methods', () => {
55
+ expect(typeof cofheClient.connect).toBe('function');
56
+ expect(typeof cofheClient.encryptInputs).toBe('function');
57
+ expect(typeof cofheClient.decryptForView).toBe('function');
58
+ expect(typeof cofheClient.getSnapshot).toBe('function');
59
+ expect(typeof cofheClient.subscribe).toBe('function');
60
+ });
61
+ });
62
+
63
+ describe('Environment', () => {
64
+ it('should have the correct environment', () => {
65
+ expect(cofheClient.config.environment).toBe('node');
66
+ });
67
+ });
68
+
69
+ describe('Real Connection', () => {
70
+ it('should connect to real chain', async () => {
71
+ await cofheClient.connect(publicClient, walletClient);
72
+
73
+ expect(cofheClient.connected).toBe(true);
74
+
75
+ const snapshot = cofheClient.getSnapshot();
76
+ expect(snapshot.connected).toBe(true);
77
+ expect(snapshot.chainId).toBe(cofheArbSepolia.id);
78
+ expect(snapshot.account).toBe(TEST_ACCOUNT);
79
+ }, 30000);
80
+
81
+ it('should handle real network errors', async () => {
82
+ try {
83
+ await cofheClient.connect(
84
+ {
85
+ getChainId: vi.fn().mockRejectedValue(new Error('Network error')),
86
+ } as unknown as PublicClient,
87
+ walletClient
88
+ );
89
+ } catch (error) {
90
+ expect(error).toBeInstanceOf(CofheError);
91
+ expect((error as CofheError).code).toBe(CofheErrorCode.PublicWalletGetChainIdFailed);
92
+ }
93
+ }, 30000);
94
+ });
95
+
96
+ describe('State Management', () => {
97
+ it('should track connection state changes', async () => {
98
+ const states: any[] = [];
99
+ const unsubscribe = cofheClient.subscribe((snapshot) => {
100
+ states.push({ ...snapshot });
101
+ });
102
+
103
+ await cofheClient.connect(publicClient, walletClient);
104
+
105
+ unsubscribe();
106
+
107
+ expect(states.length).toBeGreaterThan(0);
108
+
109
+ // First state should be connecting
110
+ const firstState = states.find((s) => s.connecting);
111
+ expect(firstState).toBeDefined();
112
+ expect(firstState?.connecting).toBe(true);
113
+ expect(firstState?.connected).toBe(false);
114
+
115
+ // Last state should be connected
116
+ const lastState = states[states.length - 1];
117
+ expect(lastState.connected).toBe(true);
118
+ expect(lastState.connecting).toBe(false);
119
+ expect(lastState.chainId).toBe(cofheArbSepolia.id);
120
+ }, 30000);
121
+ });
122
+
123
+ describe('Builder Creation', () => {
124
+ it('should create encrypt builder after connection', async () => {
125
+ await cofheClient.connect(publicClient, walletClient);
126
+
127
+ const builder = cofheClient.encryptInputs([{ data: 100n, utype: 2, securityZone: 0 }]);
128
+
129
+ expect(builder).toBeDefined();
130
+ expect(typeof builder.setChainId).toBe('function');
131
+ expect(typeof builder.setAccount).toBe('function');
132
+ expect(typeof builder.setSecurityZone).toBe('function');
133
+ expect(typeof builder.execute).toBe('function');
134
+ }, 30000);
135
+
136
+ it('should create decrypt builder after connection', async () => {
137
+ await cofheClient.connect(publicClient, walletClient);
138
+
139
+ const builder = cofheClient.decryptForView('0x123', 2);
140
+
141
+ expect(builder).toBeDefined();
142
+ expect(typeof builder.setChainId).toBe('function');
143
+ expect(typeof builder.setAccount).toBe('function');
144
+ expect(typeof builder.onPoll).toBe('function');
145
+ expect(typeof builder.execute).toBe('function');
146
+ }, 30000);
147
+
148
+ it('should create decryptForTx builder after connection', async () => {
149
+ await cofheClient.connect(publicClient, walletClient);
150
+
151
+ const builder = cofheClient.decryptForTx('0x123');
152
+
153
+ expect(builder).toBeDefined();
154
+ expect(typeof builder.setChainId).toBe('function');
155
+ expect(typeof builder.setAccount).toBe('function');
156
+ expect(typeof builder.onPoll).toBe('function');
157
+ }, 30000);
158
+ });
159
+ });