@cofhe/sdk 0.1.1 → 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 (107) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/adapters/ethers6.ts +28 -28
  3. package/adapters/hardhat.ts +0 -1
  4. package/adapters/index.test.ts +14 -19
  5. package/adapters/smartWallet.ts +81 -73
  6. package/adapters/test-utils.ts +45 -45
  7. package/adapters/types.ts +3 -3
  8. package/chains/chains/localcofhe.ts +14 -0
  9. package/chains/chains.test.ts +2 -1
  10. package/chains/defineChain.ts +2 -2
  11. package/chains/index.ts +3 -1
  12. package/chains/types.ts +3 -3
  13. package/core/baseBuilder.ts +30 -49
  14. package/core/client.test.ts +200 -72
  15. package/core/client.ts +152 -148
  16. package/core/clientTypes.ts +114 -0
  17. package/core/config.test.ts +30 -11
  18. package/core/config.ts +26 -13
  19. package/core/consts.ts +18 -0
  20. package/core/decrypt/cofheMocksSealOutput.ts +2 -4
  21. package/core/decrypt/decryptHandleBuilder.ts +51 -45
  22. package/core/decrypt/{tnSealOutput.ts → tnSealOutputV1.ts} +1 -1
  23. package/core/decrypt/tnSealOutputV2.ts +298 -0
  24. package/core/encrypt/cofheMocksZkVerifySign.ts +15 -16
  25. package/core/encrypt/encryptInputsBuilder.test.ts +132 -116
  26. package/core/encrypt/encryptInputsBuilder.ts +159 -111
  27. package/core/encrypt/encryptUtils.ts +6 -3
  28. package/core/encrypt/zkPackProveVerify.ts +70 -8
  29. package/core/error.ts +0 -2
  30. package/core/fetchKeys.test.ts +1 -18
  31. package/core/fetchKeys.ts +0 -26
  32. package/core/index.ts +37 -17
  33. package/core/keyStore.ts +65 -38
  34. package/core/permits.test.ts +255 -4
  35. package/core/permits.ts +83 -18
  36. package/core/types.ts +198 -152
  37. package/core/utils.ts +43 -1
  38. package/dist/adapters.d.cts +38 -20
  39. package/dist/adapters.d.ts +38 -20
  40. package/dist/chains.cjs +18 -8
  41. package/dist/chains.d.cts +31 -9
  42. package/dist/chains.d.ts +31 -9
  43. package/dist/chains.js +1 -1
  44. package/dist/{chunk-KFGPTJ6X.js → chunk-I5WFEYXX.js} +1768 -1526
  45. package/dist/{chunk-LU7BMUUT.js → chunk-R3B5TMVX.js} +330 -197
  46. package/dist/{chunk-GZCQQYVI.js → chunk-TBLR7NNE.js} +18 -9
  47. package/dist/{types-PhwGgQvs.d.ts → clientTypes-RqkgkV2i.d.ts} +331 -429
  48. package/dist/{types-bB7wLj0q.d.cts → clientTypes-e4filDzK.d.cts} +331 -429
  49. package/dist/core.cjs +3000 -2625
  50. package/dist/core.d.cts +113 -7
  51. package/dist/core.d.ts +113 -7
  52. package/dist/core.js +3 -3
  53. package/dist/node.cjs +2851 -2526
  54. package/dist/node.d.cts +4 -4
  55. package/dist/node.d.ts +4 -4
  56. package/dist/node.js +4 -3
  57. package/dist/{permit-S9CnI6MF.d.cts → permit-MZ502UBl.d.cts} +54 -41
  58. package/dist/{permit-S9CnI6MF.d.ts → permit-MZ502UBl.d.ts} +54 -41
  59. package/dist/permits.cjs +328 -195
  60. package/dist/permits.d.cts +113 -825
  61. package/dist/permits.d.ts +113 -825
  62. package/dist/permits.js +1 -1
  63. package/dist/types-YiAC4gig.d.cts +33 -0
  64. package/dist/types-YiAC4gig.d.ts +33 -0
  65. package/dist/web.cjs +3067 -2527
  66. package/dist/web.d.cts +22 -6
  67. package/dist/web.d.ts +22 -6
  68. package/dist/web.js +185 -9
  69. package/dist/zkProve.worker.cjs +93 -0
  70. package/dist/zkProve.worker.d.cts +2 -0
  71. package/dist/zkProve.worker.d.ts +2 -0
  72. package/dist/zkProve.worker.js +91 -0
  73. package/node/client.test.ts +20 -25
  74. package/node/encryptInputs.test.ts +18 -38
  75. package/node/index.ts +1 -0
  76. package/package.json +15 -15
  77. package/permits/index.ts +1 -0
  78. package/permits/localstorage.test.ts +9 -14
  79. package/permits/onchain-utils.ts +221 -0
  80. package/permits/permit.test.ts +76 -27
  81. package/permits/permit.ts +58 -95
  82. package/permits/sealing.test.ts +3 -3
  83. package/permits/sealing.ts +2 -2
  84. package/permits/store.test.ts +10 -50
  85. package/permits/store.ts +9 -21
  86. package/permits/test-utils.ts +11 -3
  87. package/permits/types.ts +39 -9
  88. package/permits/utils.ts +0 -5
  89. package/permits/validation.test.ts +29 -32
  90. package/permits/validation.ts +114 -176
  91. package/web/client.web.test.ts +20 -25
  92. package/web/config.web.test.ts +0 -2
  93. package/web/encryptInputs.web.test.ts +31 -54
  94. package/web/index.ts +65 -1
  95. package/web/storage.ts +19 -5
  96. package/web/worker.builder.web.test.ts +148 -0
  97. package/web/worker.config.web.test.ts +329 -0
  98. package/web/worker.output.web.test.ts +84 -0
  99. package/web/workerManager.test.ts +80 -0
  100. package/web/workerManager.ts +214 -0
  101. package/web/workerManager.web.test.ts +114 -0
  102. package/web/zkProve.worker.ts +133 -0
  103. package/core/result.test.ts +0 -180
  104. package/core/result.ts +0 -67
  105. package/core/test-utils.ts +0 -45
  106. package/dist/types-KImPrEIe.d.cts +0 -48
  107. package/dist/types-KImPrEIe.d.ts +0 -48
@@ -1,10 +1,10 @@
1
- import { hardhat } from './chunk-GZCQQYVI.js';
2
- import { permitStore, PermitUtils } from './chunk-LU7BMUUT.js';
1
+ import { hardhat as hardhat$1 } from './chunk-TBLR7NNE.js';
2
+ import { permitStore, PermitUtils, MOCKS_QUERY_DECRYPTER_ADDRESS, MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY, MOCKS_ZK_VERIFIER_ADDRESS } from './chunk-R3B5TMVX.js';
3
3
  import { createStore } from 'zustand/vanilla';
4
- import { getAddress, http, createWalletClient, encodePacked, keccak256, toBytes, hashMessage } from 'viem';
5
- import { z } from 'zod';
6
- import { hardhat as hardhat$1 } from 'viem/chains';
4
+ import { createWalletClient, http, encodePacked, keccak256, toBytes, hashMessage, getAddress } from 'viem';
5
+ import { hardhat } from 'viem/chains';
7
6
  import { privateKeyToAccount } from 'viem/accounts';
7
+ import { z } from 'zod';
8
8
  import { persist, createJSONStorage } from 'zustand/middleware';
9
9
  import { produce } from 'immer';
10
10
 
@@ -143,250 +143,123 @@ var bigintSafeJsonStringify = (value) => {
143
143
  };
144
144
  var isCofhesdkError = (error) => error instanceof CofhesdkError;
145
145
 
146
- // core/result.ts
147
- var ResultErr = (error) => ({
148
- success: false,
149
- data: null,
150
- error
151
- });
152
- var ResultOk = (data) => ({
153
- success: true,
154
- data,
155
- error: null
156
- });
157
- var ResultErrOrInternal = (error) => {
158
- return ResultErr(CofhesdkError.fromError(error));
159
- };
160
- var ResultHttpError = (error, url, status) => {
161
- if (error instanceof CofhesdkError)
162
- return error;
163
- const message = status ? `HTTP error ${status} from ${url}` : `HTTP request failed for ${url}`;
164
- return new CofhesdkError({
165
- code: "INTERNAL_ERROR" /* InternalError */,
166
- message,
167
- cause: error instanceof Error ? error : void 0
168
- });
169
- };
170
- var ResultValidationError = (message) => {
171
- return new CofhesdkError({
172
- code: "INVALID_PERMIT_DATA" /* InvalidPermitData */,
173
- message
174
- });
175
- };
176
- var resultWrapper = async (tryFn, catchFn, finallyFn) => {
177
- try {
178
- const result = await tryFn();
179
- return ResultOk(result);
180
- } catch (error) {
181
- const result = ResultErrOrInternal(error);
182
- catchFn?.(result.error);
183
- return result;
184
- } finally {
185
- finallyFn?.();
186
- }
187
- };
188
- var resultWrapperSync = (fn) => {
189
- try {
190
- const result = fn();
191
- return ResultOk(result);
192
- } catch (error) {
193
- return ResultErrOrInternal(error);
194
- }
195
- };
196
- var storeActivePermit = async (permit, publicClient, walletClient) => {
197
- const chainId = await publicClient.getChainId();
198
- const account = walletClient.account.address;
199
- permitStore.setPermit(chainId, account, permit);
200
- permitStore.setActivePermitHash(chainId, account, PermitUtils.getHash(permit));
201
- };
202
- var createPermitWithSign = async (options, publicClient, walletClient, permitMethod) => {
203
- const permit = await permitMethod(options, publicClient, walletClient);
204
- await storeActivePermit(permit, publicClient, walletClient);
205
- return permit;
206
- };
207
- var createSelf = async (options, publicClient, walletClient) => {
208
- return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSelfAndSign);
209
- };
210
- var createSharing = async (options, publicClient, walletClient) => {
211
- return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSharingAndSign);
212
- };
213
- var importShared = async (options, publicClient, walletClient) => {
214
- return createPermitWithSign(options, publicClient, walletClient, PermitUtils.importSharedAndSign);
215
- };
216
- var getHash = (permit) => {
217
- return PermitUtils.getHash(permit);
218
- };
219
- var serialize = (permit) => {
220
- return PermitUtils.serialize(permit);
221
- };
222
- var deserialize = (serialized) => {
223
- return PermitUtils.deserialize(serialized);
224
- };
225
- var getPermit = async (chainId, account, hash) => {
226
- return permitStore.getPermit(chainId, account, hash);
227
- };
228
- var getPermits = async (chainId, account) => {
229
- return permitStore.getPermits(chainId, account);
230
- };
231
- var getActivePermit = async (chainId, account) => {
232
- return permitStore.getActivePermit(chainId, account);
233
- };
234
- var getActivePermitHash = async (chainId, account) => {
235
- return permitStore.getActivePermitHash(chainId, account);
236
- };
237
- var selectActivePermit = async (chainId, account, hash) => {
238
- await permitStore.setActivePermitHash(chainId, account, hash);
239
- };
240
- var removePermit = async (chainId, account, hash) => {
241
- await permitStore.removePermit(chainId, account, hash);
242
- };
243
- var removeActivePermit = async (chainId, account) => {
244
- await permitStore.removeActivePermitHash(chainId, account);
245
- };
246
- var permits = {
247
- getSnapshot: permitStore.store.getState,
248
- subscribe: permitStore.store.subscribe,
249
- createSelf,
250
- createSharing,
251
- importShared,
252
- getHash,
253
- serialize,
254
- deserialize,
255
- getPermit,
256
- getPermits,
257
- getActivePermit,
258
- getActivePermitHash,
259
- removePermit,
260
- selectActivePermit,
261
- removeActivePermit
262
- };
263
- function uint160ToAddress(uint160) {
264
- const hexStr = uint160.toString(16).padStart(40, "0");
265
- return getAddress("0x" + hexStr);
146
+ // core/types.ts
147
+ var FheTypes = /* @__PURE__ */ ((FheTypes2) => {
148
+ FheTypes2[FheTypes2["Bool"] = 0] = "Bool";
149
+ FheTypes2[FheTypes2["Uint4"] = 1] = "Uint4";
150
+ FheTypes2[FheTypes2["Uint8"] = 2] = "Uint8";
151
+ FheTypes2[FheTypes2["Uint16"] = 3] = "Uint16";
152
+ FheTypes2[FheTypes2["Uint32"] = 4] = "Uint32";
153
+ FheTypes2[FheTypes2["Uint64"] = 5] = "Uint64";
154
+ FheTypes2[FheTypes2["Uint128"] = 6] = "Uint128";
155
+ FheTypes2[FheTypes2["Uint160"] = 7] = "Uint160";
156
+ FheTypes2[FheTypes2["Uint256"] = 8] = "Uint256";
157
+ FheTypes2[FheTypes2["Uint512"] = 9] = "Uint512";
158
+ FheTypes2[FheTypes2["Uint1024"] = 10] = "Uint1024";
159
+ FheTypes2[FheTypes2["Uint2048"] = 11] = "Uint2048";
160
+ FheTypes2[FheTypes2["Uint2"] = 12] = "Uint2";
161
+ FheTypes2[FheTypes2["Uint6"] = 13] = "Uint6";
162
+ FheTypes2[FheTypes2["Uint10"] = 14] = "Uint10";
163
+ FheTypes2[FheTypes2["Uint12"] = 15] = "Uint12";
164
+ FheTypes2[FheTypes2["Uint14"] = 16] = "Uint14";
165
+ FheTypes2[FheTypes2["Int2"] = 17] = "Int2";
166
+ FheTypes2[FheTypes2["Int4"] = 18] = "Int4";
167
+ FheTypes2[FheTypes2["Int6"] = 19] = "Int6";
168
+ FheTypes2[FheTypes2["Int8"] = 20] = "Int8";
169
+ FheTypes2[FheTypes2["Int10"] = 21] = "Int10";
170
+ FheTypes2[FheTypes2["Int12"] = 22] = "Int12";
171
+ FheTypes2[FheTypes2["Int14"] = 23] = "Int14";
172
+ FheTypes2[FheTypes2["Int16"] = 24] = "Int16";
173
+ FheTypes2[FheTypes2["Int32"] = 25] = "Int32";
174
+ FheTypes2[FheTypes2["Int64"] = 26] = "Int64";
175
+ FheTypes2[FheTypes2["Int128"] = 27] = "Int128";
176
+ FheTypes2[FheTypes2["Int160"] = 28] = "Int160";
177
+ FheTypes2[FheTypes2["Int256"] = 29] = "Int256";
178
+ return FheTypes2;
179
+ })(FheTypes || {});
180
+ var FheUintUTypes = [
181
+ 2 /* Uint8 */,
182
+ 3 /* Uint16 */,
183
+ 4 /* Uint32 */,
184
+ 5 /* Uint64 */,
185
+ 6 /* Uint128 */
186
+ // [U256-DISABLED]
187
+ // FheTypes.Uint256,
188
+ ];
189
+ var FheAllUTypes = [
190
+ 0 /* Bool */,
191
+ 2 /* Uint8 */,
192
+ 3 /* Uint16 */,
193
+ 4 /* Uint32 */,
194
+ 5 /* Uint64 */,
195
+ 6 /* Uint128 */,
196
+ // [U256-DISABLED]
197
+ // FheTypes.Uint256,
198
+ 7 /* Uint160 */
199
+ ];
200
+ function assertCorrectEncryptedItemInput(input) {
201
+ if (!input.signature.startsWith("0x"))
202
+ throw new Error("Signature must be a hex string starting with 0x");
266
203
  }
267
- var isValidUtype = (utype) => {
268
- return utype === 0 /* Bool */ || utype === 7 /* Uint160 */ || utype == null || FheUintUTypes.includes(utype);
269
- };
270
- var convertViaUtype = (utype, value) => {
271
- if (utype === 0 /* Bool */) {
272
- return !!value;
273
- } else if (utype === 7 /* Uint160 */) {
274
- return uint160ToAddress(value);
275
- } else if (utype == null || FheUintUTypes.includes(utype)) {
276
- return value;
277
- } else {
278
- throw new Error(`convertViaUtype :: invalid utype :: ${utype}`);
279
- }
204
+ var EncryptableFactoriesImpl = {
205
+ bool: (data, securityZone = 0) => ({ data, securityZone, utype: 0 /* Bool */ }),
206
+ address: (data, securityZone = 0) => ({ data, securityZone, utype: 7 /* Uint160 */ }),
207
+ uint8: (data, securityZone = 0) => ({ data, securityZone, utype: 2 /* Uint8 */ }),
208
+ uint16: (data, securityZone = 0) => ({ data, securityZone, utype: 3 /* Uint16 */ }),
209
+ uint32: (data, securityZone = 0) => ({ data, securityZone, utype: 4 /* Uint32 */ }),
210
+ uint64: (data, securityZone = 0) => ({ data, securityZone, utype: 5 /* Uint64 */ }),
211
+ uint128: (data, securityZone = 0) => ({ data, securityZone, utype: 6 /* Uint128 */ })
212
+ // [U256-DISABLED]
213
+ // uint256: (data: EncryptableUint256['data'], securityZone = 0) =>
214
+ // ({ data, securityZone, utype: FheTypes.Uint256 }) as EncryptableUint256,
280
215
  };
281
- var BaseBuilder = class {
282
- config;
283
- publicClient;
284
- walletClient;
285
- chainId;
286
- account;
287
- requireConnected;
288
- constructor(params) {
289
- this.config = params.config;
290
- this.publicClient = params.publicClient;
291
- this.walletClient = params.walletClient;
292
- this.chainId = params.chainId;
293
- this.account = params.account;
294
- this.requireConnected = params.requireConnected;
295
- }
296
- /**
297
- * Gets the chain ID from the instance or fetches it from the public client
298
- * @returns The chain ID
299
- * @throws {CofhesdkError} If chainId is not set and publicClient is not available
300
- */
301
- async getChainIdOrThrow() {
302
- if (this.chainId)
303
- return this.chainId;
304
- throw new CofhesdkError({
305
- code: "CHAIN_ID_UNINITIALIZED" /* ChainIdUninitialized */,
306
- message: "Chain ID is not set",
307
- hint: "Ensure client.connect() has been called and awaited, or use setChainId(...) to set the chainId explicitly.",
308
- context: {
309
- chainId: this.chainId
310
- }
311
- });
312
- }
313
- /**
314
- * Gets the account address from the instance or fetches it from the wallet client
315
- * @returns The account address
316
- * @throws {CofhesdkError} If account is not set and walletClient is not available
317
- */
318
- async getAccountOrThrow() {
319
- if (this.account)
320
- return this.account;
321
- throw new CofhesdkError({
322
- code: "ACCOUNT_UNINITIALIZED" /* AccountUninitialized */,
323
- message: "Account is not set",
324
- hint: "Ensure client.connect() has been called and awaited, or use setAccount(...) to set the account explicitly.",
325
- context: {
326
- account: this.account
327
- }
328
- });
329
- }
330
- /**
331
- * Gets the config or throws an error if not available
332
- * @returns The config
333
- * @throws {CofhesdkError} If config is not set
334
- */
335
- getConfigOrThrow() {
336
- if (this.config)
337
- return this.config;
338
- throw new CofhesdkError({
339
- code: "MISSING_CONFIG" /* MissingConfig */,
340
- message: "Builder config is undefined",
341
- hint: "Ensure client has been created with a config.",
342
- context: {
343
- config: this.config
344
- }
345
- });
346
- }
347
- /**
348
- * Gets the public client or throws an error if not available
349
- * @returns The public client
350
- * @throws {CofhesdkError} If publicClient is not set
351
- */
352
- getPublicClientOrThrow() {
353
- if (this.publicClient)
354
- return this.publicClient;
355
- throw new CofhesdkError({
356
- code: "MISSING_PUBLIC_CLIENT" /* MissingPublicClient */,
357
- message: "Public client not found",
358
- hint: "Ensure client.connect() has been called with a publicClient.",
359
- context: {
360
- publicClient: this.publicClient
361
- }
362
- });
363
- }
364
- /**
365
- * Gets the wallet client or throws an error if not available
366
- * @returns The wallet client
367
- * @throws {CofhesdkError} If walletClient is not set
368
- */
369
- getWalletClientOrThrow() {
370
- if (this.walletClient)
371
- return this.walletClient;
372
- throw new CofhesdkError({
373
- code: "MISSING_WALLET_CLIENT" /* MissingWalletClient */,
374
- message: "Wallet client not found",
375
- hint: "Ensure client.connect() has been called with a walletClient.",
376
- context: {
377
- walletClient: this.walletClient
378
- }
379
- });
380
- }
381
- /**
382
- * Requires the client to be connected
383
- * @throws {CofhesdkError} If client is not connected
384
- */
385
- requireConnectedOrThrow() {
386
- if (this.requireConnected)
387
- this.requireConnected();
216
+ function createEncryptableByLiteral(type, data, securityZone = 0) {
217
+ switch (type) {
218
+ case "bool": {
219
+ if (typeof data !== "boolean")
220
+ throw new Error("Bool encryptable data must be boolean");
221
+ return EncryptableFactoriesImpl.bool(data, securityZone);
222
+ }
223
+ case "address":
224
+ case "uint8":
225
+ case "uint16":
226
+ case "uint32":
227
+ case "uint64":
228
+ case "uint128": {
229
+ if (typeof data === "boolean")
230
+ throw new Error("Uint encryptable data must be string or bigint");
231
+ return EncryptableFactoriesImpl[type](data, securityZone);
232
+ }
233
+ default: {
234
+ const _exhaustive = type;
235
+ throw new Error(`Unsupported encryptable type: ${_exhaustive}`);
236
+ }
388
237
  }
238
+ }
239
+ var Encryptable = {
240
+ ...EncryptableFactoriesImpl,
241
+ create: createEncryptableByLiteral
389
242
  };
243
+ function isEncryptableItem(value) {
244
+ return (
245
+ // Is object and exists
246
+ typeof value === "object" && value !== null && // Has securityZone
247
+ "securityZone" in value && typeof value.securityZone === "number" && // Has utype
248
+ "utype" in value && FheAllUTypes.includes(value.utype) && // Has data
249
+ "data" in value && ["string", "number", "bigint", "boolean"].includes(typeof value.data)
250
+ );
251
+ }
252
+ var EncryptStep = /* @__PURE__ */ ((EncryptStep2) => {
253
+ EncryptStep2["InitTfhe"] = "initTfhe";
254
+ EncryptStep2["FetchKeys"] = "fetchKeys";
255
+ EncryptStep2["Pack"] = "pack";
256
+ EncryptStep2["Prove"] = "prove";
257
+ EncryptStep2["Verify"] = "verify";
258
+ return EncryptStep2;
259
+ })(EncryptStep || {});
260
+ function isLastEncryptionStep(step) {
261
+ return step === "verify" /* Verify */;
262
+ }
390
263
  var toHexString = (bytes) => bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
391
264
  var toBigIntOrThrow = (value) => {
392
265
  if (typeof value === "bigint") {
@@ -455,23 +328,211 @@ async function getWalletClientAccount(walletClient) {
455
328
  }
456
329
  return address;
457
330
  }
331
+ function fheTypeToString(utype) {
332
+ switch (utype) {
333
+ case 0 /* Bool */:
334
+ return "bool";
335
+ case 1 /* Uint4 */:
336
+ return "uint4";
337
+ case 2 /* Uint8 */:
338
+ return "uint8";
339
+ case 3 /* Uint16 */:
340
+ return "uint16";
341
+ case 4 /* Uint32 */:
342
+ return "uint32";
343
+ case 5 /* Uint64 */:
344
+ return "uint64";
345
+ case 6 /* Uint128 */:
346
+ return "uint128";
347
+ case 7 /* Uint160 */:
348
+ return "uint160";
349
+ case 8 /* Uint256 */:
350
+ return "uint256";
351
+ case 9 /* Uint512 */:
352
+ return "uint512";
353
+ case 10 /* Uint1024 */:
354
+ return "uint1024";
355
+ case 11 /* Uint2048 */:
356
+ return "uint2048";
357
+ case 12 /* Uint2 */:
358
+ return "uint2";
359
+ case 13 /* Uint6 */:
360
+ return "uint6";
361
+ case 14 /* Uint10 */:
362
+ return "uint10";
363
+ default:
364
+ throw new Error(`Unknown FheType: ${utype}`);
365
+ }
366
+ }
458
367
 
459
- // core/decrypt/MockQueryDecrypterAbi.ts
460
- var MockQueryDecrypterAbi = [
461
- {
462
- type: "function",
463
- name: "acl",
464
- inputs: [],
465
- outputs: [{ name: "", type: "address", internalType: "contract ACL" }],
466
- stateMutability: "view"
467
- },
468
- {
469
- type: "function",
470
- name: "decodeLowLevelReversion",
471
- inputs: [{ name: "data", type: "bytes", internalType: "bytes" }],
472
- outputs: [{ name: "error", type: "string", internalType: "string" }],
473
- stateMutability: "pure"
474
- },
368
+ // core/encrypt/zkPackProveVerify.ts
369
+ var MAX_UINT8 = 255n;
370
+ var MAX_UINT16 = 65535n;
371
+ var MAX_UINT32 = 4294967295n;
372
+ var MAX_UINT64 = 18446744073709551615n;
373
+ var MAX_UINT128 = 340282366920938463463374607431768211455n;
374
+ var MAX_UINT160 = 1461501637330902918203684832716283019655932542975n;
375
+ var MAX_ENCRYPTABLE_BITS = 2048;
376
+ var zkPack = (items, builder) => {
377
+ let totalBits = 0;
378
+ for (const item of items) {
379
+ switch (item.utype) {
380
+ case 0 /* Bool */: {
381
+ builder.push_boolean(item.data);
382
+ totalBits += 1;
383
+ break;
384
+ }
385
+ case 2 /* Uint8 */: {
386
+ const bint = toBigIntOrThrow(item.data);
387
+ validateBigIntInRange(bint, MAX_UINT8);
388
+ builder.push_u8(parseInt(bint.toString()));
389
+ totalBits += 8;
390
+ break;
391
+ }
392
+ case 3 /* Uint16 */: {
393
+ const bint = toBigIntOrThrow(item.data);
394
+ validateBigIntInRange(bint, MAX_UINT16);
395
+ builder.push_u16(parseInt(bint.toString()));
396
+ totalBits += 16;
397
+ break;
398
+ }
399
+ case 4 /* Uint32 */: {
400
+ const bint = toBigIntOrThrow(item.data);
401
+ validateBigIntInRange(bint, MAX_UINT32);
402
+ builder.push_u32(parseInt(bint.toString()));
403
+ totalBits += 32;
404
+ break;
405
+ }
406
+ case 5 /* Uint64 */: {
407
+ const bint = toBigIntOrThrow(item.data);
408
+ validateBigIntInRange(bint, MAX_UINT64);
409
+ builder.push_u64(bint);
410
+ totalBits += 64;
411
+ break;
412
+ }
413
+ case 6 /* Uint128 */: {
414
+ const bint = toBigIntOrThrow(item.data);
415
+ validateBigIntInRange(bint, MAX_UINT128);
416
+ builder.push_u128(bint);
417
+ totalBits += 128;
418
+ break;
419
+ }
420
+ case 7 /* Uint160 */: {
421
+ const bint = toBigIntOrThrow(item.data);
422
+ validateBigIntInRange(bint, MAX_UINT160);
423
+ builder.push_u160(bint);
424
+ totalBits += 160;
425
+ break;
426
+ }
427
+ default: {
428
+ throw new CofhesdkError({
429
+ code: "ZK_PACK_FAILED" /* ZkPackFailed */,
430
+ message: `Invalid utype: ${item.utype}`,
431
+ hint: `Ensure that the utype is valid, using the Encryptable type, for example: Encryptable.uint128(100n)`,
432
+ context: {
433
+ item
434
+ }
435
+ });
436
+ }
437
+ }
438
+ }
439
+ if (totalBits > MAX_ENCRYPTABLE_BITS) {
440
+ throw new CofhesdkError({
441
+ code: "ZK_PACK_FAILED" /* ZkPackFailed */,
442
+ message: `Total bits ${totalBits} exceeds ${MAX_ENCRYPTABLE_BITS}`,
443
+ hint: `Ensure that the total bits of the items to encrypt does not exceed ${MAX_ENCRYPTABLE_BITS}`,
444
+ context: {
445
+ totalBits,
446
+ maxBits: MAX_ENCRYPTABLE_BITS,
447
+ items
448
+ }
449
+ });
450
+ }
451
+ return builder;
452
+ };
453
+ var zkProveWithWorker = async (workerFn, fheKeyHex, crsHex, items, metadata) => {
454
+ return await workerFn(fheKeyHex, crsHex, items, metadata);
455
+ };
456
+ var zkProve = async (builder, crs, metadata) => {
457
+ return new Promise((resolve) => {
458
+ setTimeout(() => {
459
+ const compactList = builder.build_with_proof_packed(
460
+ crs,
461
+ metadata,
462
+ 1
463
+ // ZkComputeLoad.Verify
464
+ );
465
+ resolve(compactList.serialize());
466
+ }, 0);
467
+ });
468
+ };
469
+ var constructZkPoKMetadata = (accountAddr, securityZone, chainId) => {
470
+ const accountAddrNoPrefix = accountAddr.startsWith("0x") ? accountAddr.slice(2) : accountAddr;
471
+ const accountBytes = hexToBytes(accountAddrNoPrefix);
472
+ const chainIdBytes = new Uint8Array(32);
473
+ let value = chainId;
474
+ for (let i = 31; i >= 0 && value > 0; i--) {
475
+ chainIdBytes[i] = value & 255;
476
+ value = value >>> 8;
477
+ }
478
+ const metadata = new Uint8Array(1 + accountBytes.length + 32);
479
+ metadata[0] = securityZone;
480
+ metadata.set(accountBytes, 1);
481
+ metadata.set(chainIdBytes, 1 + accountBytes.length);
482
+ return metadata;
483
+ };
484
+ var zkVerify = async (verifierUrl, serializedBytes, address, securityZone, chainId) => {
485
+ const packed_list = toHexString(serializedBytes);
486
+ const sz_byte = new Uint8Array([securityZone]);
487
+ const payload = {
488
+ packed_list,
489
+ account_addr: address,
490
+ security_zone: sz_byte[0],
491
+ chain_id: chainId
492
+ };
493
+ const body = JSON.stringify(payload);
494
+ try {
495
+ const response = await fetch(`${verifierUrl}/verify`, {
496
+ method: "POST",
497
+ headers: {
498
+ "Content-Type": "application/json"
499
+ },
500
+ body
501
+ });
502
+ if (!response.ok) {
503
+ const errorBody = await response.text();
504
+ throw new CofhesdkError({
505
+ code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
506
+ message: `HTTP error! ZK proof verification failed - ${errorBody}`
507
+ });
508
+ }
509
+ const json = await response.json();
510
+ if (json.status !== "success") {
511
+ throw new CofhesdkError({
512
+ code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
513
+ message: `ZK proof verification response malformed - ${json.error}`
514
+ });
515
+ }
516
+ return json.data.map(({ ct_hash, signature, recid }) => {
517
+ return {
518
+ ct_hash,
519
+ signature: concatSigRecid(signature, recid)
520
+ };
521
+ });
522
+ } catch (e) {
523
+ throw new CofhesdkError({
524
+ code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
525
+ message: `ZK proof verification failed`,
526
+ cause: e instanceof Error ? e : void 0
527
+ });
528
+ }
529
+ };
530
+ var concatSigRecid = (signature, recid) => {
531
+ return signature + (recid + 27).toString(16).padStart(2, "0");
532
+ };
533
+
534
+ // core/encrypt/MockZkVerifierAbi.ts
535
+ var MockZkVerifierAbi = [
475
536
  {
476
537
  type: "function",
477
538
  name: "exists",
@@ -481,943 +542,670 @@ var MockQueryDecrypterAbi = [
481
542
  },
482
543
  {
483
544
  type: "function",
484
- name: "initialize",
545
+ name: "insertCtHash",
485
546
  inputs: [
486
- { name: "_taskManager", type: "address", internalType: "address" },
487
- { name: "_acl", type: "address", internalType: "address" }
547
+ { name: "ctHash", type: "uint256", internalType: "uint256" },
548
+ { name: "value", type: "uint256", internalType: "uint256" }
488
549
  ],
489
550
  outputs: [],
490
551
  stateMutability: "nonpayable"
491
552
  },
492
553
  {
493
554
  type: "function",
494
- name: "queryDecrypt",
555
+ name: "insertPackedCtHashes",
495
556
  inputs: [
496
- { name: "ctHash", type: "uint256", internalType: "uint256" },
497
- { name: "", type: "uint256", internalType: "uint256" },
498
- {
499
- name: "permission",
500
- type: "tuple",
501
- internalType: "struct Permission",
502
- components: [
503
- { name: "issuer", type: "address", internalType: "address" },
504
- { name: "expiration", type: "uint64", internalType: "uint64" },
505
- { name: "recipient", type: "address", internalType: "address" },
506
- { name: "validatorId", type: "uint256", internalType: "uint256" },
507
- {
508
- name: "validatorContract",
509
- type: "address",
510
- internalType: "address"
511
- },
512
- { name: "sealingKey", type: "bytes32", internalType: "bytes32" },
513
- { name: "issuerSignature", type: "bytes", internalType: "bytes" },
514
- { name: "recipientSignature", type: "bytes", internalType: "bytes" }
515
- ]
516
- }
517
- ],
518
- outputs: [
519
- { name: "allowed", type: "bool", internalType: "bool" },
520
- { name: "error", type: "string", internalType: "string" },
521
- { name: "", type: "uint256", internalType: "uint256" }
557
+ { name: "ctHashes", type: "uint256[]", internalType: "uint256[]" },
558
+ { name: "values", type: "uint256[]", internalType: "uint256[]" }
522
559
  ],
523
- stateMutability: "view"
560
+ outputs: [],
561
+ stateMutability: "nonpayable"
524
562
  },
525
563
  {
526
564
  type: "function",
527
- name: "querySealOutput",
565
+ name: "zkVerify",
528
566
  inputs: [
529
- { name: "ctHash", type: "uint256", internalType: "uint256" },
530
- { name: "", type: "uint256", internalType: "uint256" },
567
+ { name: "value", type: "uint256", internalType: "uint256" },
568
+ { name: "utype", type: "uint8", internalType: "uint8" },
569
+ { name: "user", type: "address", internalType: "address" },
570
+ { name: "securityZone", type: "uint8", internalType: "uint8" },
571
+ { name: "", type: "uint256", internalType: "uint256" }
572
+ ],
573
+ outputs: [
531
574
  {
532
- name: "permission",
575
+ name: "",
533
576
  type: "tuple",
534
- internalType: "struct Permission",
577
+ internalType: "struct EncryptedInput",
535
578
  components: [
536
- { name: "issuer", type: "address", internalType: "address" },
537
- { name: "expiration", type: "uint64", internalType: "uint64" },
538
- { name: "recipient", type: "address", internalType: "address" },
539
- { name: "validatorId", type: "uint256", internalType: "uint256" },
540
- {
541
- name: "validatorContract",
542
- type: "address",
543
- internalType: "address"
544
- },
545
- { name: "sealingKey", type: "bytes32", internalType: "bytes32" },
546
- { name: "issuerSignature", type: "bytes", internalType: "bytes" },
547
- { name: "recipientSignature", type: "bytes", internalType: "bytes" }
579
+ { name: "ctHash", type: "uint256", internalType: "uint256" },
580
+ { name: "securityZone", type: "uint8", internalType: "uint8" },
581
+ { name: "utype", type: "uint8", internalType: "uint8" },
582
+ { name: "signature", type: "bytes", internalType: "bytes" }
548
583
  ]
549
584
  }
550
585
  ],
551
- outputs: [
552
- { name: "allowed", type: "bool", internalType: "bool" },
553
- { name: "error", type: "string", internalType: "string" },
554
- { name: "", type: "bytes32", internalType: "bytes32" }
555
- ],
556
- stateMutability: "view"
586
+ stateMutability: "nonpayable"
557
587
  },
558
588
  {
559
589
  type: "function",
560
- name: "seal",
590
+ name: "zkVerifyCalcCtHash",
561
591
  inputs: [
562
- { name: "input", type: "uint256", internalType: "uint256" },
563
- { name: "key", type: "bytes32", internalType: "bytes32" }
592
+ { name: "value", type: "uint256", internalType: "uint256" },
593
+ { name: "utype", type: "uint8", internalType: "uint8" },
594
+ { name: "user", type: "address", internalType: "address" },
595
+ { name: "securityZone", type: "uint8", internalType: "uint8" },
596
+ { name: "", type: "uint256", internalType: "uint256" }
564
597
  ],
565
- outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
566
- stateMutability: "pure"
598
+ outputs: [{ name: "ctHash", type: "uint256", internalType: "uint256" }],
599
+ stateMutability: "view"
567
600
  },
568
601
  {
569
602
  type: "function",
570
- name: "taskManager",
571
- inputs: [],
572
- outputs: [{ name: "", type: "address", internalType: "contract TaskManager" }],
603
+ name: "zkVerifyCalcCtHashesPacked",
604
+ inputs: [
605
+ { name: "values", type: "uint256[]", internalType: "uint256[]" },
606
+ { name: "utypes", type: "uint8[]", internalType: "uint8[]" },
607
+ { name: "user", type: "address", internalType: "address" },
608
+ { name: "securityZone", type: "uint8", internalType: "uint8" },
609
+ { name: "chainId", type: "uint256", internalType: "uint256" }
610
+ ],
611
+ outputs: [{ name: "ctHashes", type: "uint256[]", internalType: "uint256[]" }],
573
612
  stateMutability: "view"
574
613
  },
575
614
  {
576
615
  type: "function",
577
- name: "unseal",
616
+ name: "zkVerifyPacked",
578
617
  inputs: [
579
- { name: "hashed", type: "bytes32", internalType: "bytes32" },
580
- { name: "key", type: "bytes32", internalType: "bytes32" }
618
+ { name: "values", type: "uint256[]", internalType: "uint256[]" },
619
+ { name: "utypes", type: "uint8[]", internalType: "uint8[]" },
620
+ { name: "user", type: "address", internalType: "address" },
621
+ { name: "securityZone", type: "uint8", internalType: "uint8" },
622
+ { name: "chainId", type: "uint256", internalType: "uint256" }
581
623
  ],
582
- outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
583
- stateMutability: "pure"
624
+ outputs: [
625
+ {
626
+ name: "inputs",
627
+ type: "tuple[]",
628
+ internalType: "struct EncryptedInput[]",
629
+ components: [
630
+ { name: "ctHash", type: "uint256", internalType: "uint256" },
631
+ { name: "securityZone", type: "uint8", internalType: "uint8" },
632
+ { name: "utype", type: "uint8", internalType: "uint8" },
633
+ { name: "signature", type: "bytes", internalType: "bytes" }
634
+ ]
635
+ }
636
+ ],
637
+ stateMutability: "nonpayable"
584
638
  },
585
- { type: "error", name: "NotAllowed", inputs: [] },
586
- { type: "error", name: "SealingKeyInvalid", inputs: [] },
587
- { type: "error", name: "SealingKeyMissing", inputs: [] }
639
+ { type: "error", name: "InvalidInputs", inputs: [] }
588
640
  ];
589
-
590
- // core/decrypt/cofheMocksSealOutput.ts
591
- var MockQueryDecrypterAddress = "0x0000000000000000000000000000000000000200";
592
- async function cofheMocksSealOutput(ctHash, utype, permit, publicClient, mocksSealOutputDelay) {
593
- if (mocksSealOutputDelay > 0)
594
- await sleep(mocksSealOutputDelay);
595
- const permission = PermitUtils.getPermission(permit, true);
596
- const permissionWithBigInts = {
597
- ...permission,
598
- expiration: BigInt(permission.expiration),
599
- validatorId: BigInt(permission.validatorId)
600
- };
601
- const [allowed, error, result] = await publicClient.readContract({
602
- address: MockQueryDecrypterAddress,
603
- abi: MockQueryDecrypterAbi,
604
- functionName: "querySealOutput",
605
- args: [ctHash, BigInt(utype), permissionWithBigInts]
641
+ function createMockZkVerifierSigner() {
642
+ return createWalletClient({
643
+ chain: hardhat,
644
+ transport: http(),
645
+ account: privateKeyToAccount(MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY)
606
646
  });
607
- if (error != "") {
608
- throw new CofhesdkError({
609
- code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
610
- message: `mocks querySealOutput call failed: ${error}`
611
- });
647
+ }
648
+ async function cofheMocksCheckEncryptableBits(items) {
649
+ let totalBits = 0;
650
+ for (const item of items) {
651
+ switch (item.utype) {
652
+ case 0 /* Bool */: {
653
+ totalBits += 1;
654
+ break;
655
+ }
656
+ case 2 /* Uint8 */: {
657
+ totalBits += 8;
658
+ break;
659
+ }
660
+ case 3 /* Uint16 */: {
661
+ totalBits += 16;
662
+ break;
663
+ }
664
+ case 4 /* Uint32 */: {
665
+ totalBits += 32;
666
+ break;
667
+ }
668
+ case 5 /* Uint64 */: {
669
+ totalBits += 64;
670
+ break;
671
+ }
672
+ case 6 /* Uint128 */: {
673
+ totalBits += 128;
674
+ break;
675
+ }
676
+ case 7 /* Uint160 */: {
677
+ totalBits += 160;
678
+ break;
679
+ }
680
+ }
612
681
  }
613
- if (allowed == false) {
682
+ if (totalBits > MAX_ENCRYPTABLE_BITS) {
614
683
  throw new CofhesdkError({
615
- code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
616
- message: `mocks querySealOutput call failed: ACL Access Denied (NotAllowed)`
684
+ code: "ZK_PACK_FAILED" /* ZkPackFailed */,
685
+ message: `Total bits ${totalBits} exceeds ${MAX_ENCRYPTABLE_BITS}`,
686
+ hint: `Ensure that the total bits of the items to encrypt does not exceed ${MAX_ENCRYPTABLE_BITS}`,
687
+ context: {
688
+ totalBits,
689
+ maxBits: MAX_ENCRYPTABLE_BITS,
690
+ items
691
+ }
617
692
  });
618
693
  }
619
- const sealedBigInt = BigInt(result);
620
- const sealingKeyBigInt = BigInt(permission.sealingKey);
621
- const unsealed = sealedBigInt ^ sealingKeyBigInt;
622
- return unsealed;
623
694
  }
624
-
625
- // core/decrypt/tnSealOutput.ts
626
- async function tnSealOutput(ctHash, chainId, permission, thresholdNetworkUrl) {
627
- let sealed;
628
- let errorMessage;
629
- let sealOutputResult;
630
- const body = {
631
- ct_tempkey: ctHash.toString(16).padStart(64, "0"),
632
- host_chain_id: chainId,
633
- permit: permission
634
- };
695
+ async function calcCtHashes(items, account, securityZone, publicClient) {
696
+ const calcCtHashesArgs = [
697
+ items.map(({ data }) => BigInt(data)),
698
+ items.map(({ utype }) => utype),
699
+ account,
700
+ securityZone,
701
+ BigInt(hardhat.id)
702
+ ];
703
+ let ctHashes;
635
704
  try {
636
- const sealOutputRes = await fetch(`${thresholdNetworkUrl}/sealoutput`, {
637
- method: "POST",
638
- headers: {
639
- "Content-Type": "application/json"
640
- },
641
- body: JSON.stringify(body)
705
+ ctHashes = await publicClient.readContract({
706
+ address: MOCKS_ZK_VERIFIER_ADDRESS,
707
+ abi: MockZkVerifierAbi,
708
+ functionName: "zkVerifyCalcCtHashesPacked",
709
+ args: calcCtHashesArgs
642
710
  });
643
- sealOutputResult = await sealOutputRes.json();
644
- sealed = sealOutputResult.sealed;
645
- errorMessage = sealOutputResult.error_message;
646
- } catch (e) {
711
+ } catch (err) {
647
712
  throw new CofhesdkError({
648
- code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
649
- message: `sealOutput request failed`,
650
- hint: "Ensure the threshold network URL is valid.",
651
- cause: e instanceof Error ? e : void 0,
713
+ code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
714
+ message: `mockZkVerifySign calcCtHashes failed while calling zkVerifyCalcCtHashesPacked`,
715
+ cause: err instanceof Error ? err : void 0,
652
716
  context: {
653
- thresholdNetworkUrl,
654
- body
717
+ address: MOCKS_ZK_VERIFIER_ADDRESS,
718
+ items,
719
+ account,
720
+ securityZone,
721
+ publicClient,
722
+ calcCtHashesArgs
655
723
  }
656
724
  });
657
725
  }
658
- if (sealed == null) {
726
+ if (ctHashes.length !== items.length) {
659
727
  throw new CofhesdkError({
660
- code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
661
- message: `sealOutput request returned no data | Caused by: ${errorMessage}`,
728
+ code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
729
+ message: `mockZkVerifySign calcCtHashes returned incorrect number of ctHashes`,
662
730
  context: {
663
- thresholdNetworkUrl,
664
- body,
665
- sealOutputResult
731
+ items,
732
+ account,
733
+ securityZone,
734
+ publicClient,
735
+ calcCtHashesArgs,
736
+ ctHashes
666
737
  }
667
738
  });
668
739
  }
669
- return sealed;
740
+ return items.map((item, index) => ({
741
+ ...item,
742
+ ctHash: ctHashes[index]
743
+ }));
670
744
  }
671
-
672
- // core/decrypt/decryptHandleBuilder.ts
673
- var DecryptHandlesBuilder = class extends BaseBuilder {
674
- ctHash;
675
- utype;
676
- permitHash;
677
- permit;
678
- constructor(params) {
679
- super({
680
- config: params.config,
681
- publicClient: params.publicClient,
682
- walletClient: params.walletClient,
683
- chainId: params.chainId,
684
- account: params.account,
685
- requireConnected: params.requireConnected
745
+ async function insertCtHashes(items, walletClient) {
746
+ const insertPackedCtHashesArgs = [items.map(({ ctHash }) => ctHash), items.map(({ data }) => BigInt(data))];
747
+ try {
748
+ const account = walletClient.account;
749
+ await walletClient.writeContract({
750
+ address: MOCKS_ZK_VERIFIER_ADDRESS,
751
+ abi: MockZkVerifierAbi,
752
+ functionName: "insertPackedCtHashes",
753
+ args: insertPackedCtHashesArgs,
754
+ chain: hardhat,
755
+ account
756
+ });
757
+ } catch (err) {
758
+ throw new CofhesdkError({
759
+ code: "ZK_MOCKS_INSERT_CT_HASHES_FAILED" /* ZkMocksInsertCtHashesFailed */,
760
+ message: `mockZkVerifySign insertPackedCtHashes failed while calling insertPackedCtHashes`,
761
+ cause: err instanceof Error ? err : void 0,
762
+ context: {
763
+ items,
764
+ walletClient,
765
+ insertPackedCtHashesArgs
766
+ }
686
767
  });
687
- this.ctHash = params.ctHash;
688
- this.utype = params.utype;
689
- this.permitHash = params.permitHash;
690
- this.permit = params.permit;
691
- }
692
- /**
693
- * @param chainId - Chain to decrypt values from. Used to fetch the threshold network URL and use the correct permit.
694
- *
695
- * If not provided, the chainId will be fetched from the connected publicClient.
696
- *
697
- * Example:
698
- * ```typescript
699
- * const unsealed = await decryptHandle(ctHash, utype)
700
- * .setChainId(11155111)
701
- * .decrypt();
702
- * ```
703
- *
704
- * @returns The chainable DecryptHandlesBuilder instance.
705
- */
706
- setChainId(chainId) {
707
- this.chainId = chainId;
708
- return this;
709
768
  }
710
- getChainId() {
711
- return this.chainId;
769
+ }
770
+ async function createProofSignatures(items, securityZone) {
771
+ let signatures = [];
772
+ let encInputSignerClient;
773
+ try {
774
+ encInputSignerClient = createMockZkVerifierSigner();
775
+ } catch (err) {
776
+ throw new CofhesdkError({
777
+ code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
778
+ message: `mockZkVerifySign createProofSignatures failed while creating wallet client`,
779
+ cause: err instanceof Error ? err : void 0,
780
+ context: {
781
+ MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY
782
+ }
783
+ });
712
784
  }
713
- /**
714
- * @param account - Account to decrypt values from. Used to fetch the correct permit.
715
- *
716
- * If not provided, the account will be fetched from the connected walletClient.
717
- *
718
- * Example:
719
- * ```typescript
720
- * const unsealed = await decryptHandle(ctHash, utype)
721
- * .setAccount('0x1234567890123456789012345678901234567890')
722
- * .decrypt();
723
- * ```
724
- *
725
- * @returns The chainable DecryptHandlesBuilder instance.
726
- */
727
- setAccount(account) {
728
- this.account = account;
729
- return this;
730
- }
731
- getAccount() {
732
- return this.account;
733
- }
734
- /**
735
- * @param permitHash - Permit hash to decrypt values from. Used to fetch the correct permit.
736
- *
737
- * If not provided, the active permit for the chainId and account will be used.
738
- * If `setPermit()` is called, it will be used regardless of chainId, account, or permitHash.
739
- *
740
- * Example:
741
- * ```typescript
742
- * const unsealed = await decryptHandle(ctHash, utype)
743
- * .setPermitHash('0x1234567890123456789012345678901234567890')
744
- * .decrypt();
745
- * ```
746
- *
747
- * @returns The chainable DecryptHandlesBuilder instance.
748
- */
749
- setPermitHash(permitHash) {
750
- this.permitHash = permitHash;
751
- return this;
752
- }
753
- getPermitHash() {
754
- return this.permitHash;
755
- }
756
- /**
757
- * @param permit - Permit to decrypt values with. If provided, it will be used regardless of chainId, account, or permitHash.
758
- *
759
- * If not provided, the permit will be determined by chainId, account, and permitHash.
760
- *
761
- * Example:
762
- * ```typescript
763
- * const unsealed = await decryptHandle(ctHash, utype)
764
- * .setPermit(permit)
765
- * .decrypt();
766
- * ```
767
- *
768
- * @returns The chainable DecryptHandlesBuilder instance.
769
- */
770
- setPermit(permit) {
771
- this.permit = permit;
772
- return this;
773
- }
774
- getPermit() {
775
- return this.permit;
776
- }
777
- getThresholdNetworkUrl(chainId) {
778
- const config = this.getConfigOrThrow();
779
- return getThresholdNetworkUrlOrThrow(config, chainId);
780
- }
781
- validateUtypeOrThrow() {
782
- if (!isValidUtype(this.utype))
783
- throw new CofhesdkError({
784
- code: "INVALID_UTYPE" /* InvalidUtype */,
785
- message: `Invalid utype to decrypt to`,
786
- context: {
787
- utype: this.utype
788
- }
789
- });
790
- }
791
- async getResolvedPermit() {
792
- if (this.permit)
793
- return this.permit;
794
- const chainId = await this.getChainIdOrThrow();
795
- const account = await this.getAccountOrThrow();
796
- if (this.permitHash) {
797
- const permit2 = await permits.getPermit(chainId, account, this.permitHash);
798
- if (!permit2) {
799
- throw new CofhesdkError({
800
- code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
801
- message: `Permit with hash <${this.permitHash}> not found for account <${account}> and chainId <${chainId}>`,
802
- hint: "Ensure the permit exists and is valid.",
803
- context: {
804
- chainId,
805
- account,
806
- permitHash: this.permitHash
807
- }
808
- });
809
- }
810
- return permit2;
811
- }
812
- const permit = await permits.getActivePermit(chainId, account);
813
- if (!permit) {
814
- throw new CofhesdkError({
815
- code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
816
- message: `Active permit not found for chainId <${chainId}> and account <${account}>`,
817
- hint: "Ensure a permit exists for this account on this chain.",
818
- context: {
819
- chainId,
820
- account
821
- }
785
+ try {
786
+ for (const item of items) {
787
+ const packedData = encodePacked(["uint256", "int32", "uint8"], [BigInt(item.data), securityZone, item.utype]);
788
+ const messageHash = keccak256(packedData);
789
+ const ethSignedHash = hashMessage({ raw: toBytes(messageHash) });
790
+ const signature = await encInputSignerClient.signMessage({
791
+ message: { raw: toBytes(ethSignedHash) },
792
+ account: encInputSignerClient.account
822
793
  });
794
+ signatures.push(signature);
823
795
  }
824
- return permit;
825
- }
826
- /**
827
- * On hardhat, interact with MockZkVerifier contract instead of CoFHE
828
- */
829
- async mocksSealOutput(permit) {
830
- const config = this.getConfigOrThrow();
831
- const mocksSealOutputDelay = config.mocks.sealOutputDelay;
832
- return cofheMocksSealOutput(this.ctHash, this.utype, permit, this.getPublicClientOrThrow(), mocksSealOutputDelay);
833
- }
834
- /**
835
- * In the production context, perform a true decryption with the CoFHE coprocessor.
836
- */
837
- async productionSealOutput(chainId, permit) {
838
- const thresholdNetworkUrl = this.getThresholdNetworkUrl(chainId);
839
- const permission = PermitUtils.getPermission(permit, true);
840
- const sealed = await tnSealOutput(this.ctHash, chainId, permission, thresholdNetworkUrl);
841
- return PermitUtils.unseal(permit, sealed);
842
- }
843
- /**
844
- * Final step of the decryption process. MUST BE CALLED LAST IN THE CHAIN.
845
- *
846
- * This will:
847
- * - Use a permit based on provided permit OR chainId + account + permitHash
848
- * - Check permit validity
849
- * - Call CoFHE `/sealoutput` with the permit, which returns a sealed (encrypted) item
850
- * - Unseal the sealed item with the permit
851
- * - Return the unsealed item
852
- *
853
- * Example:
854
- * ```typescript
855
- * const unsealed = await decryptHandle(ctHash, utype)
856
- * .setChainId(11155111) // optional
857
- * .setAccount('0x123...890') // optional
858
- * .decrypt(); // execute
859
- * ```
860
- *
861
- * @returns The unsealed item.
862
- */
863
- decrypt() {
864
- return resultWrapper(async () => {
865
- await this.requireConnectedOrThrow();
866
- this.validateUtypeOrThrow();
867
- const permit = await this.getResolvedPermit();
868
- await PermitUtils.validate(permit);
869
- const chainId = permit._signedDomain.chainId;
870
- let unsealed;
871
- if (chainId === hardhat.id) {
872
- unsealed = await this.mocksSealOutput(permit);
873
- } else {
874
- unsealed = await this.productionSealOutput(chainId, permit);
796
+ } catch (err) {
797
+ throw new CofhesdkError({
798
+ code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
799
+ message: `mockZkVerifySign createProofSignatures failed while calling signMessage`,
800
+ cause: err instanceof Error ? err : void 0,
801
+ context: {
802
+ items,
803
+ securityZone
875
804
  }
876
- return convertViaUtype(this.utype, unsealed);
877
805
  });
878
806
  }
879
- };
880
-
881
- // core/encrypt/zkPackProveVerify.ts
882
- var MAX_UINT8 = 255n;
883
- var MAX_UINT16 = 65535n;
884
- var MAX_UINT32 = 4294967295n;
885
- var MAX_UINT64 = 18446744073709551615n;
886
- var MAX_UINT128 = 340282366920938463463374607431768211455n;
887
- var MAX_UINT160 = 1461501637330902918203684832716283019655932542975n;
888
- var MAX_ENCRYPTABLE_BITS = 2048;
889
- var zkPack = (items, builder) => {
890
- let totalBits = 0;
891
- for (const item of items) {
892
- switch (item.utype) {
893
- case 0 /* Bool */: {
894
- builder.push_boolean(item.data);
895
- totalBits += 1;
896
- break;
897
- }
898
- case 2 /* Uint8 */: {
899
- const bint = toBigIntOrThrow(item.data);
900
- validateBigIntInRange(bint, MAX_UINT8);
901
- builder.push_u8(parseInt(bint.toString()));
902
- totalBits += 8;
903
- break;
904
- }
905
- case 3 /* Uint16 */: {
906
- const bint = toBigIntOrThrow(item.data);
907
- validateBigIntInRange(bint, MAX_UINT16);
908
- builder.push_u16(parseInt(bint.toString()));
909
- totalBits += 16;
910
- break;
911
- }
912
- case 4 /* Uint32 */: {
913
- const bint = toBigIntOrThrow(item.data);
914
- validateBigIntInRange(bint, MAX_UINT32);
915
- builder.push_u32(parseInt(bint.toString()));
916
- totalBits += 32;
917
- break;
918
- }
919
- case 5 /* Uint64 */: {
920
- const bint = toBigIntOrThrow(item.data);
921
- validateBigIntInRange(bint, MAX_UINT64);
922
- builder.push_u64(bint);
923
- totalBits += 64;
924
- break;
925
- }
926
- case 6 /* Uint128 */: {
927
- const bint = toBigIntOrThrow(item.data);
928
- validateBigIntInRange(bint, MAX_UINT128);
929
- builder.push_u128(bint);
930
- totalBits += 128;
931
- break;
932
- }
933
- case 7 /* Uint160 */: {
934
- const bint = toBigIntOrThrow(item.data);
935
- validateBigIntInRange(bint, MAX_UINT160);
936
- builder.push_u160(bint);
937
- totalBits += 160;
938
- break;
939
- }
940
- default: {
941
- throw new CofhesdkError({
942
- code: "ZK_PACK_FAILED" /* ZkPackFailed */,
943
- message: `Invalid utype: ${item.utype}`,
944
- hint: `Ensure that the utype is valid, using the Encryptable type, for example: Encryptable.uint128(100n)`,
945
- context: {
946
- item
947
- }
948
- });
949
- }
950
- }
951
- }
952
- if (totalBits > MAX_ENCRYPTABLE_BITS) {
807
+ if (signatures.length !== items.length) {
953
808
  throw new CofhesdkError({
954
- code: "ZK_PACK_FAILED" /* ZkPackFailed */,
955
- message: `Total bits ${totalBits} exceeds ${MAX_ENCRYPTABLE_BITS}`,
956
- hint: `Ensure that the total bits of the items to encrypt does not exceed ${MAX_ENCRYPTABLE_BITS}`,
809
+ code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
810
+ message: `mockZkVerifySign createProofSignatures returned incorrect number of signatures`,
957
811
  context: {
958
- totalBits,
959
- maxBits: MAX_ENCRYPTABLE_BITS,
960
- items
812
+ items,
813
+ securityZone
961
814
  }
962
815
  });
963
816
  }
964
- return builder;
965
- };
966
- var zkProve = async (builder, crs, address, securityZone, chainId) => {
967
- const metadata = constructZkPoKMetadata(address, securityZone, chainId);
968
- return new Promise((resolve) => {
969
- setTimeout(() => {
970
- const compactList = builder.build_with_proof_packed(
971
- crs,
972
- metadata,
973
- 1
974
- // ZkComputeLoad.Verify
975
- );
976
- resolve(compactList.serialize());
977
- }, 0);
978
- });
979
- };
980
- var constructZkPoKMetadata = (accountAddr, securityZone, chainId) => {
981
- const accountAddrNoPrefix = accountAddr.startsWith("0x") ? accountAddr.slice(2) : accountAddr;
982
- const accountBytes = hexToBytes(accountAddrNoPrefix);
983
- const chainIdBytes = new Uint8Array(32);
984
- let value = chainId;
985
- for (let i = 31; i >= 0 && value > 0; i--) {
986
- chainIdBytes[i] = value & 255;
987
- value = value >>> 8;
988
- }
989
- const metadata = new Uint8Array(1 + accountBytes.length + 32);
990
- metadata[0] = securityZone;
991
- metadata.set(accountBytes, 1);
992
- metadata.set(chainIdBytes, 1 + accountBytes.length);
993
- return metadata;
994
- };
995
- var zkVerify = async (verifierUrl, serializedBytes, address, securityZone, chainId) => {
996
- const packed_list = toHexString(serializedBytes);
997
- const sz_byte = new Uint8Array([securityZone]);
998
- const payload = {
999
- packed_list,
1000
- account_addr: address,
1001
- security_zone: sz_byte[0],
1002
- chain_id: chainId
817
+ return signatures;
818
+ }
819
+ async function cofheMocksZkVerifySign(items, account, securityZone, publicClient, walletClient, zkvWalletClient) {
820
+ const _walletClient = zkvWalletClient ?? createMockZkVerifierSigner();
821
+ const encryptableItems = await calcCtHashes(items, account, securityZone, publicClient);
822
+ await insertCtHashes(encryptableItems, _walletClient);
823
+ const signatures = await createProofSignatures(encryptableItems, securityZone);
824
+ return encryptableItems.map((item, index) => ({
825
+ ct_hash: item.ctHash.toString(),
826
+ signature: signatures[index]
827
+ }));
828
+ }
829
+ var CofhesdkConfigSchema = z.object({
830
+ /** Environment that the SDK is running in */
831
+ environment: z.enum(["node", "hardhat", "web", "react"]).optional().default("node"),
832
+ /** List of supported chain configurations */
833
+ supportedChains: z.array(z.custom()),
834
+ /** How permits are generated */
835
+ permitGeneration: z.enum(["ON_CONNECT", "ON_DECRYPT_HANDLES", "MANUAL"]).optional().default("ON_CONNECT"),
836
+ /** Default permit expiration in seconds, default is 30 days */
837
+ defaultPermitExpiration: z.number().optional().default(60 * 60 * 24 * 30),
838
+ /** Storage method for fhe keys (defaults to indexedDB on web, filesystem on node) */
839
+ fheKeyStorage: z.object({
840
+ getItem: z.custom((val) => typeof val === "function", {
841
+ message: "getItem must be a function"
842
+ }),
843
+ setItem: z.custom((val) => typeof val === "function", {
844
+ message: "setItem must be a function"
845
+ }),
846
+ removeItem: z.custom((val) => typeof val === "function", {
847
+ message: "removeItem must be a function"
848
+ })
849
+ }).or(z.null()).default(null),
850
+ /** Whether to use Web Workers for ZK proof generation (web platform only) */
851
+ useWorkers: z.boolean().optional().default(true),
852
+ /** Mocks configs */
853
+ mocks: z.object({
854
+ sealOutputDelay: z.number().optional().default(0)
855
+ }).optional().default({ sealOutputDelay: 0 }),
856
+ /** Internal configuration */
857
+ _internal: z.object({
858
+ zkvWalletClient: z.any().optional()
859
+ }).optional()
860
+ });
861
+ function createCofhesdkConfigBase(config) {
862
+ const result = CofhesdkConfigSchema.safeParse(config);
863
+ if (!result.success) {
864
+ throw new Error(`Invalid cofhesdk configuration: ${z.prettifyError(result.error)}`, { cause: result.error });
865
+ }
866
+ return result.data;
867
+ }
868
+ var getCofhesdkConfigItem = (config, key) => {
869
+ return config[key];
870
+ };
871
+ function getSupportedChainOrThrow(config, chainId) {
872
+ const supportedChain = config.supportedChains.find((chain) => chain.id === chainId);
873
+ if (!supportedChain) {
874
+ throw new CofhesdkError({
875
+ code: "UNSUPPORTED_CHAIN" /* UnsupportedChain */,
876
+ message: `Config does not support chain <${chainId}>`,
877
+ hint: "Ensure config passed to client has been created with this chain in the config.supportedChains array.",
878
+ context: {
879
+ chainId,
880
+ supportedChainIds: config.supportedChains.map((c) => c.id)
881
+ }
882
+ });
883
+ }
884
+ return supportedChain;
885
+ }
886
+ function getCoFheUrlOrThrow(config, chainId) {
887
+ const supportedChain = getSupportedChainOrThrow(config, chainId);
888
+ const url = supportedChain.coFheUrl;
889
+ if (!url) {
890
+ throw new CofhesdkError({
891
+ code: "MISSING_CONFIG" /* MissingConfig */,
892
+ message: `CoFHE URL is not configured for chain <${chainId}>`,
893
+ hint: "Ensure this chain config includes a coFheUrl property.",
894
+ context: { chainId }
895
+ });
896
+ }
897
+ return url;
898
+ }
899
+ function getZkVerifierUrlOrThrow(config, chainId) {
900
+ const supportedChain = getSupportedChainOrThrow(config, chainId);
901
+ const url = supportedChain.verifierUrl;
902
+ if (!url) {
903
+ throw new CofhesdkError({
904
+ code: "ZK_VERIFIER_URL_UNINITIALIZED" /* ZkVerifierUrlUninitialized */,
905
+ message: `ZK verifier URL is not configured for chain <${chainId}>`,
906
+ hint: "Ensure this chain config includes a verifierUrl property.",
907
+ context: { chainId }
908
+ });
909
+ }
910
+ return url;
911
+ }
912
+ function getThresholdNetworkUrlOrThrow(config, chainId) {
913
+ const supportedChain = getSupportedChainOrThrow(config, chainId);
914
+ const url = supportedChain.thresholdNetworkUrl;
915
+ if (!url) {
916
+ throw new CofhesdkError({
917
+ code: "THRESHOLD_NETWORK_URL_UNINITIALIZED" /* ThresholdNetworkUrlUninitialized */,
918
+ message: `Threshold network URL is not configured for chain <${chainId}>`,
919
+ hint: "Ensure this chain config includes a thresholdNetworkUrl property.",
920
+ context: { chainId }
921
+ });
922
+ }
923
+ return url;
924
+ }
925
+ function isValidPersistedState(state) {
926
+ if (state && typeof state === "object") {
927
+ if ("fhe" in state && "crs" in state) {
928
+ return true;
929
+ } else {
930
+ throw new Error(
931
+ "Invalid persisted state structure for KeysStore. Is object but doesn't contain required fields 'fhe' and 'crs'."
932
+ );
933
+ }
934
+ }
935
+ return false;
936
+ }
937
+ var DEFAULT_KEYS_STORE = {
938
+ fhe: {},
939
+ crs: {}
940
+ };
941
+ function isStoreWithPersist(store) {
942
+ return "persist" in store;
943
+ }
944
+ function createKeysStore(storage) {
945
+ const keysStore = storage ? createStoreWithPersit(storage) : createStore()(() => ({
946
+ fhe: {},
947
+ crs: {}
948
+ }));
949
+ const getFheKey = (chainId, securityZone = 0) => {
950
+ if (chainId == null || securityZone == null)
951
+ return void 0;
952
+ const stored = keysStore.getState().fhe[chainId]?.[securityZone];
953
+ return stored;
1003
954
  };
1004
- const body = JSON.stringify(payload);
955
+ const getCrs = (chainId) => {
956
+ if (chainId == null)
957
+ return void 0;
958
+ const stored = keysStore.getState().crs[chainId];
959
+ return stored;
960
+ };
961
+ const setFheKey = (chainId, securityZone, key) => {
962
+ keysStore.setState(
963
+ produce((state) => {
964
+ if (state.fhe[chainId] == null)
965
+ state.fhe[chainId] = {};
966
+ state.fhe[chainId][securityZone] = key;
967
+ })
968
+ );
969
+ };
970
+ const setCrs = (chainId, crs) => {
971
+ keysStore.setState(
972
+ produce((state) => {
973
+ state.crs[chainId] = crs;
974
+ })
975
+ );
976
+ };
977
+ const clearKeysStorage = async () => {
978
+ if (storage) {
979
+ await storage.removeItem("cofhesdk-keys");
980
+ }
981
+ };
982
+ const rehydrateKeysStore = async () => {
983
+ if (!isStoreWithPersist(keysStore))
984
+ return;
985
+ if (keysStore.persist.hasHydrated())
986
+ return;
987
+ await keysStore.persist.rehydrate();
988
+ };
989
+ return {
990
+ store: keysStore,
991
+ getFheKey,
992
+ getCrs,
993
+ setFheKey,
994
+ setCrs,
995
+ clearKeysStorage,
996
+ rehydrateKeysStore
997
+ };
998
+ }
999
+ function createStoreWithPersit(storage) {
1000
+ const result = createStore()(
1001
+ persist(() => DEFAULT_KEYS_STORE, {
1002
+ // because earleir tests were written with on-init hydration skipped (due to the error suppression in zustand), returning this flag to fix test (i.e. KeyStore > Storage Utilities > should rehydrate keys store)
1003
+ skipHydration: true,
1004
+ // if onRehydrateStorage is not passed here, the errors thrown by storage layer are swallowed by zustand here: https://github.com/pmndrs/zustand/blob/39a391b6c1ff9aa89b81694d9bdb21da37dd4ac6/src/middleware/persist.ts#L321
1005
+ onRehydrateStorage: () => (_state, _error) => {
1006
+ if (_error)
1007
+ throw new Error(`onRehydrateStorage: Error rehydrating keys store: ${_error}`);
1008
+ },
1009
+ name: "cofhesdk-keys",
1010
+ storage: createJSONStorage(() => storage),
1011
+ merge: (persistedState, currentState) => {
1012
+ const persisted = isValidPersistedState(persistedState) ? persistedState : DEFAULT_KEYS_STORE;
1013
+ const current = currentState;
1014
+ const mergedFhe = { ...persisted.fhe };
1015
+ const allChainIds = /* @__PURE__ */ new Set([...Object.keys(current.fhe), ...Object.keys(persisted.fhe)]);
1016
+ for (const chainId of allChainIds) {
1017
+ const persistedZones = persisted.fhe[chainId] || {};
1018
+ const currentZones = current.fhe[chainId] || {};
1019
+ mergedFhe[chainId] = { ...persistedZones, ...currentZones };
1020
+ }
1021
+ const mergedCrs = { ...persisted.crs, ...current.crs };
1022
+ return {
1023
+ fhe: mergedFhe,
1024
+ crs: mergedCrs
1025
+ };
1026
+ }
1027
+ })
1028
+ );
1029
+ return result;
1030
+ }
1031
+
1032
+ // core/fetchKeys.ts
1033
+ var PUBLIC_KEY_LENGTH_MIN = 15e3;
1034
+ var checkKeyValidity = (key, serializer) => {
1035
+ if (key == null || key.length === 0)
1036
+ return [false, `Key is null or empty <${key}>`];
1005
1037
  try {
1006
- const response = await fetch(`${verifierUrl}/verify`, {
1038
+ serializer(key);
1039
+ return [true, `Key is valid`];
1040
+ } catch (err) {
1041
+ return [false, `Serialization failed <${err}> key length <${key.length}>`];
1042
+ }
1043
+ };
1044
+ var fetchFhePublicKey = async (coFheUrl, chainId, securityZone, tfhePublicKeyDeserializer, keysStorage) => {
1045
+ const storedKey = keysStorage?.getFheKey(chainId, securityZone);
1046
+ const [storedKeyValid] = checkKeyValidity(storedKey, tfhePublicKeyDeserializer);
1047
+ if (storedKeyValid)
1048
+ return [storedKey, false];
1049
+ let pk_data = void 0;
1050
+ try {
1051
+ const pk_res = await fetch(`${coFheUrl}/GetNetworkPublicKey`, {
1007
1052
  method: "POST",
1008
1053
  headers: {
1009
1054
  "Content-Type": "application/json"
1010
1055
  },
1011
- body
1012
- });
1013
- if (!response.ok) {
1014
- const errorBody = await response.text();
1015
- throw new CofhesdkError({
1016
- code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
1017
- message: `HTTP error! ZK proof verification failed - ${errorBody}`
1018
- });
1019
- }
1020
- const json = await response.json();
1021
- if (json.status !== "success") {
1022
- throw new CofhesdkError({
1023
- code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
1024
- message: `ZK proof verification response malformed - ${json.error}`
1025
- });
1026
- }
1027
- return json.data.map(({ ct_hash, signature, recid }) => {
1028
- return {
1029
- ct_hash,
1030
- signature: concatSigRecid(signature, recid)
1031
- };
1032
- });
1033
- } catch (e) {
1034
- throw new CofhesdkError({
1035
- code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
1036
- message: `ZK proof verification failed`,
1037
- cause: e instanceof Error ? e : void 0
1056
+ body: JSON.stringify({ securityZone })
1038
1057
  });
1058
+ const json = await pk_res.json();
1059
+ pk_data = json.publicKey;
1060
+ } catch (err) {
1061
+ throw new Error(`Error fetching FHE publicKey; fetching from CoFHE failed with error ${err}`);
1039
1062
  }
1063
+ if (pk_data == null || typeof pk_data !== "string") {
1064
+ throw new Error(`Error fetching FHE publicKey; fetched result invalid: missing or not a string`);
1065
+ }
1066
+ if (pk_data === "0x") {
1067
+ throw new Error("Error fetching FHE publicKey; provided chain is not FHE enabled / not found");
1068
+ }
1069
+ if (pk_data.length < PUBLIC_KEY_LENGTH_MIN) {
1070
+ throw new Error(
1071
+ `Error fetching FHE publicKey; got shorter than expected key length: ${pk_data.length}. Expected length >= ${PUBLIC_KEY_LENGTH_MIN}`
1072
+ );
1073
+ }
1074
+ try {
1075
+ tfhePublicKeyDeserializer(pk_data);
1076
+ } catch (err) {
1077
+ throw new Error(`Error serializing FHE publicKey; ${err}`);
1078
+ }
1079
+ keysStorage?.setFheKey(chainId, securityZone, pk_data);
1080
+ return [pk_data, true];
1040
1081
  };
1041
- var concatSigRecid = (signature, recid) => {
1042
- return signature + (recid + 27).toString(16).padStart(2, "0");
1043
- };
1044
-
1045
- // core/encrypt/MockZkVerifierAbi.ts
1046
- var MockZkVerifierAbi = [
1047
- {
1048
- type: "function",
1049
- name: "exists",
1050
- inputs: [],
1051
- outputs: [{ name: "", type: "bool", internalType: "bool" }],
1052
- stateMutability: "pure"
1053
- },
1054
- {
1055
- type: "function",
1056
- name: "insertCtHash",
1057
- inputs: [
1058
- { name: "ctHash", type: "uint256", internalType: "uint256" },
1059
- { name: "value", type: "uint256", internalType: "uint256" }
1060
- ],
1061
- outputs: [],
1062
- stateMutability: "nonpayable"
1063
- },
1064
- {
1065
- type: "function",
1066
- name: "insertPackedCtHashes",
1067
- inputs: [
1068
- { name: "ctHashes", type: "uint256[]", internalType: "uint256[]" },
1069
- { name: "values", type: "uint256[]", internalType: "uint256[]" }
1070
- ],
1071
- outputs: [],
1072
- stateMutability: "nonpayable"
1073
- },
1074
- {
1075
- type: "function",
1076
- name: "zkVerify",
1077
- inputs: [
1078
- { name: "value", type: "uint256", internalType: "uint256" },
1079
- { name: "utype", type: "uint8", internalType: "uint8" },
1080
- { name: "user", type: "address", internalType: "address" },
1081
- { name: "securityZone", type: "uint8", internalType: "uint8" },
1082
- { name: "", type: "uint256", internalType: "uint256" }
1083
- ],
1084
- outputs: [
1085
- {
1086
- name: "",
1087
- type: "tuple",
1088
- internalType: "struct EncryptedInput",
1089
- components: [
1090
- { name: "ctHash", type: "uint256", internalType: "uint256" },
1091
- { name: "securityZone", type: "uint8", internalType: "uint8" },
1092
- { name: "utype", type: "uint8", internalType: "uint8" },
1093
- { name: "signature", type: "bytes", internalType: "bytes" }
1094
- ]
1095
- }
1096
- ],
1097
- stateMutability: "nonpayable"
1098
- },
1099
- {
1100
- type: "function",
1101
- name: "zkVerifyCalcCtHash",
1102
- inputs: [
1103
- { name: "value", type: "uint256", internalType: "uint256" },
1104
- { name: "utype", type: "uint8", internalType: "uint8" },
1105
- { name: "user", type: "address", internalType: "address" },
1106
- { name: "securityZone", type: "uint8", internalType: "uint8" },
1107
- { name: "", type: "uint256", internalType: "uint256" }
1108
- ],
1109
- outputs: [{ name: "ctHash", type: "uint256", internalType: "uint256" }],
1110
- stateMutability: "view"
1111
- },
1112
- {
1113
- type: "function",
1114
- name: "zkVerifyCalcCtHashesPacked",
1115
- inputs: [
1116
- { name: "values", type: "uint256[]", internalType: "uint256[]" },
1117
- { name: "utypes", type: "uint8[]", internalType: "uint8[]" },
1118
- { name: "user", type: "address", internalType: "address" },
1119
- { name: "securityZone", type: "uint8", internalType: "uint8" },
1120
- { name: "chainId", type: "uint256", internalType: "uint256" }
1121
- ],
1122
- outputs: [{ name: "ctHashes", type: "uint256[]", internalType: "uint256[]" }],
1123
- stateMutability: "view"
1124
- },
1125
- {
1126
- type: "function",
1127
- name: "zkVerifyPacked",
1128
- inputs: [
1129
- { name: "values", type: "uint256[]", internalType: "uint256[]" },
1130
- { name: "utypes", type: "uint8[]", internalType: "uint8[]" },
1131
- { name: "user", type: "address", internalType: "address" },
1132
- { name: "securityZone", type: "uint8", internalType: "uint8" },
1133
- { name: "chainId", type: "uint256", internalType: "uint256" }
1134
- ],
1135
- outputs: [
1136
- {
1137
- name: "inputs",
1138
- type: "tuple[]",
1139
- internalType: "struct EncryptedInput[]",
1140
- components: [
1141
- { name: "ctHash", type: "uint256", internalType: "uint256" },
1142
- { name: "securityZone", type: "uint8", internalType: "uint8" },
1143
- { name: "utype", type: "uint8", internalType: "uint8" },
1144
- { name: "signature", type: "bytes", internalType: "bytes" }
1145
- ]
1146
- }
1147
- ],
1148
- stateMutability: "nonpayable"
1149
- },
1150
- { type: "error", name: "InvalidInputs", inputs: [] }
1151
- ];
1152
- var MocksZkVerifierAddress = "0x0000000000000000000000000000000000000100";
1153
- var MocksEncryptedInputSignerPkey = "0x6c8d7f768a6bb4aafe85e8a2f5a9680355239c7e14646ed62b044e39de154512";
1154
- async function cofheMocksCheckEncryptableBits(items) {
1155
- let totalBits = 0;
1156
- for (const item of items) {
1157
- switch (item.utype) {
1158
- case 0 /* Bool */: {
1159
- totalBits += 1;
1160
- break;
1161
- }
1162
- case 2 /* Uint8 */: {
1163
- totalBits += 8;
1164
- break;
1165
- }
1166
- case 3 /* Uint16 */: {
1167
- totalBits += 16;
1168
- break;
1169
- }
1170
- case 4 /* Uint32 */: {
1171
- totalBits += 32;
1172
- break;
1173
- }
1174
- case 5 /* Uint64 */: {
1175
- totalBits += 64;
1176
- break;
1177
- }
1178
- case 6 /* Uint128 */: {
1179
- totalBits += 128;
1180
- break;
1181
- }
1182
- case 7 /* Uint160 */: {
1183
- totalBits += 160;
1184
- break;
1185
- }
1082
+ var fetchCrs = async (coFheUrl, chainId, securityZone, compactPkeCrsDeserializer, keysStorage) => {
1083
+ const storedKey = keysStorage?.getCrs(chainId);
1084
+ const [storedKeyValid] = checkKeyValidity(storedKey, compactPkeCrsDeserializer);
1085
+ if (storedKeyValid)
1086
+ return [storedKey, false];
1087
+ let crs_data = void 0;
1088
+ try {
1089
+ const crs_res = await fetch(`${coFheUrl}/GetCrs`, {
1090
+ method: "POST",
1091
+ headers: {
1092
+ "Content-Type": "application/json"
1093
+ },
1094
+ body: JSON.stringify({ securityZone })
1095
+ });
1096
+ const json = await crs_res.json();
1097
+ crs_data = json.crs;
1098
+ } catch (err) {
1099
+ throw new Error(`Error fetching CRS; fetching failed with error ${err}`);
1100
+ }
1101
+ if (crs_data == null || typeof crs_data !== "string") {
1102
+ throw new Error(`Error fetching CRS; invalid: missing or not a string`);
1103
+ }
1104
+ try {
1105
+ compactPkeCrsDeserializer(crs_data);
1106
+ } catch (err) {
1107
+ console.error(`Error serializing CRS ${err}`);
1108
+ throw new Error(`Error serializing CRS; ${err}`);
1109
+ }
1110
+ keysStorage?.setCrs(chainId, crs_data);
1111
+ return [crs_data, true];
1112
+ };
1113
+ var fetchKeys = async (config, chainId, securityZone = 0, tfhePublicKeyDeserializer, compactPkeCrsDeserializer, keysStorage) => {
1114
+ const coFheUrl = getCoFheUrlOrThrow(config, chainId);
1115
+ return await Promise.all([
1116
+ fetchFhePublicKey(coFheUrl, chainId, securityZone, tfhePublicKeyDeserializer, keysStorage),
1117
+ fetchCrs(coFheUrl, chainId, securityZone, compactPkeCrsDeserializer, keysStorage)
1118
+ ]);
1119
+ };
1120
+ var BaseBuilder = class {
1121
+ config;
1122
+ publicClient;
1123
+ walletClient;
1124
+ chainId;
1125
+ account;
1126
+ constructor(params) {
1127
+ if (!params.config) {
1128
+ throw new CofhesdkError({
1129
+ code: "MISSING_CONFIG" /* MissingConfig */,
1130
+ message: "Builder config is undefined",
1131
+ hint: "Ensure client has been created with a config.",
1132
+ context: {
1133
+ config: params.config
1134
+ }
1135
+ });
1186
1136
  }
1137
+ this.config = params.config;
1138
+ this.publicClient = params.publicClient;
1139
+ this.walletClient = params.walletClient;
1140
+ this.chainId = params.chainId;
1141
+ this.account = params.account;
1142
+ params.requireConnected?.();
1187
1143
  }
1188
- if (totalBits > MAX_ENCRYPTABLE_BITS) {
1144
+ /**
1145
+ * Asserts that this.chainId is populated
1146
+ * @throws {CofhesdkError} If chainId is not set
1147
+ */
1148
+ assertChainId() {
1149
+ if (this.chainId)
1150
+ return;
1189
1151
  throw new CofhesdkError({
1190
- code: "ZK_PACK_FAILED" /* ZkPackFailed */,
1191
- message: `Total bits ${totalBits} exceeds ${MAX_ENCRYPTABLE_BITS}`,
1192
- hint: `Ensure that the total bits of the items to encrypt does not exceed ${MAX_ENCRYPTABLE_BITS}`,
1152
+ code: "CHAIN_ID_UNINITIALIZED" /* ChainIdUninitialized */,
1153
+ message: "Chain ID is not set",
1154
+ hint: "Ensure client.connect() has been called and awaited, or use setChainId(...) to set the chainId explicitly.",
1193
1155
  context: {
1194
- totalBits,
1195
- maxBits: MAX_ENCRYPTABLE_BITS,
1196
- items
1156
+ chainId: this.chainId
1197
1157
  }
1198
1158
  });
1199
1159
  }
1200
- }
1201
- async function calcCtHashes(items, account, securityZone, publicClient) {
1202
- const calcCtHashesArgs = [
1203
- items.map(({ data }) => BigInt(data)),
1204
- items.map(({ utype }) => utype),
1205
- account,
1206
- securityZone,
1207
- BigInt(hardhat$1.id)
1208
- ];
1209
- let ctHashes;
1210
- try {
1211
- ctHashes = await publicClient.readContract({
1212
- address: MocksZkVerifierAddress,
1213
- abi: MockZkVerifierAbi,
1214
- functionName: "zkVerifyCalcCtHashesPacked",
1215
- args: calcCtHashesArgs
1160
+ /**
1161
+ * Asserts that this.account is populated
1162
+ * @throws {CofhesdkError} If account is not set
1163
+ */
1164
+ assertAccount() {
1165
+ if (this.account)
1166
+ return;
1167
+ throw new CofhesdkError({
1168
+ code: "ACCOUNT_UNINITIALIZED" /* AccountUninitialized */,
1169
+ message: "Account is not set",
1170
+ hint: "Ensure client.connect() has been called and awaited, or use setAccount(...) to set the account explicitly.",
1171
+ context: {
1172
+ account: this.account
1173
+ }
1216
1174
  });
1217
- } catch (err) {
1175
+ }
1176
+ /**
1177
+ * Asserts that this.publicClient is populated
1178
+ * @throws {CofhesdkError} If publicClient is not set
1179
+ */
1180
+ assertPublicClient() {
1181
+ if (this.publicClient)
1182
+ return;
1218
1183
  throw new CofhesdkError({
1219
- code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
1220
- message: `mockZkVerifySign calcCtHashes failed while calling zkVerifyCalcCtHashesPacked`,
1221
- cause: err instanceof Error ? err : void 0,
1184
+ code: "MISSING_PUBLIC_CLIENT" /* MissingPublicClient */,
1185
+ message: "Public client not found",
1186
+ hint: "Ensure client.connect() has been called with a publicClient.",
1222
1187
  context: {
1223
- address: MocksZkVerifierAddress,
1224
- items,
1225
- account,
1226
- securityZone,
1227
- publicClient,
1228
- calcCtHashesArgs
1188
+ publicClient: this.publicClient
1229
1189
  }
1230
1190
  });
1231
1191
  }
1232
- if (ctHashes.length !== items.length) {
1192
+ /**
1193
+ * Asserts that this.walletClient is populated
1194
+ * @throws {CofhesdkError} If walletClient is not set
1195
+ */
1196
+ assertWalletClient() {
1197
+ if (this.walletClient)
1198
+ return;
1233
1199
  throw new CofhesdkError({
1234
- code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
1235
- message: `mockZkVerifySign calcCtHashes returned incorrect number of ctHashes`,
1200
+ code: "MISSING_WALLET_CLIENT" /* MissingWalletClient */,
1201
+ message: "Wallet client not found",
1202
+ hint: "Ensure client.connect() has been called with a walletClient.",
1236
1203
  context: {
1237
- items,
1238
- account,
1239
- securityZone,
1240
- publicClient,
1241
- calcCtHashesArgs,
1242
- ctHashes
1204
+ walletClient: this.walletClient
1243
1205
  }
1244
1206
  });
1245
1207
  }
1246
- return items.map((item, index) => ({
1247
- ...item,
1248
- ctHash: ctHashes[index]
1249
- }));
1250
- }
1251
- async function insertCtHashes(items, walletClient) {
1252
- const insertPackedCtHashesArgs = [items.map(({ ctHash }) => ctHash), items.map(({ data }) => BigInt(data))];
1253
- try {
1254
- const account = walletClient.account;
1255
- await walletClient.writeContract({
1256
- address: MocksZkVerifierAddress,
1257
- abi: MockZkVerifierAbi,
1258
- functionName: "insertPackedCtHashes",
1259
- args: insertPackedCtHashesArgs,
1260
- chain: hardhat$1,
1261
- account
1262
- });
1263
- } catch (err) {
1264
- throw new CofhesdkError({
1265
- code: "ZK_MOCKS_INSERT_CT_HASHES_FAILED" /* ZkMocksInsertCtHashesFailed */,
1266
- message: `mockZkVerifySign insertPackedCtHashes failed while calling insertPackedCtHashes`,
1267
- cause: err instanceof Error ? err : void 0,
1268
- context: {
1269
- items,
1270
- walletClient,
1271
- insertPackedCtHashesArgs
1272
- }
1273
- });
1274
- }
1275
- }
1276
- async function createProofSignatures(items, securityZone) {
1277
- let signatures = [];
1278
- let encInputSignerClient;
1279
- try {
1280
- encInputSignerClient = createWalletClient({
1281
- chain: hardhat$1,
1282
- transport: http(),
1283
- account: privateKeyToAccount(MocksEncryptedInputSignerPkey)
1284
- });
1285
- } catch (err) {
1286
- throw new CofhesdkError({
1287
- code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
1288
- message: `mockZkVerifySign createProofSignatures failed while creating wallet client`,
1289
- cause: err instanceof Error ? err : void 0,
1290
- context: {
1291
- MocksEncryptedInputSignerPkey
1292
- }
1293
- });
1294
- }
1295
- try {
1296
- for (const item of items) {
1297
- const packedData = encodePacked(["uint256", "int32", "uint8"], [BigInt(item.data), securityZone, item.utype]);
1298
- const messageHash = keccak256(packedData);
1299
- const ethSignedHash = hashMessage({ raw: toBytes(messageHash) });
1300
- const signature = await encInputSignerClient.signMessage({
1301
- message: { raw: toBytes(ethSignedHash) },
1302
- account: encInputSignerClient.account
1303
- });
1304
- signatures.push(signature);
1305
- }
1306
- } catch (err) {
1307
- throw new CofhesdkError({
1308
- code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
1309
- message: `mockZkVerifySign createProofSignatures failed while calling signMessage`,
1310
- cause: err instanceof Error ? err : void 0,
1311
- context: {
1312
- items,
1313
- securityZone
1314
- }
1315
- });
1316
- }
1317
- if (signatures.length !== items.length) {
1318
- throw new CofhesdkError({
1319
- code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
1320
- message: `mockZkVerifySign createProofSignatures returned incorrect number of signatures`,
1321
- context: {
1322
- items,
1323
- securityZone
1324
- }
1325
- });
1326
- }
1327
- return signatures;
1328
- }
1329
- async function cofheMocksZkVerifySign(items, account, securityZone, publicClient, walletClient, zkvWalletClient) {
1330
- const _walletClient = zkvWalletClient ?? walletClient;
1331
- const encryptableItems = await calcCtHashes(items, account, securityZone, publicClient);
1332
- await insertCtHashes(encryptableItems, _walletClient);
1333
- const signatures = await createProofSignatures(encryptableItems, securityZone);
1334
- return encryptableItems.map((item, index) => ({
1335
- ct_hash: item.ctHash.toString(),
1336
- signature: signatures[index]
1337
- }));
1338
- }
1339
- function createKeysStore(storage) {
1340
- const keysStore = storage ? createStore()(
1341
- persist(
1342
- () => ({
1343
- fhe: {},
1344
- crs: {}
1345
- }),
1346
- {
1347
- name: "cofhesdk-keys",
1348
- storage: createJSONStorage(() => storage),
1349
- merge: (persistedState, currentState) => {
1350
- const persisted = persistedState;
1351
- const current = currentState;
1352
- const mergedFhe = { ...persisted.fhe };
1353
- const allChainIds = /* @__PURE__ */ new Set([...Object.keys(current.fhe), ...Object.keys(persisted.fhe)]);
1354
- for (const chainId of allChainIds) {
1355
- const persistedZones = persisted.fhe[chainId] || {};
1356
- const currentZones = current.fhe[chainId] || {};
1357
- mergedFhe[chainId] = { ...persistedZones, ...currentZones };
1358
- }
1359
- const mergedCrs = { ...persisted.crs, ...current.crs };
1360
- return {
1361
- fhe: mergedFhe,
1362
- crs: mergedCrs
1363
- };
1364
- }
1365
- }
1366
- )
1367
- ) : createStore()(() => ({
1368
- fhe: {},
1369
- crs: {}
1370
- }));
1371
- const getFheKey = (chainId, securityZone = 0) => {
1372
- if (chainId == null || securityZone == null)
1373
- return void 0;
1374
- const stored = keysStore.getState().fhe[chainId]?.[securityZone];
1375
- return stored;
1376
- };
1377
- const getCrs = (chainId) => {
1378
- if (chainId == null)
1379
- return void 0;
1380
- const stored = keysStore.getState().crs[chainId];
1381
- return stored;
1382
- };
1383
- const setFheKey = (chainId, securityZone, key) => {
1384
- keysStore.setState(
1385
- produce((state) => {
1386
- if (state.fhe[chainId] == null)
1387
- state.fhe[chainId] = {};
1388
- state.fhe[chainId][securityZone] = key;
1389
- })
1390
- );
1391
- };
1392
- const setCrs = (chainId, crs) => {
1393
- keysStore.setState(
1394
- produce((state) => {
1395
- state.crs[chainId] = crs;
1396
- })
1397
- );
1398
- };
1399
- const clearKeysStorage = async () => {
1400
- if (storage) {
1401
- await storage.removeItem("cofhesdk-keys");
1402
- }
1403
- };
1404
- const rehydrateKeysStore = async () => {
1405
- if ("persist" in keysStore) {
1406
- if (keysStore.persist.hasHydrated())
1407
- return;
1408
- await keysStore.persist.rehydrate();
1409
- }
1410
- };
1411
- return {
1412
- store: keysStore,
1413
- getFheKey,
1414
- getCrs,
1415
- setFheKey,
1416
- setCrs,
1417
- clearKeysStorage,
1418
- rehydrateKeysStore
1419
- };
1420
- }
1208
+ };
1421
1209
 
1422
1210
  // core/encrypt/encryptInputsBuilder.ts
1423
1211
  var EncryptInputsBuilder = class extends BaseBuilder {
@@ -1429,7 +1217,10 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1429
1217
  compactPkeCrsDeserializer;
1430
1218
  zkBuilderAndCrsGenerator;
1431
1219
  initTfhe;
1220
+ zkProveWorkerFn;
1432
1221
  keysStorage;
1222
+ // Worker configuration (from config, overrideable)
1223
+ useWorker;
1433
1224
  stepTimestamps = {
1434
1225
  ["initTfhe" /* InitTfhe */]: 0,
1435
1226
  ["fetchKeys" /* FetchKeys */]: 0,
@@ -1449,11 +1240,43 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1449
1240
  this.inputItems = params.inputs;
1450
1241
  this.securityZone = params.securityZone ?? 0;
1451
1242
  this.zkvWalletClient = params.zkvWalletClient;
1243
+ if (!params.tfhePublicKeyDeserializer) {
1244
+ throw new CofhesdkError({
1245
+ code: "MISSING_TFHE_PUBLIC_KEY_DESERIALIZER" /* MissingTfhePublicKeyDeserializer */,
1246
+ message: "EncryptInputsBuilder tfhePublicKeyDeserializer is undefined",
1247
+ hint: "Ensure client has been created with a tfhePublicKeyDeserializer.",
1248
+ context: {
1249
+ tfhePublicKeyDeserializer: params.tfhePublicKeyDeserializer
1250
+ }
1251
+ });
1252
+ }
1452
1253
  this.tfhePublicKeyDeserializer = params.tfhePublicKeyDeserializer;
1254
+ if (!params.compactPkeCrsDeserializer) {
1255
+ throw new CofhesdkError({
1256
+ code: "MISSING_COMPACT_PKE_CRS_DESERIALIZER" /* MissingCompactPkeCrsDeserializer */,
1257
+ message: "EncryptInputsBuilder compactPkeCrsDeserializer is undefined",
1258
+ hint: "Ensure client has been created with a compactPkeCrsDeserializer.",
1259
+ context: {
1260
+ compactPkeCrsDeserializer: params.compactPkeCrsDeserializer
1261
+ }
1262
+ });
1263
+ }
1453
1264
  this.compactPkeCrsDeserializer = params.compactPkeCrsDeserializer;
1265
+ if (!params.zkBuilderAndCrsGenerator) {
1266
+ throw new CofhesdkError({
1267
+ code: "MISSING_ZK_BUILDER_AND_CRS_GENERATOR" /* MissingZkBuilderAndCrsGenerator */,
1268
+ message: "EncryptInputsBuilder zkBuilderAndCrsGenerator is undefined",
1269
+ hint: "Ensure client has been created with a zkBuilderAndCrsGenerator.",
1270
+ context: {
1271
+ zkBuilderAndCrsGenerator: params.zkBuilderAndCrsGenerator
1272
+ }
1273
+ });
1274
+ }
1454
1275
  this.zkBuilderAndCrsGenerator = params.zkBuilderAndCrsGenerator;
1455
1276
  this.initTfhe = params.initTfhe;
1277
+ this.zkProveWorkerFn = params.zkProveWorkerFn;
1456
1278
  this.keysStorage = params.keysStorage;
1279
+ this.useWorker = params.config?.useWorkers ?? true;
1457
1280
  }
1458
1281
  /**
1459
1282
  * @param account - Account that will create the tx using the encrypted inputs.
@@ -1518,6 +1341,40 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1518
1341
  getSecurityZone() {
1519
1342
  return this.securityZone;
1520
1343
  }
1344
+ /**
1345
+ * @param useWorker - Whether to use Web Workers for ZK proof generation.
1346
+ *
1347
+ * Overrides the config-level useWorkers setting for this specific encryption.
1348
+ *
1349
+ * Example:
1350
+ * ```typescript
1351
+ * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1352
+ * .setUseWorker(false)
1353
+ * .encrypt();
1354
+ * ```
1355
+ *
1356
+ * @returns The chainable EncryptInputsBuilder instance.
1357
+ */
1358
+ setUseWorker(useWorker) {
1359
+ this.useWorker = useWorker;
1360
+ return this;
1361
+ }
1362
+ /**
1363
+ * Gets the current worker configuration.
1364
+ *
1365
+ * @returns Whether Web Workers are enabled for this encryption.
1366
+ *
1367
+ * Example:
1368
+ * ```typescript
1369
+ * const builder = encryptInputs([Encryptable.uint128(10n)]);
1370
+ * console.log(builder.getUseWorker()); // true (from config)
1371
+ * builder.setUseWorker(false);
1372
+ * console.log(builder.getUseWorker()); // false (overridden)
1373
+ * ```
1374
+ */
1375
+ getUseWorker() {
1376
+ return this.useWorker;
1377
+ }
1521
1378
  /**
1522
1379
  * @param callback - Function to be called with the encryption step.
1523
1380
  *
@@ -1555,50 +1412,13 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1555
1412
  const duration = Date.now() - this.stepTimestamps[step];
1556
1413
  this.stepCallback(step, { ...context, isStart: false, isEnd: true, duration });
1557
1414
  }
1558
- /**
1559
- * tfhePublicKeyDeserializer is a platform-specific dependency injected into core/createCofhesdkClientBase by web/createCofhesdkClient and node/createCofhesdkClient
1560
- * web/ uses zama "tfhe"
1561
- * node/ uses zama "node-tfhe"
1562
- * Users should not set this manually.
1563
- */
1564
- getTfhePublicKeyDeserializerOrThrow() {
1565
- if (this.tfhePublicKeyDeserializer)
1566
- return this.tfhePublicKeyDeserializer;
1567
- throw new CofhesdkError({
1568
- code: "MISSING_TFHE_PUBLIC_KEY_DESERIALIZER" /* MissingTfhePublicKeyDeserializer */,
1569
- message: "EncryptInputsBuilder tfhePublicKeyDeserializer is undefined",
1570
- hint: "Ensure client has been created with a tfhePublicKeyDeserializer.",
1571
- context: {
1572
- tfhePublicKeyDeserializer: this.tfhePublicKeyDeserializer
1573
- }
1574
- });
1575
- }
1576
- /**
1577
- * compactPkeCrsDeserializer is a platform-specific dependency injected into core/createCofhesdkClientBase by web/createCofhesdkClient and node/createCofhesdkClient
1578
- * web/ uses zama "tfhe"
1579
- * node/ uses zama "node-tfhe"
1580
- * Users should not set this manually.
1581
- */
1582
- getCompactPkeCrsDeserializerOrThrow() {
1583
- if (this.compactPkeCrsDeserializer)
1584
- return this.compactPkeCrsDeserializer;
1585
- throw new CofhesdkError({
1586
- code: "MISSING_COMPACT_PKE_CRS_DESERIALIZER" /* MissingCompactPkeCrsDeserializer */,
1587
- message: "EncryptInputsBuilder compactPkeCrsDeserializer is undefined",
1588
- hint: "Ensure client has been created with a compactPkeCrsDeserializer.",
1589
- context: {
1590
- compactPkeCrsDeserializer: this.compactPkeCrsDeserializer
1591
- }
1592
- });
1593
- }
1594
1415
  /**
1595
1416
  * zkVerifierUrl is included in the chains exported from cofhesdk/chains for use in CofhesdkConfig.supportedChains
1596
1417
  * Users should generally not set this manually.
1597
1418
  */
1598
1419
  async getZkVerifierUrl() {
1599
- const config = this.getConfigOrThrow();
1600
- const chainId = await this.getChainIdOrThrow();
1601
- return getZkVerifierUrlOrThrow(config, chainId);
1420
+ this.assertChainId();
1421
+ return getZkVerifierUrlOrThrow(this.config, this.chainId);
1602
1422
  }
1603
1423
  /**
1604
1424
  * initTfhe is a platform-specific dependency injected into core/createCofhesdkClientBase by web/createCofhesdkClient and node/createCofhesdkClient
@@ -1626,10 +1446,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1626
1446
  * If the key/crs already exists in the store it is returned, else it is fetched, stored, and returned
1627
1447
  */
1628
1448
  async fetchFheKeyAndCrs() {
1629
- const config = this.getConfigOrThrow();
1630
- const chainId = await this.getChainIdOrThrow();
1631
- const compactPkeCrsDeserializer = this.getCompactPkeCrsDeserializerOrThrow();
1632
- const tfhePublicKeyDeserializer = this.getTfhePublicKeyDeserializerOrThrow();
1449
+ this.assertChainId();
1633
1450
  const securityZone = this.getSecurityZone();
1634
1451
  try {
1635
1452
  await this.keysStorage?.rehydrateKeysStore();
@@ -1648,11 +1465,11 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1648
1465
  let crsFetchedFromCoFHE = false;
1649
1466
  try {
1650
1467
  [[fheKey, fheKeyFetchedFromCoFHE], [crs, crsFetchedFromCoFHE]] = await fetchKeys(
1651
- config,
1652
- chainId,
1468
+ this.config,
1469
+ this.chainId,
1653
1470
  securityZone,
1654
- tfhePublicKeyDeserializer,
1655
- compactPkeCrsDeserializer,
1471
+ this.tfhePublicKeyDeserializer,
1472
+ this.compactPkeCrsDeserializer,
1656
1473
  this.keysStorage
1657
1474
  );
1658
1475
  } catch (error) {
@@ -1660,11 +1477,11 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1660
1477
  code: "FETCH_KEYS_FAILED" /* FetchKeysFailed */,
1661
1478
  message: `Failed to fetch FHE key and CRS`,
1662
1479
  context: {
1663
- config,
1664
- chainId,
1480
+ config: this.config,
1481
+ chainId: this.chainId,
1665
1482
  securityZone,
1666
- compactPkeCrsDeserializer,
1667
- tfhePublicKeyDeserializer
1483
+ compactPkeCrsDeserializer: this.compactPkeCrsDeserializer,
1484
+ tfhePublicKeyDeserializer: this.tfhePublicKeyDeserializer
1668
1485
  }
1669
1486
  });
1670
1487
  }
@@ -1673,7 +1490,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1673
1490
  code: "MISSING_FHE_KEY" /* MissingFheKey */,
1674
1491
  message: `FHE key not found`,
1675
1492
  context: {
1676
- chainId,
1493
+ chainId: this.chainId,
1677
1494
  securityZone
1678
1495
  }
1679
1496
  });
@@ -1683,34 +1500,12 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1683
1500
  code: "MISSING_CRS" /* MissingCrs */,
1684
1501
  message: `CRS not found for chainId <${this.chainId}>`,
1685
1502
  context: {
1686
- chainId
1503
+ chainId: this.chainId
1687
1504
  }
1688
1505
  });
1689
1506
  }
1690
1507
  return { fheKey, fheKeyFetchedFromCoFHE, crs, crsFetchedFromCoFHE };
1691
1508
  }
1692
- /**
1693
- * zkBuilderAndCrsGenerator is a platform-specific dependency injected into core/createCofhesdkClientBase by web/createCofhesdkClient and node/createCofhesdkClient
1694
- * web/ uses zama "tfhe"
1695
- * node/ uses zama "node-tfhe"
1696
- * Users should not set this manually.
1697
- *
1698
- * Generates the zkBuilder and zkCrs from the fheKey and crs
1699
- */
1700
- generateZkBuilderAndCrs(fheKey, crs) {
1701
- const zkBuilderAndCrsGenerator = this.zkBuilderAndCrsGenerator;
1702
- if (!zkBuilderAndCrsGenerator) {
1703
- throw new CofhesdkError({
1704
- code: "MISSING_ZK_BUILDER_AND_CRS_GENERATOR" /* MissingZkBuilderAndCrsGenerator */,
1705
- message: `zkBuilderAndCrsGenerator is undefined`,
1706
- hint: "Ensure client has been created with a zkBuilderAndCrsGenerator.",
1707
- context: {
1708
- zkBuilderAndCrsGenerator: this.zkBuilderAndCrsGenerator
1709
- }
1710
- });
1711
- }
1712
- return zkBuilderAndCrsGenerator(fheKey, crs);
1713
- }
1714
1509
  /**
1715
1510
  * @dev Encrypt against the cofheMocks instead of CoFHE
1716
1511
  *
@@ -1718,7 +1513,10 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1718
1513
  * cofheMocksInsertPackedHashes - stores the ctHashes and their plaintext values for on-chain mocking of FHE operations.
1719
1514
  * cofheMocksZkCreateProofSignatures - creates signatures to be included in the encrypted inputs. The signers address is known and verified in the mock contracts.
1720
1515
  */
1721
- async mocksEncrypt(account) {
1516
+ async mocksEncrypt() {
1517
+ this.assertAccount();
1518
+ this.assertPublicClient();
1519
+ this.assertWalletClient();
1722
1520
  this.fireStepStart("initTfhe" /* InitTfhe */);
1723
1521
  await sleep(100);
1724
1522
  this.fireStepEnd("initTfhe" /* InitTfhe */, { tfheInitializationExecuted: false });
@@ -1736,10 +1534,10 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1736
1534
  await sleep(500);
1737
1535
  const signedResults = await cofheMocksZkVerifySign(
1738
1536
  this.inputItems,
1739
- account,
1537
+ this.account,
1740
1538
  this.securityZone,
1741
- this.getPublicClientOrThrow(),
1742
- this.getWalletClientOrThrow(),
1539
+ this.publicClient,
1540
+ this.walletClient,
1743
1541
  this.zkvWalletClient
1744
1542
  );
1745
1543
  const encryptedInputs = signedResults.map(({ ct_hash, signature }, index) => ({
@@ -1754,23 +1552,44 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1754
1552
  /**
1755
1553
  * In the production context, perform a true encryption with the CoFHE coprocessor.
1756
1554
  */
1757
- async productionEncrypt(account, chainId) {
1555
+ async productionEncrypt() {
1556
+ this.assertAccount();
1557
+ this.assertChainId();
1758
1558
  this.fireStepStart("initTfhe" /* InitTfhe */);
1759
1559
  const tfheInitializationExecuted = await this.initTfheOrThrow();
1760
1560
  this.fireStepEnd("initTfhe" /* InitTfhe */, { tfheInitializationExecuted });
1761
1561
  this.fireStepStart("fetchKeys" /* FetchKeys */);
1762
1562
  const { fheKey, fheKeyFetchedFromCoFHE, crs, crsFetchedFromCoFHE } = await this.fetchFheKeyAndCrs();
1763
- let { zkBuilder, zkCrs } = this.generateZkBuilderAndCrs(fheKey, crs);
1563
+ let { zkBuilder, zkCrs } = this.zkBuilderAndCrsGenerator(fheKey, crs);
1764
1564
  this.fireStepEnd("fetchKeys" /* FetchKeys */, { fheKeyFetchedFromCoFHE, crsFetchedFromCoFHE });
1765
1565
  this.fireStepStart("pack" /* Pack */);
1766
1566
  zkBuilder = zkPack(this.inputItems, zkBuilder);
1767
1567
  this.fireStepEnd("pack" /* Pack */);
1768
1568
  this.fireStepStart("prove" /* Prove */);
1769
- const proof = await zkProve(zkBuilder, zkCrs, account, this.securityZone, chainId);
1770
- this.fireStepEnd("prove" /* Prove */);
1569
+ const metadata = constructZkPoKMetadata(this.account, this.securityZone, this.chainId);
1570
+ let proof = null;
1571
+ let usedWorker = false;
1572
+ let workerFailedError;
1573
+ if (this.useWorker && this.zkProveWorkerFn) {
1574
+ try {
1575
+ proof = await zkProveWithWorker(this.zkProveWorkerFn, fheKey, crs, this.inputItems, metadata);
1576
+ usedWorker = true;
1577
+ } catch (error) {
1578
+ workerFailedError = error instanceof Error ? error.message : String(error);
1579
+ }
1580
+ }
1581
+ if (proof == null) {
1582
+ proof = await zkProve(zkBuilder, zkCrs, metadata);
1583
+ usedWorker = false;
1584
+ }
1585
+ this.fireStepEnd("prove" /* Prove */, {
1586
+ useWorker: this.useWorker,
1587
+ usedWorker,
1588
+ workerFailedError
1589
+ });
1771
1590
  this.fireStepStart("verify" /* Verify */);
1772
1591
  const zkVerifierUrl = await this.getZkVerifierUrl();
1773
- const verifyResults = await zkVerify(zkVerifierUrl, proof, account, this.securityZone, chainId);
1592
+ const verifyResults = await zkVerify(zkVerifierUrl, proof, this.account, this.securityZone, this.chainId);
1774
1593
  const encryptedInputs = verifyResults.map(
1775
1594
  ({ ct_hash, signature }, index) => ({
1776
1595
  ctHash: BigInt(ct_hash),
@@ -1802,307 +1621,722 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1802
1621
  * @returns The encrypted inputs.
1803
1622
  */
1804
1623
  async encrypt() {
1805
- return resultWrapper(async () => {
1806
- await this.requireConnectedOrThrow();
1807
- const account = await this.getAccountOrThrow();
1808
- const chainId = await this.getChainIdOrThrow();
1809
- if (chainId === hardhat$1.id) {
1810
- return await this.mocksEncrypt(account);
1811
- }
1812
- return await this.productionEncrypt(account, chainId);
1813
- });
1624
+ if (this.chainId === hardhat.id)
1625
+ return this.mocksEncrypt();
1626
+ return this.productionEncrypt();
1814
1627
  }
1815
1628
  };
1816
-
1817
- // core/types.ts
1818
- var FheTypes = /* @__PURE__ */ ((FheTypes2) => {
1819
- FheTypes2[FheTypes2["Bool"] = 0] = "Bool";
1820
- FheTypes2[FheTypes2["Uint4"] = 1] = "Uint4";
1821
- FheTypes2[FheTypes2["Uint8"] = 2] = "Uint8";
1822
- FheTypes2[FheTypes2["Uint16"] = 3] = "Uint16";
1823
- FheTypes2[FheTypes2["Uint32"] = 4] = "Uint32";
1824
- FheTypes2[FheTypes2["Uint64"] = 5] = "Uint64";
1825
- FheTypes2[FheTypes2["Uint128"] = 6] = "Uint128";
1826
- FheTypes2[FheTypes2["Uint160"] = 7] = "Uint160";
1827
- FheTypes2[FheTypes2["Uint256"] = 8] = "Uint256";
1828
- FheTypes2[FheTypes2["Uint512"] = 9] = "Uint512";
1829
- FheTypes2[FheTypes2["Uint1024"] = 10] = "Uint1024";
1830
- FheTypes2[FheTypes2["Uint2048"] = 11] = "Uint2048";
1831
- FheTypes2[FheTypes2["Uint2"] = 12] = "Uint2";
1832
- FheTypes2[FheTypes2["Uint6"] = 13] = "Uint6";
1833
- FheTypes2[FheTypes2["Uint10"] = 14] = "Uint10";
1834
- FheTypes2[FheTypes2["Uint12"] = 15] = "Uint12";
1835
- FheTypes2[FheTypes2["Uint14"] = 16] = "Uint14";
1836
- FheTypes2[FheTypes2["Int2"] = 17] = "Int2";
1837
- FheTypes2[FheTypes2["Int4"] = 18] = "Int4";
1838
- FheTypes2[FheTypes2["Int6"] = 19] = "Int6";
1839
- FheTypes2[FheTypes2["Int8"] = 20] = "Int8";
1840
- FheTypes2[FheTypes2["Int10"] = 21] = "Int10";
1841
- FheTypes2[FheTypes2["Int12"] = 22] = "Int12";
1842
- FheTypes2[FheTypes2["Int14"] = 23] = "Int14";
1843
- FheTypes2[FheTypes2["Int16"] = 24] = "Int16";
1844
- FheTypes2[FheTypes2["Int32"] = 25] = "Int32";
1845
- FheTypes2[FheTypes2["Int64"] = 26] = "Int64";
1846
- FheTypes2[FheTypes2["Int128"] = 27] = "Int128";
1847
- FheTypes2[FheTypes2["Int160"] = 28] = "Int160";
1848
- FheTypes2[FheTypes2["Int256"] = 29] = "Int256";
1849
- return FheTypes2;
1850
- })(FheTypes || {});
1851
- var FheUintUTypes = [
1852
- 2 /* Uint8 */,
1853
- 3 /* Uint16 */,
1854
- 4 /* Uint32 */,
1855
- 5 /* Uint64 */,
1856
- 6 /* Uint128 */
1857
- // [U256-DISABLED]
1858
- // FheTypes.Uint256,
1859
- ];
1860
- var FheAllUTypes = [
1861
- 0 /* Bool */,
1862
- 2 /* Uint8 */,
1863
- 3 /* Uint16 */,
1864
- 4 /* Uint32 */,
1865
- 5 /* Uint64 */,
1866
- 6 /* Uint128 */,
1867
- // [U256-DISABLED]
1868
- // FheTypes.Uint256,
1869
- 7 /* Uint160 */
1870
- ];
1871
- var Encryptable = {
1872
- bool: (data, securityZone = 0) => ({ data, securityZone, utype: 0 /* Bool */ }),
1873
- address: (data, securityZone = 0) => ({ data, securityZone, utype: 7 /* Uint160 */ }),
1874
- uint8: (data, securityZone = 0) => ({ data, securityZone, utype: 2 /* Uint8 */ }),
1875
- uint16: (data, securityZone = 0) => ({ data, securityZone, utype: 3 /* Uint16 */ }),
1876
- uint32: (data, securityZone = 0) => ({ data, securityZone, utype: 4 /* Uint32 */ }),
1877
- uint64: (data, securityZone = 0) => ({ data, securityZone, utype: 5 /* Uint64 */ }),
1878
- uint128: (data, securityZone = 0) => ({ data, securityZone, utype: 6 /* Uint128 */ })
1879
- // [U256-DISABLED]
1880
- // uint256: (data: EncryptableUint256['data'], securityZone = 0) =>
1881
- // ({ data, securityZone, utype: FheTypes.Uint256 }) as EncryptableUint256,
1629
+ var storeActivePermit = async (permit, publicClient, walletClient) => {
1630
+ const chainId = await publicClient.getChainId();
1631
+ const account = walletClient.account.address;
1632
+ permitStore.setPermit(chainId, account, permit);
1633
+ permitStore.setActivePermitHash(chainId, account, permit.hash);
1882
1634
  };
1883
- function isEncryptableItem(value) {
1884
- return (
1885
- // Is object and exists
1886
- typeof value === "object" && value !== null && // Has securityZone
1887
- "securityZone" in value && typeof value.securityZone === "number" && // Has utype
1888
- "utype" in value && FheAllUTypes.includes(value.utype) && // Has data
1889
- "data" in value && ["string", "number", "bigint", "boolean"].includes(typeof value.data)
1890
- );
1635
+ var createPermitWithSign = async (options, publicClient, walletClient, permitMethod) => {
1636
+ const permit = await permitMethod(options, publicClient, walletClient);
1637
+ await storeActivePermit(permit, publicClient, walletClient);
1638
+ return permit;
1639
+ };
1640
+ var createSelf = async (options, publicClient, walletClient) => {
1641
+ return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSelfAndSign);
1642
+ };
1643
+ var createSharing = async (options, publicClient, walletClient) => {
1644
+ return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSharingAndSign);
1645
+ };
1646
+ var importShared = async (options, publicClient, walletClient) => {
1647
+ return createPermitWithSign(options, publicClient, walletClient, PermitUtils.importSharedAndSign);
1648
+ };
1649
+ var getHash = (permit) => {
1650
+ return PermitUtils.getHash(permit);
1651
+ };
1652
+ var serialize = (permit) => {
1653
+ return PermitUtils.serialize(permit);
1654
+ };
1655
+ var deserialize = (serialized) => {
1656
+ return PermitUtils.deserialize(serialized);
1657
+ };
1658
+ var getPermit = async (chainId, account, hash) => {
1659
+ return permitStore.getPermit(chainId, account, hash);
1660
+ };
1661
+ var getPermits = async (chainId, account) => {
1662
+ return permitStore.getPermits(chainId, account);
1663
+ };
1664
+ var getActivePermit = async (chainId, account) => {
1665
+ return permitStore.getActivePermit(chainId, account);
1666
+ };
1667
+ var getActivePermitHash = (chainId, account) => {
1668
+ return permitStore.getActivePermitHash(chainId, account);
1669
+ };
1670
+ var selectActivePermit = (chainId, account, hash) => {
1671
+ permitStore.setActivePermitHash(chainId, account, hash);
1672
+ };
1673
+ var getOrCreateSelfPermit = async (publicClient, walletClient, chainId, account, options) => {
1674
+ const _chainId = chainId ?? await publicClient.getChainId();
1675
+ const _account = account ?? walletClient.account.address;
1676
+ const activePermit = await getActivePermit(_chainId, _account);
1677
+ if (activePermit && activePermit.type === "self") {
1678
+ return activePermit;
1679
+ }
1680
+ return createSelf(options ?? { issuer: _account, name: "Autogenerated Self Permit" }, publicClient, walletClient);
1681
+ };
1682
+ var getOrCreateSharingPermit = async (publicClient, walletClient, options, chainId, account) => {
1683
+ const _chainId = chainId ?? await publicClient.getChainId();
1684
+ const _account = account ?? walletClient.account.address;
1685
+ const activePermit = await getActivePermit(_chainId, _account);
1686
+ if (activePermit && activePermit.type === "sharing") {
1687
+ return activePermit;
1688
+ }
1689
+ return createSharing(options, publicClient, walletClient);
1690
+ };
1691
+ var removePermit = async (chainId, account, hash) => permitStore.removePermit(chainId, account, hash);
1692
+ var removeActivePermit = async (chainId, account) => permitStore.removeActivePermitHash(chainId, account);
1693
+ var permits = {
1694
+ getSnapshot: permitStore.store.getState,
1695
+ subscribe: permitStore.store.subscribe,
1696
+ createSelf,
1697
+ createSharing,
1698
+ importShared,
1699
+ getOrCreateSelfPermit,
1700
+ getOrCreateSharingPermit,
1701
+ getHash,
1702
+ serialize,
1703
+ deserialize,
1704
+ getPermit,
1705
+ getPermits,
1706
+ getActivePermit,
1707
+ getActivePermitHash,
1708
+ removePermit,
1709
+ selectActivePermit,
1710
+ removeActivePermit
1711
+ };
1712
+ function uint160ToAddress(uint160) {
1713
+ const hexStr = uint160.toString(16).padStart(40, "0");
1714
+ return getAddress("0x" + hexStr);
1715
+ }
1716
+ var isValidUtype = (utype) => {
1717
+ return utype === 0 /* Bool */ || utype === 7 /* Uint160 */ || utype == null || FheUintUTypes.includes(utype);
1718
+ };
1719
+ var convertViaUtype = (utype, value) => {
1720
+ if (utype === 0 /* Bool */) {
1721
+ return !!value;
1722
+ } else if (utype === 7 /* Uint160 */) {
1723
+ return uint160ToAddress(value);
1724
+ } else if (utype == null || FheUintUTypes.includes(utype)) {
1725
+ return value;
1726
+ } else {
1727
+ throw new Error(`convertViaUtype :: invalid utype :: ${utype}`);
1728
+ }
1729
+ };
1730
+
1731
+ // core/decrypt/MockQueryDecrypterAbi.ts
1732
+ var MockQueryDecrypterAbi = [
1733
+ {
1734
+ type: "function",
1735
+ name: "acl",
1736
+ inputs: [],
1737
+ outputs: [{ name: "", type: "address", internalType: "contract ACL" }],
1738
+ stateMutability: "view"
1739
+ },
1740
+ {
1741
+ type: "function",
1742
+ name: "decodeLowLevelReversion",
1743
+ inputs: [{ name: "data", type: "bytes", internalType: "bytes" }],
1744
+ outputs: [{ name: "error", type: "string", internalType: "string" }],
1745
+ stateMutability: "pure"
1746
+ },
1747
+ {
1748
+ type: "function",
1749
+ name: "exists",
1750
+ inputs: [],
1751
+ outputs: [{ name: "", type: "bool", internalType: "bool" }],
1752
+ stateMutability: "pure"
1753
+ },
1754
+ {
1755
+ type: "function",
1756
+ name: "initialize",
1757
+ inputs: [
1758
+ { name: "_taskManager", type: "address", internalType: "address" },
1759
+ { name: "_acl", type: "address", internalType: "address" }
1760
+ ],
1761
+ outputs: [],
1762
+ stateMutability: "nonpayable"
1763
+ },
1764
+ {
1765
+ type: "function",
1766
+ name: "queryDecrypt",
1767
+ inputs: [
1768
+ { name: "ctHash", type: "uint256", internalType: "uint256" },
1769
+ { name: "", type: "uint256", internalType: "uint256" },
1770
+ {
1771
+ name: "permission",
1772
+ type: "tuple",
1773
+ internalType: "struct Permission",
1774
+ components: [
1775
+ { name: "issuer", type: "address", internalType: "address" },
1776
+ { name: "expiration", type: "uint64", internalType: "uint64" },
1777
+ { name: "recipient", type: "address", internalType: "address" },
1778
+ { name: "validatorId", type: "uint256", internalType: "uint256" },
1779
+ {
1780
+ name: "validatorContract",
1781
+ type: "address",
1782
+ internalType: "address"
1783
+ },
1784
+ { name: "sealingKey", type: "bytes32", internalType: "bytes32" },
1785
+ { name: "issuerSignature", type: "bytes", internalType: "bytes" },
1786
+ { name: "recipientSignature", type: "bytes", internalType: "bytes" }
1787
+ ]
1788
+ }
1789
+ ],
1790
+ outputs: [
1791
+ { name: "allowed", type: "bool", internalType: "bool" },
1792
+ { name: "error", type: "string", internalType: "string" },
1793
+ { name: "", type: "uint256", internalType: "uint256" }
1794
+ ],
1795
+ stateMutability: "view"
1796
+ },
1797
+ {
1798
+ type: "function",
1799
+ name: "querySealOutput",
1800
+ inputs: [
1801
+ { name: "ctHash", type: "uint256", internalType: "uint256" },
1802
+ { name: "", type: "uint256", internalType: "uint256" },
1803
+ {
1804
+ name: "permission",
1805
+ type: "tuple",
1806
+ internalType: "struct Permission",
1807
+ components: [
1808
+ { name: "issuer", type: "address", internalType: "address" },
1809
+ { name: "expiration", type: "uint64", internalType: "uint64" },
1810
+ { name: "recipient", type: "address", internalType: "address" },
1811
+ { name: "validatorId", type: "uint256", internalType: "uint256" },
1812
+ {
1813
+ name: "validatorContract",
1814
+ type: "address",
1815
+ internalType: "address"
1816
+ },
1817
+ { name: "sealingKey", type: "bytes32", internalType: "bytes32" },
1818
+ { name: "issuerSignature", type: "bytes", internalType: "bytes" },
1819
+ { name: "recipientSignature", type: "bytes", internalType: "bytes" }
1820
+ ]
1821
+ }
1822
+ ],
1823
+ outputs: [
1824
+ { name: "allowed", type: "bool", internalType: "bool" },
1825
+ { name: "error", type: "string", internalType: "string" },
1826
+ { name: "", type: "bytes32", internalType: "bytes32" }
1827
+ ],
1828
+ stateMutability: "view"
1829
+ },
1830
+ {
1831
+ type: "function",
1832
+ name: "seal",
1833
+ inputs: [
1834
+ { name: "input", type: "uint256", internalType: "uint256" },
1835
+ { name: "key", type: "bytes32", internalType: "bytes32" }
1836
+ ],
1837
+ outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
1838
+ stateMutability: "pure"
1839
+ },
1840
+ {
1841
+ type: "function",
1842
+ name: "taskManager",
1843
+ inputs: [],
1844
+ outputs: [{ name: "", type: "address", internalType: "contract TaskManager" }],
1845
+ stateMutability: "view"
1846
+ },
1847
+ {
1848
+ type: "function",
1849
+ name: "unseal",
1850
+ inputs: [
1851
+ { name: "hashed", type: "bytes32", internalType: "bytes32" },
1852
+ { name: "key", type: "bytes32", internalType: "bytes32" }
1853
+ ],
1854
+ outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
1855
+ stateMutability: "pure"
1856
+ },
1857
+ { type: "error", name: "NotAllowed", inputs: [] },
1858
+ { type: "error", name: "SealingKeyInvalid", inputs: [] },
1859
+ { type: "error", name: "SealingKeyMissing", inputs: [] }
1860
+ ];
1861
+
1862
+ // core/decrypt/cofheMocksSealOutput.ts
1863
+ async function cofheMocksSealOutput(ctHash, utype, permit, publicClient, mocksSealOutputDelay) {
1864
+ if (mocksSealOutputDelay > 0)
1865
+ await sleep(mocksSealOutputDelay);
1866
+ const permission = PermitUtils.getPermission(permit, true);
1867
+ const permissionWithBigInts = {
1868
+ ...permission,
1869
+ expiration: BigInt(permission.expiration),
1870
+ validatorId: BigInt(permission.validatorId)
1871
+ };
1872
+ const [allowed, error, result] = await publicClient.readContract({
1873
+ address: MOCKS_QUERY_DECRYPTER_ADDRESS,
1874
+ abi: MockQueryDecrypterAbi,
1875
+ functionName: "querySealOutput",
1876
+ args: [ctHash, BigInt(utype), permissionWithBigInts]
1877
+ });
1878
+ if (error != "") {
1879
+ throw new CofhesdkError({
1880
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1881
+ message: `mocks querySealOutput call failed: ${error}`
1882
+ });
1883
+ }
1884
+ if (allowed == false) {
1885
+ throw new CofhesdkError({
1886
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1887
+ message: `mocks querySealOutput call failed: ACL Access Denied (NotAllowed)`
1888
+ });
1889
+ }
1890
+ const sealedBigInt = BigInt(result);
1891
+ const sealingKeyBigInt = BigInt(permission.sealingKey);
1892
+ const unsealed = sealedBigInt ^ sealingKeyBigInt;
1893
+ return unsealed;
1891
1894
  }
1892
- var EncryptStep = /* @__PURE__ */ ((EncryptStep2) => {
1893
- EncryptStep2["InitTfhe"] = "initTfhe";
1894
- EncryptStep2["FetchKeys"] = "fetchKeys";
1895
- EncryptStep2["Pack"] = "pack";
1896
- EncryptStep2["Prove"] = "prove";
1897
- EncryptStep2["Verify"] = "verify";
1898
- return EncryptStep2;
1899
- })(EncryptStep || {});
1900
1895
 
1901
- // core/config.ts
1902
- var CofhesdkConfigSchema = z.object({
1903
- /** List of supported chain configurations */
1904
- supportedChains: z.array(z.custom()),
1905
- /** Strategy for fetching FHE keys */
1906
- fheKeysPrefetching: z.enum(["CONNECTED_CHAIN", "SUPPORTED_CHAINS", "OFF"]).optional().default("OFF"),
1907
- /** How permits are generated */
1908
- permitGeneration: z.enum(["ON_CONNECT", "ON_DECRYPT_HANDLES", "MANUAL"]).optional().default("ON_CONNECT"),
1909
- /** Default permit expiration in seconds, default is 30 days */
1910
- defaultPermitExpiration: z.number().optional().default(60 * 60 * 24 * 30),
1911
- /** Storage method for fhe keys (defaults to indexedDB on web, filesystem on node) */
1912
- fheKeyStorage: z.object({
1913
- getItem: z.function().args(z.string()).returns(z.promise(z.any())),
1914
- setItem: z.function().args(z.string(), z.any()).returns(z.promise(z.void())),
1915
- removeItem: z.function().args(z.string()).returns(z.promise(z.void()))
1916
- }).or(z.null()).default(null),
1917
- /** Mocks configs */
1918
- mocks: z.object({
1919
- sealOutputDelay: z.number().optional().default(0)
1920
- }).optional().default({ sealOutputDelay: 0 }),
1921
- /** Internal configuration */
1922
- _internal: z.object({
1923
- zkvWalletClient: z.any().optional()
1924
- }).optional()
1925
- });
1926
- function createCofhesdkConfigBase(config) {
1927
- const result = CofhesdkConfigSchema.safeParse(config);
1928
- if (!result.success) {
1929
- throw new Error(`Invalid cofhesdk configuration: ${result.error.message}`);
1896
+ // core/decrypt/tnSealOutputV2.ts
1897
+ var POLL_INTERVAL_MS = 1e3;
1898
+ var POLL_TIMEOUT_MS = 5 * 60 * 1e3;
1899
+ function numberArrayToUint8Array(arr) {
1900
+ return new Uint8Array(arr);
1901
+ }
1902
+ function convertSealedData(sealed) {
1903
+ if (!sealed) {
1904
+ throw new CofhesdkError({
1905
+ code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
1906
+ message: "Sealed data is missing from completed response"
1907
+ });
1930
1908
  }
1931
- return result.data;
1909
+ return {
1910
+ data: numberArrayToUint8Array(sealed.data),
1911
+ public_key: numberArrayToUint8Array(sealed.public_key),
1912
+ nonce: numberArrayToUint8Array(sealed.nonce)
1913
+ };
1932
1914
  }
1933
- var getCofhesdkConfigItem = (config, key) => {
1934
- return config[key];
1935
- };
1936
- function getSupportedChainOrThrow(config, chainId) {
1937
- const supportedChain = config.supportedChains.find((chain) => chain.id === chainId);
1938
- if (!supportedChain) {
1915
+ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission) {
1916
+ const body = {
1917
+ ct_tempkey: ctHash.toString(16).padStart(64, "0"),
1918
+ host_chain_id: chainId,
1919
+ permit: permission
1920
+ };
1921
+ let response;
1922
+ try {
1923
+ response = await fetch(`${thresholdNetworkUrl}/v2/sealoutput`, {
1924
+ method: "POST",
1925
+ headers: {
1926
+ "Content-Type": "application/json"
1927
+ },
1928
+ body: JSON.stringify(body)
1929
+ });
1930
+ } catch (e) {
1939
1931
  throw new CofhesdkError({
1940
- code: "UNSUPPORTED_CHAIN" /* UnsupportedChain */,
1941
- message: `Config does not support chain <${chainId}>`,
1942
- hint: "Ensure config passed to client has been created with this chain in the config.supportedChains array.",
1932
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1933
+ message: `sealOutput request failed`,
1934
+ hint: "Ensure the threshold network URL is valid and reachable.",
1935
+ cause: e instanceof Error ? e : void 0,
1943
1936
  context: {
1944
- chainId,
1945
- supportedChainIds: config.supportedChains.map((c) => c.id)
1937
+ thresholdNetworkUrl,
1938
+ body
1946
1939
  }
1947
1940
  });
1948
1941
  }
1949
- return supportedChain;
1950
- }
1951
- function getCoFheUrlOrThrow(config, chainId) {
1952
- const supportedChain = getSupportedChainOrThrow(config, chainId);
1953
- const url = supportedChain.coFheUrl;
1954
- if (!url) {
1942
+ if (!response.ok) {
1943
+ let errorMessage = `HTTP ${response.status}`;
1944
+ try {
1945
+ const errorBody = await response.json();
1946
+ errorMessage = errorBody.error_message || errorBody.message || errorMessage;
1947
+ } catch {
1948
+ errorMessage = response.statusText || errorMessage;
1949
+ }
1955
1950
  throw new CofhesdkError({
1956
- code: "MISSING_CONFIG" /* MissingConfig */,
1957
- message: `CoFHE URL is not configured for chain <${chainId}>`,
1958
- hint: "Ensure this chain config includes a coFheUrl property.",
1959
- context: { chainId }
1951
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1952
+ message: `sealOutput request failed: ${errorMessage}`,
1953
+ hint: "Check the threshold network URL and request parameters.",
1954
+ context: {
1955
+ thresholdNetworkUrl,
1956
+ status: response.status,
1957
+ statusText: response.statusText,
1958
+ body
1959
+ }
1960
1960
  });
1961
1961
  }
1962
- return url;
1963
- }
1964
- function getZkVerifierUrlOrThrow(config, chainId) {
1965
- const supportedChain = getSupportedChainOrThrow(config, chainId);
1966
- const url = supportedChain.verifierUrl;
1967
- if (!url) {
1962
+ let submitResponse;
1963
+ try {
1964
+ submitResponse = await response.json();
1965
+ } catch (e) {
1968
1966
  throw new CofhesdkError({
1969
- code: "ZK_VERIFIER_URL_UNINITIALIZED" /* ZkVerifierUrlUninitialized */,
1970
- message: `ZK verifier URL is not configured for chain <${chainId}>`,
1971
- hint: "Ensure this chain config includes a verifierUrl property.",
1972
- context: { chainId }
1967
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1968
+ message: `Failed to parse sealOutput submit response`,
1969
+ cause: e instanceof Error ? e : void 0,
1970
+ context: {
1971
+ thresholdNetworkUrl,
1972
+ body
1973
+ }
1974
+ });
1975
+ }
1976
+ if (!submitResponse.request_id) {
1977
+ throw new CofhesdkError({
1978
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1979
+ message: `sealOutput submit response missing request_id`,
1980
+ context: {
1981
+ thresholdNetworkUrl,
1982
+ body,
1983
+ submitResponse
1984
+ }
1985
+ });
1986
+ }
1987
+ return submitResponse.request_id;
1988
+ }
1989
+ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
1990
+ const startTime = Date.now();
1991
+ let completed = false;
1992
+ while (!completed) {
1993
+ if (Date.now() - startTime > POLL_TIMEOUT_MS) {
1994
+ throw new CofhesdkError({
1995
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1996
+ message: `sealOutput polling timed out after ${POLL_TIMEOUT_MS}ms`,
1997
+ hint: "The request may still be processing. Try again later.",
1998
+ context: {
1999
+ thresholdNetworkUrl,
2000
+ requestId,
2001
+ timeoutMs: POLL_TIMEOUT_MS
2002
+ }
2003
+ });
2004
+ }
2005
+ let response;
2006
+ try {
2007
+ response = await fetch(`${thresholdNetworkUrl}/v2/sealoutput/${requestId}`, {
2008
+ method: "GET",
2009
+ headers: {
2010
+ "Content-Type": "application/json"
2011
+ }
2012
+ });
2013
+ } catch (e) {
2014
+ throw new CofhesdkError({
2015
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2016
+ message: `sealOutput status poll failed`,
2017
+ hint: "Ensure the threshold network URL is valid and reachable.",
2018
+ cause: e instanceof Error ? e : void 0,
2019
+ context: {
2020
+ thresholdNetworkUrl,
2021
+ requestId
2022
+ }
2023
+ });
2024
+ }
2025
+ if (response.status === 404) {
2026
+ throw new CofhesdkError({
2027
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2028
+ message: `sealOutput request not found: ${requestId}`,
2029
+ hint: "The request may have expired or been invalid.",
2030
+ context: {
2031
+ thresholdNetworkUrl,
2032
+ requestId
2033
+ }
2034
+ });
2035
+ }
2036
+ if (!response.ok) {
2037
+ let errorMessage = `HTTP ${response.status}`;
2038
+ try {
2039
+ const errorBody = await response.json();
2040
+ errorMessage = errorBody.error_message || errorBody.message || errorMessage;
2041
+ } catch {
2042
+ errorMessage = response.statusText || errorMessage;
2043
+ }
2044
+ throw new CofhesdkError({
2045
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2046
+ message: `sealOutput status poll failed: ${errorMessage}`,
2047
+ context: {
2048
+ thresholdNetworkUrl,
2049
+ requestId,
2050
+ status: response.status,
2051
+ statusText: response.statusText
2052
+ }
2053
+ });
2054
+ }
2055
+ let statusResponse;
2056
+ try {
2057
+ statusResponse = await response.json();
2058
+ } catch (e) {
2059
+ throw new CofhesdkError({
2060
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2061
+ message: `Failed to parse sealOutput status response`,
2062
+ cause: e instanceof Error ? e : void 0,
2063
+ context: {
2064
+ thresholdNetworkUrl,
2065
+ requestId
2066
+ }
2067
+ });
2068
+ }
2069
+ if (statusResponse.status === "COMPLETED") {
2070
+ if (statusResponse.is_succeed === false) {
2071
+ const errorMessage = statusResponse.error_message || "Unknown error";
2072
+ throw new CofhesdkError({
2073
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2074
+ message: `sealOutput request failed: ${errorMessage}`,
2075
+ context: {
2076
+ thresholdNetworkUrl,
2077
+ requestId,
2078
+ statusResponse
2079
+ }
2080
+ });
2081
+ }
2082
+ if (!statusResponse.sealed) {
2083
+ throw new CofhesdkError({
2084
+ code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
2085
+ message: `sealOutput request completed but returned no sealed data`,
2086
+ context: {
2087
+ thresholdNetworkUrl,
2088
+ requestId,
2089
+ statusResponse
2090
+ }
2091
+ });
2092
+ }
2093
+ return convertSealedData(statusResponse.sealed);
2094
+ }
2095
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
2096
+ }
2097
+ throw new CofhesdkError({
2098
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2099
+ message: "Polling loop exited unexpectedly",
2100
+ context: {
2101
+ thresholdNetworkUrl,
2102
+ requestId
2103
+ }
2104
+ });
2105
+ }
2106
+ async function tnSealOutputV2(ctHash, chainId, permission, thresholdNetworkUrl) {
2107
+ const requestId = await submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission);
2108
+ return await pollSealOutputStatus(thresholdNetworkUrl, requestId);
2109
+ }
2110
+
2111
+ // core/decrypt/decryptHandleBuilder.ts
2112
+ var DecryptHandlesBuilder = class extends BaseBuilder {
2113
+ ctHash;
2114
+ utype;
2115
+ permitHash;
2116
+ permit;
2117
+ constructor(params) {
2118
+ super({
2119
+ config: params.config,
2120
+ publicClient: params.publicClient,
2121
+ walletClient: params.walletClient,
2122
+ chainId: params.chainId,
2123
+ account: params.account,
2124
+ requireConnected: params.requireConnected
1973
2125
  });
2126
+ this.ctHash = params.ctHash;
2127
+ this.utype = params.utype;
2128
+ this.permitHash = params.permitHash;
2129
+ this.permit = params.permit;
2130
+ }
2131
+ /**
2132
+ * @param chainId - Chain to decrypt values from. Used to fetch the threshold network URL and use the correct permit.
2133
+ *
2134
+ * If not provided, the chainId will be fetched from the connected publicClient.
2135
+ *
2136
+ * Example:
2137
+ * ```typescript
2138
+ * const unsealed = await decryptHandle(ctHash, utype)
2139
+ * .setChainId(11155111)
2140
+ * .decrypt();
2141
+ * ```
2142
+ *
2143
+ * @returns The chainable DecryptHandlesBuilder instance.
2144
+ */
2145
+ setChainId(chainId) {
2146
+ this.chainId = chainId;
2147
+ return this;
2148
+ }
2149
+ getChainId() {
2150
+ return this.chainId;
2151
+ }
2152
+ /**
2153
+ * @param account - Account to decrypt values from. Used to fetch the correct permit.
2154
+ *
2155
+ * If not provided, the account will be fetched from the connected walletClient.
2156
+ *
2157
+ * Example:
2158
+ * ```typescript
2159
+ * const unsealed = await decryptHandle(ctHash, utype)
2160
+ * .setAccount('0x1234567890123456789012345678901234567890')
2161
+ * .decrypt();
2162
+ * ```
2163
+ *
2164
+ * @returns The chainable DecryptHandlesBuilder instance.
2165
+ */
2166
+ setAccount(account) {
2167
+ this.account = account;
2168
+ return this;
1974
2169
  }
1975
- return url;
1976
- }
1977
- function getThresholdNetworkUrlOrThrow(config, chainId) {
1978
- const supportedChain = getSupportedChainOrThrow(config, chainId);
1979
- const url = supportedChain.thresholdNetworkUrl;
1980
- if (!url) {
1981
- throw new CofhesdkError({
1982
- code: "THRESHOLD_NETWORK_URL_UNINITIALIZED" /* ThresholdNetworkUrlUninitialized */,
1983
- message: `Threshold network URL is not configured for chain <${chainId}>`,
1984
- hint: "Ensure this chain config includes a thresholdNetworkUrl property.",
1985
- context: { chainId }
1986
- });
2170
+ getAccount() {
2171
+ return this.account;
1987
2172
  }
1988
- return url;
1989
- }
1990
-
1991
- // core/fetchKeys.ts
1992
- var PUBLIC_KEY_LENGTH_MIN = 15e3;
1993
- var checkKeyValidity = (key, serializer) => {
1994
- if (key == null || key.length === 0)
1995
- return [false, `Key is null or empty <${key}>`];
1996
- try {
1997
- serializer(key);
1998
- return [true, `Key is valid`];
1999
- } catch (err) {
2000
- return [false, `Serialization failed <${err}> key length <${key.length}>`];
2173
+ /**
2174
+ * @param permitHash - Permit hash to decrypt values from. Used to fetch the correct permit.
2175
+ *
2176
+ * If not provided, the active permit for the chainId and account will be used.
2177
+ * If `setPermit()` is called, it will be used regardless of chainId, account, or permitHash.
2178
+ *
2179
+ * Example:
2180
+ * ```typescript
2181
+ * const unsealed = await decryptHandle(ctHash, utype)
2182
+ * .setPermitHash('0x1234567890123456789012345678901234567890')
2183
+ * .decrypt();
2184
+ * ```
2185
+ *
2186
+ * @returns The chainable DecryptHandlesBuilder instance.
2187
+ */
2188
+ setPermitHash(permitHash) {
2189
+ this.permitHash = permitHash;
2190
+ return this;
2001
2191
  }
2002
- };
2003
- var fetchFhePublicKey = async (coFheUrl, chainId, securityZone, tfhePublicKeyDeserializer, keysStorage) => {
2004
- const storedKey = keysStorage?.getFheKey(chainId, securityZone);
2005
- const [storedKeyValid] = checkKeyValidity(storedKey, tfhePublicKeyDeserializer);
2006
- if (storedKeyValid)
2007
- return [storedKey, false];
2008
- let pk_data = void 0;
2009
- try {
2010
- const pk_res = await fetch(`${coFheUrl}/GetNetworkPublicKey`, {
2011
- method: "POST",
2012
- headers: {
2013
- "Content-Type": "application/json"
2014
- },
2015
- body: JSON.stringify({ securityZone })
2016
- });
2017
- const json = await pk_res.json();
2018
- pk_data = json.publicKey;
2019
- } catch (err) {
2020
- throw new Error(`Error fetching FHE publicKey; fetching from CoFHE failed with error ${err}`);
2192
+ getPermitHash() {
2193
+ return this.permitHash;
2021
2194
  }
2022
- if (pk_data == null || typeof pk_data !== "string") {
2023
- throw new Error(`Error fetching FHE publicKey; fetched result invalid: missing or not a string`);
2195
+ /**
2196
+ * @param permit - Permit to decrypt values with. If provided, it will be used regardless of chainId, account, or permitHash.
2197
+ *
2198
+ * If not provided, the permit will be determined by chainId, account, and permitHash.
2199
+ *
2200
+ * Example:
2201
+ * ```typescript
2202
+ * const unsealed = await decryptHandle(ctHash, utype)
2203
+ * .setPermit(permit)
2204
+ * .decrypt();
2205
+ * ```
2206
+ *
2207
+ * @returns The chainable DecryptHandlesBuilder instance.
2208
+ */
2209
+ setPermit(permit) {
2210
+ this.permit = permit;
2211
+ return this;
2024
2212
  }
2025
- if (pk_data === "0x") {
2026
- throw new Error("Error fetching FHE publicKey; provided chain is not FHE enabled / not found");
2213
+ getPermit() {
2214
+ return this.permit;
2027
2215
  }
2028
- if (pk_data.length < PUBLIC_KEY_LENGTH_MIN) {
2029
- throw new Error(
2030
- `Error fetching FHE publicKey; got shorter than expected key length: ${pk_data.length}. Expected length >= ${PUBLIC_KEY_LENGTH_MIN}`
2031
- );
2216
+ async getThresholdNetworkUrl() {
2217
+ this.assertChainId();
2218
+ return getThresholdNetworkUrlOrThrow(this.config, this.chainId);
2032
2219
  }
2033
- try {
2034
- tfhePublicKeyDeserializer(pk_data);
2035
- } catch (err) {
2036
- throw new Error(`Error serializing FHE publicKey; ${err}`);
2220
+ validateUtypeOrThrow() {
2221
+ if (!isValidUtype(this.utype))
2222
+ throw new CofhesdkError({
2223
+ code: "INVALID_UTYPE" /* InvalidUtype */,
2224
+ message: `Invalid utype to decrypt to`,
2225
+ context: {
2226
+ utype: this.utype
2227
+ }
2228
+ });
2037
2229
  }
2038
- keysStorage?.setFheKey(chainId, securityZone, pk_data);
2039
- return [pk_data, true];
2040
- };
2041
- var fetchCrs = async (coFheUrl, chainId, securityZone, compactPkeCrsDeserializer, keysStorage) => {
2042
- const storedKey = keysStorage?.getCrs(chainId);
2043
- const [storedKeyValid] = checkKeyValidity(storedKey, compactPkeCrsDeserializer);
2044
- if (storedKeyValid)
2045
- return [storedKey, false];
2046
- let crs_data = void 0;
2047
- try {
2048
- const crs_res = await fetch(`${coFheUrl}/GetCrs`, {
2049
- method: "POST",
2050
- headers: {
2051
- "Content-Type": "application/json"
2052
- },
2053
- body: JSON.stringify({ securityZone })
2054
- });
2055
- const json = await crs_res.json();
2056
- crs_data = json.crs;
2057
- } catch (err) {
2058
- throw new Error(`Error fetching CRS; fetching failed with error ${err}`);
2230
+ async getResolvedPermit() {
2231
+ if (this.permit)
2232
+ return this.permit;
2233
+ this.assertChainId();
2234
+ this.assertAccount();
2235
+ if (this.permitHash) {
2236
+ const permit2 = await permits.getPermit(this.chainId, this.account, this.permitHash);
2237
+ if (!permit2) {
2238
+ throw new CofhesdkError({
2239
+ code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
2240
+ message: `Permit with hash <${this.permitHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
2241
+ hint: "Ensure the permit exists and is valid.",
2242
+ context: {
2243
+ chainId: this.chainId,
2244
+ account: this.account,
2245
+ permitHash: this.permitHash
2246
+ }
2247
+ });
2248
+ }
2249
+ return permit2;
2250
+ }
2251
+ const permit = await permits.getActivePermit(this.chainId, this.account);
2252
+ if (!permit) {
2253
+ throw new CofhesdkError({
2254
+ code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
2255
+ message: `Active permit not found for chainId <${this.chainId}> and account <${this.account}>`,
2256
+ hint: "Ensure a permit exists for this account on this chain.",
2257
+ context: {
2258
+ chainId: this.chainId,
2259
+ account: this.account
2260
+ }
2261
+ });
2262
+ }
2263
+ return permit;
2059
2264
  }
2060
- if (crs_data == null || typeof crs_data !== "string") {
2061
- throw new Error(`Error fetching CRS; invalid: missing or not a string`);
2265
+ /**
2266
+ * On hardhat, interact with MockZkVerifier contract instead of CoFHE
2267
+ */
2268
+ async mocksSealOutput(permit) {
2269
+ this.assertPublicClient();
2270
+ const mocksSealOutputDelay = this.config.mocks.sealOutputDelay;
2271
+ return cofheMocksSealOutput(this.ctHash, this.utype, permit, this.publicClient, mocksSealOutputDelay);
2062
2272
  }
2063
- try {
2064
- compactPkeCrsDeserializer(crs_data);
2065
- } catch (err) {
2066
- console.error(`Error serializing CRS ${err}`);
2067
- throw new Error(`Error serializing CRS; ${err}`);
2273
+ /**
2274
+ * In the production context, perform a true decryption with the CoFHE coprocessor.
2275
+ */
2276
+ async productionSealOutput(permit) {
2277
+ this.assertChainId();
2278
+ this.assertPublicClient();
2279
+ const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
2280
+ const permission = PermitUtils.getPermission(permit, true);
2281
+ const sealed = await tnSealOutputV2(this.ctHash, this.chainId, permission, thresholdNetworkUrl);
2282
+ return PermitUtils.unseal(permit, sealed);
2283
+ }
2284
+ /**
2285
+ * Final step of the decryption process. MUST BE CALLED LAST IN THE CHAIN.
2286
+ *
2287
+ * This will:
2288
+ * - Use a permit based on provided permit OR chainId + account + permitHash
2289
+ * - Check permit validity
2290
+ * - Call CoFHE `/sealoutput` with the permit, which returns a sealed (encrypted) item
2291
+ * - Unseal the sealed item with the permit
2292
+ * - Return the unsealed item
2293
+ *
2294
+ * Example:
2295
+ * ```typescript
2296
+ * const unsealed = await decryptHandle(ctHash, utype)
2297
+ * .setChainId(11155111) // optional
2298
+ * .setAccount('0x123...890') // optional
2299
+ * .decrypt(); // execute
2300
+ * ```
2301
+ *
2302
+ * @returns The unsealed item.
2303
+ */
2304
+ async decrypt() {
2305
+ this.validateUtypeOrThrow();
2306
+ const permit = await this.getResolvedPermit();
2307
+ PermitUtils.validate(permit);
2308
+ PermitUtils.isValid(permit);
2309
+ const chainId = permit._signedDomain.chainId;
2310
+ let unsealed;
2311
+ if (chainId === hardhat$1.id) {
2312
+ unsealed = await this.mocksSealOutput(permit);
2313
+ } else {
2314
+ unsealed = await this.productionSealOutput(permit);
2315
+ }
2316
+ return convertViaUtype(this.utype, unsealed);
2068
2317
  }
2069
- keysStorage?.setCrs(chainId, crs_data);
2070
- return [crs_data, true];
2071
- };
2072
- var fetchKeys = async (config, chainId, securityZone = 0, tfhePublicKeyDeserializer, compactPkeCrsDeserializer, keysStorage) => {
2073
- const coFheUrl = getCoFheUrlOrThrow(config, chainId);
2074
- return await Promise.all([
2075
- fetchFhePublicKey(coFheUrl, chainId, securityZone, tfhePublicKeyDeserializer, keysStorage),
2076
- fetchCrs(coFheUrl, chainId, securityZone, compactPkeCrsDeserializer, keysStorage)
2077
- ]);
2078
- };
2079
- var fetchMultichainKeys = async (config, securityZone = 0, tfhePublicKeyDeserializer, compactPkeCrsDeserializer, keysStorage) => {
2080
- await Promise.all(
2081
- config.supportedChains.filter((chain) => chain.id !== hardhat.id).map(
2082
- (chain) => fetchKeys(config, chain.id, securityZone, tfhePublicKeyDeserializer, compactPkeCrsDeserializer, keysStorage)
2083
- )
2084
- );
2085
2318
  };
2086
2319
 
2087
2320
  // core/client.ts
2321
+ var InitialConnectStore = {
2322
+ connected: false,
2323
+ connecting: false,
2324
+ connectError: void 0,
2325
+ chainId: void 0,
2326
+ account: void 0,
2327
+ publicClient: void 0,
2328
+ walletClient: void 0
2329
+ };
2088
2330
  function createCofhesdkClientBase(opts) {
2089
2331
  const keysStorage = createKeysStore(opts.config.fheKeyStorage);
2090
- let _publicClient = void 0;
2091
- let _walletClient = void 0;
2092
- const connectStore = createStore(() => ({
2093
- connected: false,
2094
- connecting: false,
2095
- connectError: void 0,
2096
- chainId: void 0,
2097
- account: void 0
2098
- }));
2332
+ const connectStore = createStore(() => InitialConnectStore);
2333
+ let connectAttemptId = 0;
2099
2334
  const updateConnectState = (partial) => {
2100
2335
  connectStore.setState((state) => ({ ...state, ...partial }));
2101
2336
  };
2102
- let _connectPromise = void 0;
2103
2337
  const _requireConnected = () => {
2104
2338
  const state = connectStore.getState();
2105
- const notConnected = !state.connected || !_publicClient || !_walletClient || !state.account || !state.chainId;
2339
+ const notConnected = !state.connected || !state.account || !state.chainId || !state.publicClient || !state.walletClient;
2106
2340
  if (notConnected) {
2107
2341
  throw new CofhesdkError({
2108
2342
  code: "NOT_CONNECTED" /* NotConnected */,
@@ -2112,55 +2346,49 @@ function createCofhesdkClientBase(opts) {
2112
2346
  connected: state.connected,
2113
2347
  account: state.account,
2114
2348
  chainId: state.chainId,
2115
- publicClient: _publicClient,
2116
- walletClient: _walletClient
2349
+ publicClient: state.publicClient,
2350
+ walletClient: state.walletClient
2117
2351
  }
2118
2352
  });
2119
2353
  }
2120
2354
  };
2121
- const keyFetchResult = resultWrapper(async () => {
2122
- if (opts.config.fheKeysPrefetching === "SUPPORTED_CHAINS") {
2123
- await fetchMultichainKeys(
2124
- opts.config,
2125
- 0,
2126
- opts.tfhePublicKeyDeserializer,
2127
- opts.compactPkeCrsDeserializer,
2128
- keysStorage
2129
- );
2130
- return true;
2131
- }
2132
- return false;
2133
- });
2134
2355
  async function connect(publicClient, walletClient) {
2135
2356
  const state = connectStore.getState();
2136
- if (state.connected && _publicClient === publicClient && _walletClient === walletClient) {
2137
- return Promise.resolve(ResultOk(true));
2138
- }
2139
- if (_connectPromise && _publicClient === publicClient && _walletClient === walletClient) {
2140
- return _connectPromise;
2357
+ if (state.connected && state.publicClient === publicClient && state.walletClient === walletClient)
2358
+ return;
2359
+ connectAttemptId += 1;
2360
+ const localAttemptId = connectAttemptId;
2361
+ updateConnectState({
2362
+ ...InitialConnectStore,
2363
+ connecting: true
2364
+ });
2365
+ try {
2366
+ const chainId = await getPublicClientChainID(publicClient);
2367
+ const account = await getWalletClientAccount(walletClient);
2368
+ if (localAttemptId !== connectAttemptId)
2369
+ return;
2370
+ updateConnectState({
2371
+ connected: true,
2372
+ connecting: false,
2373
+ connectError: void 0,
2374
+ chainId,
2375
+ account,
2376
+ publicClient,
2377
+ walletClient
2378
+ });
2379
+ } catch (e) {
2380
+ if (localAttemptId !== connectAttemptId)
2381
+ return;
2382
+ updateConnectState({
2383
+ ...InitialConnectStore,
2384
+ connectError: e
2385
+ });
2386
+ throw e;
2141
2387
  }
2142
- updateConnectState({ connecting: true, connectError: null, connected: false });
2143
- _connectPromise = resultWrapper(
2144
- // try
2145
- async () => {
2146
- _publicClient = publicClient;
2147
- _walletClient = walletClient;
2148
- const chainId = await getPublicClientChainID(publicClient);
2149
- const account = await getWalletClientAccount(walletClient);
2150
- updateConnectState({ connecting: false, connected: true, chainId, account });
2151
- return true;
2152
- },
2153
- // catch
2154
- (e) => {
2155
- updateConnectState({ connecting: false, connected: false, connectError: e });
2156
- return false;
2157
- },
2158
- // finally
2159
- () => {
2160
- _connectPromise = void 0;
2161
- }
2162
- );
2163
- return _connectPromise;
2388
+ }
2389
+ function disconnect() {
2390
+ connectAttemptId += 1;
2391
+ updateConnectState({ ...InitialConnectStore });
2164
2392
  }
2165
2393
  function encryptInputs(inputs) {
2166
2394
  const state = connectStore.getState();
@@ -2169,13 +2397,14 @@ function createCofhesdkClientBase(opts) {
2169
2397
  account: state.account ?? void 0,
2170
2398
  chainId: state.chainId ?? void 0,
2171
2399
  config: opts.config,
2172
- publicClient: _publicClient ?? void 0,
2173
- walletClient: _walletClient ?? void 0,
2400
+ publicClient: state.publicClient ?? void 0,
2401
+ walletClient: state.walletClient ?? void 0,
2174
2402
  zkvWalletClient: opts.config._internal?.zkvWalletClient,
2175
2403
  tfhePublicKeyDeserializer: opts.tfhePublicKeyDeserializer,
2176
2404
  compactPkeCrsDeserializer: opts.compactPkeCrsDeserializer,
2177
2405
  zkBuilderAndCrsGenerator: opts.zkBuilderAndCrsGenerator,
2178
2406
  initTfhe: opts.initTfhe,
2407
+ zkProveWorkerFn: opts.zkProveWorkerFn,
2179
2408
  keysStorage,
2180
2409
  requireConnected: _requireConnected
2181
2410
  });
@@ -2188,8 +2417,8 @@ function createCofhesdkClientBase(opts) {
2188
2417
  chainId: state.chainId ?? void 0,
2189
2418
  account: state.account ?? void 0,
2190
2419
  config: opts.config,
2191
- publicClient: _publicClient ?? void 0,
2192
- walletClient: _walletClient ?? void 0,
2420
+ publicClient: state.publicClient ?? void 0,
2421
+ walletClient: state.walletClient ?? void 0,
2193
2422
  requireConnected: _requireConnected
2194
2423
  });
2195
2424
  }
@@ -2215,48 +2444,64 @@ function createCofhesdkClientBase(opts) {
2215
2444
  getSnapshot: permits.getSnapshot,
2216
2445
  subscribe: permits.subscribe,
2217
2446
  // Creation methods (require connection)
2218
- createSelf: async (options) => resultWrapper(async () => {
2447
+ createSelf: async (options, clients) => {
2219
2448
  _requireConnected();
2220
- return permits.createSelf(options, _publicClient, _walletClient);
2221
- }),
2222
- createSharing: async (options) => resultWrapper(async () => {
2449
+ const { publicClient, walletClient } = clients ?? connectStore.getState();
2450
+ return permits.createSelf(options, publicClient, walletClient);
2451
+ },
2452
+ createSharing: async (options, clients) => {
2223
2453
  _requireConnected();
2224
- return permits.createSharing(options, _publicClient, _walletClient);
2225
- }),
2226
- importShared: async (options) => resultWrapper(async () => {
2454
+ const { publicClient, walletClient } = clients ?? connectStore.getState();
2455
+ return permits.createSharing(options, publicClient, walletClient);
2456
+ },
2457
+ importShared: async (options, clients) => {
2227
2458
  _requireConnected();
2228
- return permits.importShared(options, _publicClient, _walletClient);
2229
- }),
2459
+ const { publicClient, walletClient } = clients ?? connectStore.getState();
2460
+ return permits.importShared(options, publicClient, walletClient);
2461
+ },
2462
+ // Get or create methods (require connection)
2463
+ getOrCreateSelfPermit: async (chainId, account, options) => {
2464
+ _requireConnected();
2465
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2466
+ const { publicClient, walletClient } = connectStore.getState();
2467
+ return permits.getOrCreateSelfPermit(publicClient, walletClient, _chainId, _account, options);
2468
+ },
2469
+ getOrCreateSharingPermit: async (options, chainId, account) => {
2470
+ _requireConnected();
2471
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2472
+ const { publicClient, walletClient } = connectStore.getState();
2473
+ return permits.getOrCreateSharingPermit(publicClient, walletClient, options, _chainId, _account);
2474
+ },
2230
2475
  // Retrieval methods (auto-fill chainId/account)
2231
- getPermit: async (hash, chainId, account) => resultWrapper(async () => {
2476
+ getPermit: async (hash, chainId, account) => {
2232
2477
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2233
2478
  return permits.getPermit(_chainId, _account, hash);
2234
- }),
2235
- getPermits: async (chainId, account) => resultWrapper(async () => {
2479
+ },
2480
+ getPermits: async (chainId, account) => {
2236
2481
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2237
2482
  return permits.getPermits(_chainId, _account);
2238
- }),
2239
- getActivePermit: async (chainId, account) => resultWrapper(async () => {
2483
+ },
2484
+ getActivePermit: async (chainId, account) => {
2240
2485
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2241
2486
  return permits.getActivePermit(_chainId, _account);
2242
- }),
2243
- getActivePermitHash: async (chainId, account) => resultWrapper(async () => {
2487
+ },
2488
+ getActivePermitHash: async (chainId, account) => {
2244
2489
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2245
2490
  return permits.getActivePermitHash(_chainId, _account);
2246
- }),
2491
+ },
2247
2492
  // Mutation methods (auto-fill chainId/account)
2248
- selectActivePermit: async (hash, chainId, account) => resultWrapper(async () => {
2493
+ selectActivePermit: (hash, chainId, account) => {
2249
2494
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2250
2495
  return permits.selectActivePermit(_chainId, _account, hash);
2251
- }),
2252
- removePermit: async (hash, chainId, account) => resultWrapper(async () => {
2496
+ },
2497
+ removePermit: async (hash, chainId, account) => {
2253
2498
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2254
2499
  return permits.removePermit(_chainId, _account, hash);
2255
- }),
2256
- removeActivePermit: async (chainId, account) => resultWrapper(async () => {
2500
+ },
2501
+ removeActivePermit: async (chainId, account) => {
2257
2502
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2258
2503
  return permits.removeActivePermit(_chainId, _account);
2259
- }),
2504
+ },
2260
2505
  // Utils (no context needed)
2261
2506
  getHash: permits.getHash,
2262
2507
  serialize: permits.serialize,
@@ -2266,10 +2511,6 @@ function createCofhesdkClientBase(opts) {
2266
2511
  // Zustand reactive accessors (don't export store directly to prevent mutation)
2267
2512
  getSnapshot: connectStore.getState,
2268
2513
  subscribe: connectStore.subscribe,
2269
- // initialization results
2270
- initializationResults: {
2271
- keyFetchResult
2272
- },
2273
2514
  // flags (read-only: reflect snapshot)
2274
2515
  get connected() {
2275
2516
  return connectStore.getState().connected;
@@ -2280,6 +2521,7 @@ function createCofhesdkClientBase(opts) {
2280
2521
  // config & platform-specific (read-only)
2281
2522
  config: opts.config,
2282
2523
  connect,
2524
+ disconnect,
2283
2525
  encryptInputs,
2284
2526
  decryptHandle,
2285
2527
  permits: clientPermits
@@ -2287,9 +2529,9 @@ function createCofhesdkClientBase(opts) {
2287
2529
  // Example:
2288
2530
  // async encryptData(data: unknown) {
2289
2531
  // requireConnected();
2290
- // // Use _publicClient and _walletClient for implementation
2532
+ // // Use state.publicClient and state.walletClient for implementation
2291
2533
  // },
2292
2534
  };
2293
2535
  }
2294
2536
 
2295
- export { CofhesdkError, CofhesdkErrorCode, DecryptHandlesBuilder, EncryptInputsBuilder, EncryptStep, Encryptable, FheAllUTypes, FheTypes, FheUintUTypes, ResultErr, ResultErrOrInternal, ResultHttpError, ResultOk, ResultValidationError, createCofhesdkClientBase, createCofhesdkConfigBase, createKeysStore, fetchKeys, fetchMultichainKeys, getCofhesdkConfigItem, isCofhesdkError, isEncryptableItem, resultWrapper, resultWrapperSync };
2537
+ export { CofhesdkError, CofhesdkErrorCode, DecryptHandlesBuilder, EncryptInputsBuilder, EncryptStep, Encryptable, FheAllUTypes, FheTypes, FheUintUTypes, InitialConnectStore, assertCorrectEncryptedItemInput, createCofhesdkClientBase, createCofhesdkConfigBase, createKeysStore, fetchKeys, fheTypeToString, getCofhesdkConfigItem, isCofhesdkError, isEncryptableItem, isLastEncryptionStep, zkProveWithWorker };