@cofhe/sdk 0.1.0 → 0.2.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 (121) hide show
  1. package/CHANGELOG.md +62 -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 +315 -0
  27. package/core/client.ts +292 -0
  28. package/core/clientTypes.ts +108 -0
  29. package/core/config.test.ts +235 -0
  30. package/core/config.ts +220 -0
  31. package/core/decrypt/MockQueryDecrypterAbi.ts +129 -0
  32. package/core/decrypt/cofheMocksSealOutput.ts +57 -0
  33. package/core/decrypt/decryptHandleBuilder.ts +287 -0
  34. package/core/decrypt/decryptUtils.ts +28 -0
  35. package/core/decrypt/tnSealOutputV1.ts +59 -0
  36. package/core/decrypt/tnSealOutputV2.ts +298 -0
  37. package/core/encrypt/MockZkVerifierAbi.ts +106 -0
  38. package/core/encrypt/cofheMocksZkVerifySign.ts +284 -0
  39. package/core/encrypt/encryptInputsBuilder.test.ts +751 -0
  40. package/core/encrypt/encryptInputsBuilder.ts +560 -0
  41. package/core/encrypt/encryptUtils.ts +67 -0
  42. package/core/encrypt/zkPackProveVerify.ts +335 -0
  43. package/core/error.ts +168 -0
  44. package/core/fetchKeys.test.ts +195 -0
  45. package/core/fetchKeys.ts +144 -0
  46. package/core/index.ts +89 -0
  47. package/core/keyStore.test.ts +226 -0
  48. package/core/keyStore.ts +154 -0
  49. package/core/permits.test.ts +494 -0
  50. package/core/permits.ts +200 -0
  51. package/core/types.ts +398 -0
  52. package/core/utils.ts +130 -0
  53. package/dist/adapters.cjs +88 -0
  54. package/dist/adapters.d.cts +14576 -0
  55. package/dist/adapters.d.ts +14576 -0
  56. package/dist/adapters.js +83 -0
  57. package/dist/chains.cjs +114 -0
  58. package/dist/chains.d.cts +121 -0
  59. package/dist/chains.d.ts +121 -0
  60. package/dist/chains.js +1 -0
  61. package/dist/chunk-UGBVZNRT.js +818 -0
  62. package/dist/chunk-WEAZ25JO.js +105 -0
  63. package/dist/chunk-WGCRJCBR.js +2523 -0
  64. package/dist/clientTypes-5_1nwtUe.d.cts +914 -0
  65. package/dist/clientTypes-Es7fyi65.d.ts +914 -0
  66. package/dist/core.cjs +3414 -0
  67. package/dist/core.d.cts +111 -0
  68. package/dist/core.d.ts +111 -0
  69. package/dist/core.js +3 -0
  70. package/dist/node.cjs +3286 -0
  71. package/dist/node.d.cts +22 -0
  72. package/dist/node.d.ts +22 -0
  73. package/dist/node.js +91 -0
  74. package/dist/permit-fUSe6KKq.d.cts +349 -0
  75. package/dist/permit-fUSe6KKq.d.ts +349 -0
  76. package/dist/permits.cjs +871 -0
  77. package/dist/permits.d.cts +1045 -0
  78. package/dist/permits.d.ts +1045 -0
  79. package/dist/permits.js +1 -0
  80. package/dist/types-KImPrEIe.d.cts +48 -0
  81. package/dist/types-KImPrEIe.d.ts +48 -0
  82. package/dist/web.cjs +3478 -0
  83. package/dist/web.d.cts +38 -0
  84. package/dist/web.d.ts +38 -0
  85. package/dist/web.js +240 -0
  86. package/dist/zkProve.worker.cjs +93 -0
  87. package/dist/zkProve.worker.d.cts +2 -0
  88. package/dist/zkProve.worker.d.ts +2 -0
  89. package/dist/zkProve.worker.js +91 -0
  90. package/node/client.test.ts +147 -0
  91. package/node/config.test.ts +68 -0
  92. package/node/encryptInputs.test.ts +155 -0
  93. package/node/index.ts +97 -0
  94. package/node/storage.ts +51 -0
  95. package/package.json +27 -15
  96. package/permits/index.ts +68 -0
  97. package/permits/localstorage.test.ts +117 -0
  98. package/permits/permit.test.ts +477 -0
  99. package/permits/permit.ts +405 -0
  100. package/permits/sealing.test.ts +84 -0
  101. package/permits/sealing.ts +131 -0
  102. package/permits/signature.ts +79 -0
  103. package/permits/store.test.ts +128 -0
  104. package/permits/store.ts +166 -0
  105. package/permits/test-utils.ts +20 -0
  106. package/permits/types.ts +191 -0
  107. package/permits/utils.ts +62 -0
  108. package/permits/validation.test.ts +288 -0
  109. package/permits/validation.ts +369 -0
  110. package/web/client.web.test.ts +147 -0
  111. package/web/config.web.test.ts +69 -0
  112. package/web/encryptInputs.web.test.ts +172 -0
  113. package/web/index.ts +161 -0
  114. package/web/storage.ts +34 -0
  115. package/web/worker.builder.web.test.ts +148 -0
  116. package/web/worker.config.web.test.ts +329 -0
  117. package/web/worker.output.web.test.ts +84 -0
  118. package/web/workerManager.test.ts +80 -0
  119. package/web/workerManager.ts +214 -0
  120. package/web/workerManager.web.test.ts +114 -0
  121. package/web/zkProve.worker.ts +133 -0
package/dist/web.d.cts ADDED
@@ -0,0 +1,38 @@
1
+ import { C as CofhesdkInputConfig, a as CofhesdkConfig, b as CofhesdkClient, E as EncryptableItem } from './clientTypes-5_1nwtUe.cjs';
2
+ import 'viem';
3
+ import './types-KImPrEIe.cjs';
4
+ import 'zod';
5
+ import './permit-fUSe6KKq.cjs';
6
+ import 'zustand/vanilla';
7
+
8
+ /**
9
+ * Terminate the worker
10
+ */
11
+ declare function terminateWorker(): void;
12
+ /**
13
+ * Check if workers are available
14
+ */
15
+ declare function areWorkersAvailable(): boolean;
16
+
17
+ /**
18
+ * Creates a CoFHE SDK configuration for web with IndexedDB storage as default
19
+ * @param config - The CoFHE SDK input configuration (fheKeyStorage will default to IndexedDB if not provided)
20
+ * @returns The CoFHE SDK configuration with web defaults applied
21
+ */
22
+ declare function createCofhesdkConfig(config: CofhesdkInputConfig): CofhesdkConfig;
23
+ /**
24
+ * Creates a CoFHE SDK client instance for web with TFHE automatically configured
25
+ * TFHE will be initialized automatically on first encryption - no manual setup required
26
+ * Workers are automatically enabled if available (can be disabled via config.useWorkers)
27
+ * @param config - The CoFHE SDK configuration (use createCofhesdkConfig to create with web defaults)
28
+ * @returns The CoFHE SDK client instance
29
+ */
30
+ declare function createCofhesdkClient<TConfig extends CofhesdkConfig>(config: TConfig): CofhesdkClient<TConfig>;
31
+
32
+ /**
33
+ * Test helper: Create a client with custom worker function (for testing fallback behavior)
34
+ * @internal - Only for testing purposes
35
+ */
36
+ declare function createCofhesdkClientWithCustomWorker(config: CofhesdkConfig, customZkProveWorkerFn: (fheKeyHex: string, crsHex: string, items: EncryptableItem[], metadata: Uint8Array) => Promise<Uint8Array>): CofhesdkClient;
37
+
38
+ export { areWorkersAvailable, createCofhesdkClient, createCofhesdkClientWithCustomWorker, createCofhesdkConfig, terminateWorker };
package/dist/web.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ import { C as CofhesdkInputConfig, a as CofhesdkConfig, b as CofhesdkClient, E as EncryptableItem } from './clientTypes-Es7fyi65.js';
2
+ import 'viem';
3
+ import './types-KImPrEIe.js';
4
+ import 'zod';
5
+ import './permit-fUSe6KKq.js';
6
+ import 'zustand/vanilla';
7
+
8
+ /**
9
+ * Terminate the worker
10
+ */
11
+ declare function terminateWorker(): void;
12
+ /**
13
+ * Check if workers are available
14
+ */
15
+ declare function areWorkersAvailable(): boolean;
16
+
17
+ /**
18
+ * Creates a CoFHE SDK configuration for web with IndexedDB storage as default
19
+ * @param config - The CoFHE SDK input configuration (fheKeyStorage will default to IndexedDB if not provided)
20
+ * @returns The CoFHE SDK configuration with web defaults applied
21
+ */
22
+ declare function createCofhesdkConfig(config: CofhesdkInputConfig): CofhesdkConfig;
23
+ /**
24
+ * Creates a CoFHE SDK client instance for web with TFHE automatically configured
25
+ * TFHE will be initialized automatically on first encryption - no manual setup required
26
+ * Workers are automatically enabled if available (can be disabled via config.useWorkers)
27
+ * @param config - The CoFHE SDK configuration (use createCofhesdkConfig to create with web defaults)
28
+ * @returns The CoFHE SDK client instance
29
+ */
30
+ declare function createCofhesdkClient<TConfig extends CofhesdkConfig>(config: TConfig): CofhesdkClient<TConfig>;
31
+
32
+ /**
33
+ * Test helper: Create a client with custom worker function (for testing fallback behavior)
34
+ * @internal - Only for testing purposes
35
+ */
36
+ declare function createCofhesdkClientWithCustomWorker(config: CofhesdkConfig, customZkProveWorkerFn: (fheKeyHex: string, crsHex: string, items: EncryptableItem[], metadata: Uint8Array) => Promise<Uint8Array>): CofhesdkClient;
37
+
38
+ export { areWorkersAvailable, createCofhesdkClient, createCofhesdkClientWithCustomWorker, createCofhesdkConfig, terminateWorker };
package/dist/web.js ADDED
@@ -0,0 +1,240 @@
1
+ import { createCofhesdkConfigBase, createCofhesdkClientBase, fheTypeToString } from './chunk-WGCRJCBR.js';
2
+ import './chunk-WEAZ25JO.js';
3
+ import './chunk-UGBVZNRT.js';
4
+ import { constructClient } from 'iframe-shared-storage';
5
+ import init, { init_panic_hook, TfheCompactPublicKey, CompactPkeCrs, ProvenCompactCiphertextList } from 'tfhe';
6
+
7
+ var createWebStorage = () => {
8
+ const client = constructClient({
9
+ iframe: {
10
+ src: "https://iframe-shared-storage.vercel.app/hub.html",
11
+ messagingOptions: {
12
+ enableLog: "both"
13
+ },
14
+ iframeReadyTimeoutMs: 3e4,
15
+ // if the iframe is not initied during this interval AND a reuqest is made, such request will throw an error
16
+ methodCallTimeoutMs: 1e4,
17
+ // if a method call is not answered during this interval, the call will throw an error
18
+ methodCallRetries: 3
19
+ // number of retries for a method call if it times out
20
+ }
21
+ });
22
+ const indexedDBKeyval = client.indexedDBKeyval;
23
+ return {
24
+ getItem: async (name) => {
25
+ return await indexedDBKeyval.get(name) ?? null;
26
+ },
27
+ setItem: async (name, value) => {
28
+ await indexedDBKeyval.set(name, value);
29
+ },
30
+ removeItem: async (name) => {
31
+ await indexedDBKeyval.del(name);
32
+ }
33
+ };
34
+ };
35
+
36
+ // web/workerManager.ts
37
+ var ZkProveWorkerManager = class {
38
+ worker = null;
39
+ pendingRequests = /* @__PURE__ */ new Map();
40
+ requestCounter = 0;
41
+ workerReady = false;
42
+ initializationPromise = null;
43
+ /**
44
+ * Initialize the worker
45
+ */
46
+ async initializeWorker() {
47
+ if (this.worker && this.workerReady) {
48
+ return;
49
+ }
50
+ if (this.initializationPromise) {
51
+ return this.initializationPromise;
52
+ }
53
+ this.initializationPromise = new Promise((resolve, reject) => {
54
+ try {
55
+ if (typeof Worker === "undefined") {
56
+ reject(new Error("Web Workers not supported"));
57
+ return;
58
+ }
59
+ try {
60
+ this.worker = new Worker(new URL("./zkProve.worker.js", import.meta.url), { type: "module" });
61
+ } catch (error) {
62
+ reject(new Error(`Failed to create worker: ${error}`));
63
+ return;
64
+ }
65
+ this.worker.onmessage = (event) => {
66
+ const { id, type, result, error } = event.data;
67
+ if (type === "ready") {
68
+ this.workerReady = true;
69
+ resolve();
70
+ return;
71
+ }
72
+ const pending = this.pendingRequests.get(id);
73
+ if (!pending) {
74
+ console.warn("[Worker Manager] Received response for unknown request:", id);
75
+ return;
76
+ }
77
+ clearTimeout(pending.timeoutId);
78
+ this.pendingRequests.delete(id);
79
+ if (type === "success" && result) {
80
+ pending.resolve(new Uint8Array(result));
81
+ } else if (type === "error") {
82
+ pending.reject(new Error(error || "Worker error"));
83
+ } else {
84
+ pending.reject(new Error("Invalid response from worker"));
85
+ }
86
+ };
87
+ this.worker.onerror = (error) => {
88
+ console.error("[Worker Manager] Worker error event:", error);
89
+ console.error("[Worker Manager] Error message:", error.message);
90
+ console.error("[Worker Manager] Error filename:", error.filename);
91
+ console.error("[Worker Manager] Error lineno:", error.lineno);
92
+ if (!this.workerReady) {
93
+ reject(new Error(`Worker failed to initialize: ${error.message || "Unknown error"}`));
94
+ }
95
+ this.pendingRequests.forEach(({ reject: reject2, timeoutId }) => {
96
+ clearTimeout(timeoutId);
97
+ reject2(new Error("Worker encountered an error"));
98
+ });
99
+ this.pendingRequests.clear();
100
+ };
101
+ setTimeout(() => {
102
+ if (!this.workerReady) {
103
+ reject(new Error("Worker initialization timeout"));
104
+ }
105
+ }, 5e3);
106
+ } catch (error) {
107
+ reject(error);
108
+ }
109
+ });
110
+ return this.initializationPromise;
111
+ }
112
+ /**
113
+ * Submit a proof generation request to the worker
114
+ */
115
+ async submitProof(fheKeyHex, crsHex, items, metadata) {
116
+ await this.initializeWorker();
117
+ const id = `zkprove-${Date.now()}-${this.requestCounter++}`;
118
+ return new Promise((resolve, reject) => {
119
+ const timeoutId = setTimeout(() => {
120
+ this.pendingRequests.delete(id);
121
+ reject(new Error("Worker request timeout (30s)"));
122
+ }, 3e4);
123
+ this.pendingRequests.set(id, { resolve, reject, timeoutId });
124
+ const message = {
125
+ id,
126
+ type: "zkProve",
127
+ fheKeyHex,
128
+ crsHex,
129
+ items,
130
+ metadata: Array.from(metadata)
131
+ };
132
+ this.worker.postMessage(message);
133
+ });
134
+ }
135
+ /**
136
+ * Terminate the worker and clean up
137
+ */
138
+ terminate() {
139
+ if (this.worker) {
140
+ this.worker.terminate();
141
+ this.worker = null;
142
+ this.workerReady = false;
143
+ this.initializationPromise = null;
144
+ }
145
+ this.pendingRequests.forEach(({ reject, timeoutId }) => {
146
+ clearTimeout(timeoutId);
147
+ reject(new Error("Worker terminated"));
148
+ });
149
+ this.pendingRequests.clear();
150
+ }
151
+ /**
152
+ * Check if worker is available
153
+ */
154
+ isAvailable() {
155
+ return typeof Worker !== "undefined";
156
+ }
157
+ };
158
+ var workerManager = null;
159
+ function getWorkerManager() {
160
+ if (!workerManager) {
161
+ workerManager = new ZkProveWorkerManager();
162
+ }
163
+ return workerManager;
164
+ }
165
+ function terminateWorker() {
166
+ if (workerManager) {
167
+ workerManager.terminate();
168
+ workerManager = null;
169
+ }
170
+ }
171
+ function areWorkersAvailable() {
172
+ return typeof Worker !== "undefined";
173
+ }
174
+ var tfheInitialized = false;
175
+ async function initTfhe() {
176
+ if (tfheInitialized)
177
+ return false;
178
+ await init();
179
+ await init_panic_hook();
180
+ tfheInitialized = true;
181
+ return true;
182
+ }
183
+ var fromHexString = (hexString) => {
184
+ const cleanString = hexString.length % 2 === 1 ? `0${hexString}` : hexString;
185
+ const arr = cleanString.replace(/^0x/, "").match(/.{1,2}/g);
186
+ if (!arr)
187
+ return new Uint8Array();
188
+ return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
189
+ };
190
+ var tfhePublicKeyDeserializer = (buff) => {
191
+ TfheCompactPublicKey.deserialize(fromHexString(buff));
192
+ };
193
+ var compactPkeCrsDeserializer = (buff) => {
194
+ CompactPkeCrs.deserialize(fromHexString(buff));
195
+ };
196
+ var zkBuilderAndCrsGenerator = (fhe, crs) => {
197
+ const fhePublicKey = TfheCompactPublicKey.deserialize(fromHexString(fhe));
198
+ const zkBuilder = ProvenCompactCiphertextList.builder(fhePublicKey);
199
+ const zkCrs = CompactPkeCrs.deserialize(fromHexString(crs));
200
+ return { zkBuilder, zkCrs };
201
+ };
202
+ async function zkProveWithWorker(fheKeyHex, crsHex, items, metadata) {
203
+ const serializedItems = items.map((item) => ({
204
+ utype: fheTypeToString(item.utype),
205
+ data: typeof item.data === "bigint" ? item.data.toString() : item.data
206
+ }));
207
+ const workerManager2 = getWorkerManager();
208
+ return await workerManager2.submitProof(fheKeyHex, crsHex, serializedItems, metadata);
209
+ }
210
+ function createCofhesdkConfig(config) {
211
+ return createCofhesdkConfigBase({
212
+ environment: "web",
213
+ ...config,
214
+ fheKeyStorage: config.fheKeyStorage === null ? null : config.fheKeyStorage ?? createWebStorage()
215
+ });
216
+ }
217
+ function createCofhesdkClient(config) {
218
+ return createCofhesdkClientBase({
219
+ config,
220
+ zkBuilderAndCrsGenerator,
221
+ tfhePublicKeyDeserializer,
222
+ compactPkeCrsDeserializer,
223
+ initTfhe,
224
+ // Always provide the worker function if available - config.useWorkers controls usage
225
+ // areWorkersAvailable will return true if the Worker API is available and false in Node.js
226
+ zkProveWorkerFn: areWorkersAvailable() ? zkProveWithWorker : void 0
227
+ });
228
+ }
229
+ function createCofhesdkClientWithCustomWorker(config, customZkProveWorkerFn) {
230
+ return createCofhesdkClientBase({
231
+ config,
232
+ zkBuilderAndCrsGenerator,
233
+ tfhePublicKeyDeserializer,
234
+ compactPkeCrsDeserializer,
235
+ initTfhe,
236
+ zkProveWorkerFn: customZkProveWorkerFn
237
+ });
238
+ }
239
+
240
+ export { areWorkersAvailable, createCofhesdkClient, createCofhesdkClientWithCustomWorker, createCofhesdkConfig, 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,147 @@
1
+ import { type CofhesdkClient, CofhesdkError, CofhesdkErrorCode } from '@/core';
2
+ import { arbSepolia as cofhesdkArbSepolia } 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 { createCofhesdkClient, createCofhesdkConfig } 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 cofhesdkClient: CofhesdkClient;
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 = createCofhesdkConfig({
37
+ supportedChains: [cofhesdkArbSepolia],
38
+ });
39
+ cofhesdkClient = createCofhesdkClient(config);
40
+ });
41
+
42
+ describe('Real Client Initialization', () => {
43
+ it('should create a client with real node-tfhe', () => {
44
+ expect(cofhesdkClient).toBeDefined();
45
+ expect(cofhesdkClient.config).toBeDefined();
46
+ expect(cofhesdkClient.connected).toBe(false);
47
+ });
48
+
49
+ it('should automatically use filesystem storage as default', () => {
50
+ expect(cofhesdkClient.config.fheKeyStorage).toBeDefined();
51
+ expect(cofhesdkClient.config.fheKeyStorage).not.toBeNull();
52
+ });
53
+
54
+ it('should have all expected methods', () => {
55
+ expect(typeof cofhesdkClient.connect).toBe('function');
56
+ expect(typeof cofhesdkClient.encryptInputs).toBe('function');
57
+ expect(typeof cofhesdkClient.decryptHandle).toBe('function');
58
+ expect(typeof cofhesdkClient.getSnapshot).toBe('function');
59
+ expect(typeof cofhesdkClient.subscribe).toBe('function');
60
+ });
61
+ });
62
+
63
+ describe('Environment', () => {
64
+ it('should have the correct environment', () => {
65
+ expect(cofhesdkClient.config.environment).toBe('node');
66
+ });
67
+ });
68
+
69
+ describe('Real Connection', () => {
70
+ it('should connect to real chain', async () => {
71
+ await cofhesdkClient.connect(publicClient, walletClient);
72
+
73
+ expect(cofhesdkClient.connected).toBe(true);
74
+
75
+ const snapshot = cofhesdkClient.getSnapshot();
76
+ expect(snapshot.connected).toBe(true);
77
+ expect(snapshot.chainId).toBe(cofhesdkArbSepolia.id);
78
+ expect(snapshot.account).toBe(TEST_ACCOUNT);
79
+ }, 30000);
80
+
81
+ it('should handle real network errors', async () => {
82
+ try {
83
+ await cofhesdkClient.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(CofhesdkError);
91
+ expect((error as CofhesdkError).code).toBe(CofhesdkErrorCode.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 = cofhesdkClient.subscribe((snapshot) => {
100
+ states.push({ ...snapshot });
101
+ });
102
+
103
+ await cofhesdkClient.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(cofhesdkArbSepolia.id);
120
+ }, 30000);
121
+ });
122
+
123
+ describe('Builder Creation', () => {
124
+ it('should create encrypt builder after connection', async () => {
125
+ await cofhesdkClient.connect(publicClient, walletClient);
126
+
127
+ const builder = cofhesdkClient.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.encrypt).toBe('function');
134
+ }, 30000);
135
+
136
+ it('should create decrypt builder after connection', async () => {
137
+ await cofhesdkClient.connect(publicClient, walletClient);
138
+
139
+ const builder = cofhesdkClient.decryptHandle(123n, 2);
140
+
141
+ expect(builder).toBeDefined();
142
+ expect(typeof builder.setChainId).toBe('function');
143
+ expect(typeof builder.setAccount).toBe('function');
144
+ expect(typeof builder.decrypt).toBe('function');
145
+ }, 30000);
146
+ });
147
+ });