@cofhe/sdk 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/CHANGELOG.md +14 -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/index.ts +3 -1
  11. package/core/baseBuilder.ts +30 -49
  12. package/core/client.test.ts +94 -77
  13. package/core/client.ts +133 -149
  14. package/core/clientTypes.ts +108 -0
  15. package/core/config.test.ts +22 -11
  16. package/core/config.ts +16 -9
  17. package/core/decrypt/decryptHandleBuilder.ts +51 -45
  18. package/core/decrypt/{tnSealOutput.ts → tnSealOutputV1.ts} +1 -1
  19. package/core/decrypt/tnSealOutputV2.ts +298 -0
  20. package/core/encrypt/cofheMocksZkVerifySign.ts +16 -10
  21. package/core/encrypt/encryptInputsBuilder.test.ts +132 -116
  22. package/core/encrypt/encryptInputsBuilder.ts +159 -111
  23. package/core/encrypt/encryptUtils.ts +6 -3
  24. package/core/encrypt/zkPackProveVerify.ts +70 -8
  25. package/core/error.ts +0 -2
  26. package/core/fetchKeys.test.ts +1 -18
  27. package/core/fetchKeys.ts +0 -26
  28. package/core/index.ts +29 -17
  29. package/core/keyStore.ts +65 -38
  30. package/core/permits.test.ts +253 -1
  31. package/core/permits.ts +80 -16
  32. package/core/types.ts +198 -152
  33. package/core/utils.ts +43 -1
  34. package/dist/adapters.d.cts +38 -20
  35. package/dist/adapters.d.ts +38 -20
  36. package/dist/chains.cjs +14 -1
  37. package/dist/chains.d.cts +23 -1
  38. package/dist/chains.d.ts +23 -1
  39. package/dist/chains.js +1 -1
  40. package/dist/{chunk-LU7BMUUT.js → chunk-UGBVZNRT.js} +39 -25
  41. package/dist/{chunk-GZCQQYVI.js → chunk-WEAZ25JO.js} +14 -2
  42. package/dist/{chunk-KFGPTJ6X.js → chunk-WGCRJCBR.js} +1920 -1692
  43. package/dist/{types-bB7wLj0q.d.cts → clientTypes-5_1nwtUe.d.cts} +308 -347
  44. package/dist/{types-PhwGgQvs.d.ts → clientTypes-Es7fyi65.d.ts} +308 -347
  45. package/dist/core.cjs +2872 -2632
  46. package/dist/core.d.cts +101 -6
  47. package/dist/core.d.ts +101 -6
  48. package/dist/core.js +3 -3
  49. package/dist/node.cjs +2716 -2520
  50. package/dist/node.d.cts +3 -3
  51. package/dist/node.d.ts +3 -3
  52. package/dist/node.js +4 -3
  53. package/dist/{permit-S9CnI6MF.d.cts → permit-fUSe6KKq.d.cts} +31 -15
  54. package/dist/{permit-S9CnI6MF.d.ts → permit-fUSe6KKq.d.ts} +31 -15
  55. package/dist/permits.cjs +39 -24
  56. package/dist/permits.d.cts +137 -148
  57. package/dist/permits.d.ts +137 -148
  58. package/dist/permits.js +1 -1
  59. package/dist/web.cjs +2929 -2518
  60. package/dist/web.d.cts +21 -5
  61. package/dist/web.d.ts +21 -5
  62. package/dist/web.js +185 -9
  63. package/dist/zkProve.worker.cjs +93 -0
  64. package/dist/zkProve.worker.d.cts +2 -0
  65. package/dist/zkProve.worker.d.ts +2 -0
  66. package/dist/zkProve.worker.js +91 -0
  67. package/node/client.test.ts +20 -25
  68. package/node/encryptInputs.test.ts +18 -38
  69. package/node/index.ts +1 -0
  70. package/package.json +14 -14
  71. package/permits/index.ts +1 -0
  72. package/permits/localstorage.test.ts +0 -1
  73. package/permits/permit.test.ts +25 -22
  74. package/permits/permit.ts +30 -21
  75. package/permits/sealing.test.ts +3 -3
  76. package/permits/sealing.ts +2 -2
  77. package/permits/store.ts +5 -7
  78. package/permits/test-utils.ts +1 -1
  79. package/permits/types.ts +17 -0
  80. package/permits/utils.ts +0 -1
  81. package/permits/validation.ts +24 -4
  82. package/web/client.web.test.ts +20 -25
  83. package/web/config.web.test.ts +0 -2
  84. package/web/encryptInputs.web.test.ts +31 -54
  85. package/web/index.ts +65 -1
  86. package/web/storage.ts +19 -5
  87. package/web/worker.builder.web.test.ts +148 -0
  88. package/web/worker.config.web.test.ts +329 -0
  89. package/web/worker.output.web.test.ts +84 -0
  90. package/web/workerManager.test.ts +80 -0
  91. package/web/workerManager.ts +214 -0
  92. package/web/workerManager.web.test.ts +114 -0
  93. package/web/zkProve.worker.ts +133 -0
  94. package/core/result.test.ts +0 -180
  95. package/core/result.ts +0 -67
  96. package/core/test-utils.ts +0 -45
@@ -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-WEAZ25JO.js';
2
+ import { permitStore, PermitUtils } from './chunk-UGBVZNRT.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,969 +328,881 @@ 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 = [
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 = [
461
536
  {
462
537
  type: "function",
463
- name: "acl",
538
+ name: "exists",
464
539
  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" }],
540
+ outputs: [{ name: "", type: "bool", internalType: "bool" }],
473
541
  stateMutability: "pure"
474
542
  },
475
543
  {
476
544
  type: "function",
477
- name: "exists",
478
- inputs: [],
479
- outputs: [{ name: "", type: "bool", internalType: "bool" }],
480
- stateMutability: "pure"
545
+ name: "insertCtHash",
546
+ inputs: [
547
+ { name: "ctHash", type: "uint256", internalType: "uint256" },
548
+ { name: "value", type: "uint256", internalType: "uint256" }
549
+ ],
550
+ outputs: [],
551
+ stateMutability: "nonpayable"
481
552
  },
482
553
  {
483
554
  type: "function",
484
- name: "initialize",
555
+ name: "insertPackedCtHashes",
485
556
  inputs: [
486
- { name: "_taskManager", type: "address", internalType: "address" },
487
- { name: "_acl", type: "address", internalType: "address" }
557
+ { name: "ctHashes", type: "uint256[]", internalType: "uint256[]" },
558
+ { name: "values", type: "uint256[]", internalType: "uint256[]" }
488
559
  ],
489
560
  outputs: [],
490
561
  stateMutability: "nonpayable"
491
562
  },
492
563
  {
493
564
  type: "function",
494
- name: "queryDecrypt",
565
+ name: "zkVerify",
495
566
  inputs: [
496
- { name: "ctHash", type: "uint256", internalType: "uint256" },
497
- { 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: [
498
574
  {
499
- name: "permission",
575
+ name: "",
500
576
  type: "tuple",
501
- internalType: "struct Permission",
577
+ internalType: "struct EncryptedInput",
502
578
  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" }
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" }
515
583
  ]
516
584
  }
517
585
  ],
518
- outputs: [
519
- { name: "allowed", type: "bool", internalType: "bool" },
520
- { name: "error", type: "string", internalType: "string" },
586
+ stateMutability: "nonpayable"
587
+ },
588
+ {
589
+ type: "function",
590
+ name: "zkVerifyCalcCtHash",
591
+ inputs: [
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" },
521
596
  { name: "", type: "uint256", internalType: "uint256" }
522
597
  ],
598
+ outputs: [{ name: "ctHash", type: "uint256", internalType: "uint256" }],
523
599
  stateMutability: "view"
524
600
  },
525
601
  {
526
602
  type: "function",
527
- name: "querySealOutput",
603
+ name: "zkVerifyCalcCtHashesPacked",
528
604
  inputs: [
529
- { name: "ctHash", type: "uint256", internalType: "uint256" },
530
- { name: "", type: "uint256", internalType: "uint256" },
531
- {
532
- name: "permission",
533
- type: "tuple",
534
- internalType: "struct Permission",
535
- 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" }
548
- ]
549
- }
550
- ],
551
- outputs: [
552
- { name: "allowed", type: "bool", internalType: "bool" },
553
- { name: "error", type: "string", internalType: "string" },
554
- { name: "", type: "bytes32", internalType: "bytes32" }
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" }
555
610
  ],
611
+ outputs: [{ name: "ctHashes", type: "uint256[]", internalType: "uint256[]" }],
556
612
  stateMutability: "view"
557
613
  },
558
614
  {
559
615
  type: "function",
560
- name: "seal",
616
+ name: "zkVerifyPacked",
561
617
  inputs: [
562
- { name: "input", type: "uint256", internalType: "uint256" },
563
- { 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" }
564
623
  ],
565
- outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
566
- stateMutability: "pure"
567
- },
568
- {
569
- type: "function",
570
- name: "taskManager",
571
- inputs: [],
572
- outputs: [{ name: "", type: "address", internalType: "contract TaskManager" }],
573
- stateMutability: "view"
574
- },
575
- {
576
- type: "function",
577
- name: "unseal",
578
- inputs: [
579
- { name: "hashed", type: "bytes32", internalType: "bytes32" },
580
- { name: "key", type: "bytes32", internalType: "bytes32" }
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
+ }
581
636
  ],
582
- outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
583
- stateMutability: "pure"
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
+ var MocksZkVerifierAddress = "0x0000000000000000000000000000000000000100";
642
+ var MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY = "0x6C8D7F768A6BB4AAFE85E8A2F5A9680355239C7E14646ED62B044E39DE154512";
643
+ var MOCKS_ZK_VERIFIER_SIGNER_ADDRESS = "0x6E12D8C87503D4287c294f2Fdef96ACd9DFf6bd2";
644
+ function createMockZkVerifierSigner() {
645
+ return createWalletClient({
646
+ chain: hardhat,
647
+ transport: http(),
648
+ account: privateKeyToAccount(MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY)
606
649
  });
607
- if (error != "") {
608
- throw new CofhesdkError({
609
- code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
610
- message: `mocks querySealOutput call failed: ${error}`
611
- });
650
+ }
651
+ async function cofheMocksCheckEncryptableBits(items) {
652
+ let totalBits = 0;
653
+ for (const item of items) {
654
+ switch (item.utype) {
655
+ case 0 /* Bool */: {
656
+ totalBits += 1;
657
+ break;
658
+ }
659
+ case 2 /* Uint8 */: {
660
+ totalBits += 8;
661
+ break;
662
+ }
663
+ case 3 /* Uint16 */: {
664
+ totalBits += 16;
665
+ break;
666
+ }
667
+ case 4 /* Uint32 */: {
668
+ totalBits += 32;
669
+ break;
670
+ }
671
+ case 5 /* Uint64 */: {
672
+ totalBits += 64;
673
+ break;
674
+ }
675
+ case 6 /* Uint128 */: {
676
+ totalBits += 128;
677
+ break;
678
+ }
679
+ case 7 /* Uint160 */: {
680
+ totalBits += 160;
681
+ break;
682
+ }
683
+ }
612
684
  }
613
- if (allowed == false) {
685
+ if (totalBits > MAX_ENCRYPTABLE_BITS) {
614
686
  throw new CofhesdkError({
615
- code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
616
- message: `mocks querySealOutput call failed: ACL Access Denied (NotAllowed)`
687
+ code: "ZK_PACK_FAILED" /* ZkPackFailed */,
688
+ message: `Total bits ${totalBits} exceeds ${MAX_ENCRYPTABLE_BITS}`,
689
+ hint: `Ensure that the total bits of the items to encrypt does not exceed ${MAX_ENCRYPTABLE_BITS}`,
690
+ context: {
691
+ totalBits,
692
+ maxBits: MAX_ENCRYPTABLE_BITS,
693
+ items
694
+ }
617
695
  });
618
696
  }
619
- const sealedBigInt = BigInt(result);
620
- const sealingKeyBigInt = BigInt(permission.sealingKey);
621
- const unsealed = sealedBigInt ^ sealingKeyBigInt;
622
- return unsealed;
623
697
  }
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
- };
698
+ async function calcCtHashes(items, account, securityZone, publicClient) {
699
+ const calcCtHashesArgs = [
700
+ items.map(({ data }) => BigInt(data)),
701
+ items.map(({ utype }) => utype),
702
+ account,
703
+ securityZone,
704
+ BigInt(hardhat.id)
705
+ ];
706
+ let ctHashes;
635
707
  try {
636
- const sealOutputRes = await fetch(`${thresholdNetworkUrl}/sealoutput`, {
637
- method: "POST",
638
- headers: {
639
- "Content-Type": "application/json"
640
- },
641
- body: JSON.stringify(body)
708
+ ctHashes = await publicClient.readContract({
709
+ address: MocksZkVerifierAddress,
710
+ abi: MockZkVerifierAbi,
711
+ functionName: "zkVerifyCalcCtHashesPacked",
712
+ args: calcCtHashesArgs
642
713
  });
643
- sealOutputResult = await sealOutputRes.json();
644
- sealed = sealOutputResult.sealed;
645
- errorMessage = sealOutputResult.error_message;
646
- } catch (e) {
714
+ } catch (err) {
647
715
  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,
716
+ code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
717
+ message: `mockZkVerifySign calcCtHashes failed while calling zkVerifyCalcCtHashesPacked`,
718
+ cause: err instanceof Error ? err : void 0,
652
719
  context: {
653
- thresholdNetworkUrl,
654
- body
720
+ address: MocksZkVerifierAddress,
721
+ items,
722
+ account,
723
+ securityZone,
724
+ publicClient,
725
+ calcCtHashesArgs
655
726
  }
656
727
  });
657
728
  }
658
- if (sealed == null) {
729
+ if (ctHashes.length !== items.length) {
659
730
  throw new CofhesdkError({
660
- code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
661
- message: `sealOutput request returned no data | Caused by: ${errorMessage}`,
731
+ code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
732
+ message: `mockZkVerifySign calcCtHashes returned incorrect number of ctHashes`,
662
733
  context: {
663
- thresholdNetworkUrl,
664
- body,
665
- sealOutputResult
734
+ items,
735
+ account,
736
+ securityZone,
737
+ publicClient,
738
+ calcCtHashesArgs,
739
+ ctHashes
666
740
  }
667
741
  });
668
742
  }
669
- return sealed;
743
+ return items.map((item, index) => ({
744
+ ...item,
745
+ ctHash: ctHashes[index]
746
+ }));
670
747
  }
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
748
+ async function insertCtHashes(items, walletClient) {
749
+ const insertPackedCtHashesArgs = [items.map(({ ctHash }) => ctHash), items.map(({ data }) => BigInt(data))];
750
+ try {
751
+ const account = walletClient.account;
752
+ await walletClient.writeContract({
753
+ address: MocksZkVerifierAddress,
754
+ abi: MockZkVerifierAbi,
755
+ functionName: "insertPackedCtHashes",
756
+ args: insertPackedCtHashesArgs,
757
+ chain: hardhat,
758
+ account
759
+ });
760
+ } catch (err) {
761
+ throw new CofhesdkError({
762
+ code: "ZK_MOCKS_INSERT_CT_HASHES_FAILED" /* ZkMocksInsertCtHashesFailed */,
763
+ message: `mockZkVerifySign insertPackedCtHashes failed while calling insertPackedCtHashes`,
764
+ cause: err instanceof Error ? err : void 0,
765
+ context: {
766
+ items,
767
+ walletClient,
768
+ insertPackedCtHashesArgs
769
+ }
686
770
  });
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
- }
710
- getChainId() {
711
- return this.chainId;
712
771
  }
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
- });
772
+ }
773
+ async function createProofSignatures(items, securityZone) {
774
+ let signatures = [];
775
+ let encInputSignerClient;
776
+ try {
777
+ encInputSignerClient = createMockZkVerifierSigner();
778
+ } catch (err) {
779
+ throw new CofhesdkError({
780
+ code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
781
+ message: `mockZkVerifySign createProofSignatures failed while creating wallet client`,
782
+ cause: err instanceof Error ? err : void 0,
783
+ context: {
784
+ MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY
809
785
  }
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
- }
786
+ });
787
+ }
788
+ try {
789
+ for (const item of items) {
790
+ const packedData = encodePacked(["uint256", "int32", "uint8"], [BigInt(item.data), securityZone, item.utype]);
791
+ const messageHash = keccak256(packedData);
792
+ const ethSignedHash = hashMessage({ raw: toBytes(messageHash) });
793
+ const signature = await encInputSignerClient.signMessage({
794
+ message: { raw: toBytes(ethSignedHash) },
795
+ account: encInputSignerClient.account
822
796
  });
797
+ signatures.push(signature);
823
798
  }
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);
799
+ } catch (err) {
800
+ throw new CofhesdkError({
801
+ code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
802
+ message: `mockZkVerifySign createProofSignatures failed while calling signMessage`,
803
+ cause: err instanceof Error ? err : void 0,
804
+ context: {
805
+ items,
806
+ securityZone
875
807
  }
876
- return convertViaUtype(this.utype, unsealed);
877
808
  });
878
809
  }
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) {
810
+ if (signatures.length !== items.length) {
953
811
  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}`,
812
+ code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
813
+ message: `mockZkVerifySign createProofSignatures returned incorrect number of signatures`,
957
814
  context: {
958
- totalBits,
959
- maxBits: MAX_ENCRYPTABLE_BITS,
960
- items
815
+ items,
816
+ securityZone
961
817
  }
962
818
  });
963
819
  }
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;
820
+ return signatures;
821
+ }
822
+ async function cofheMocksZkVerifySign(items, account, securityZone, publicClient, walletClient, zkvWalletClient) {
823
+ const _walletClient = zkvWalletClient ?? createMockZkVerifierSigner();
824
+ const encryptableItems = await calcCtHashes(items, account, securityZone, publicClient);
825
+ await insertCtHashes(encryptableItems, _walletClient);
826
+ const signatures = await createProofSignatures(encryptableItems, securityZone);
827
+ return encryptableItems.map((item, index) => ({
828
+ ct_hash: item.ctHash.toString(),
829
+ signature: signatures[index]
830
+ }));
831
+ }
832
+ var CofhesdkConfigSchema = z.object({
833
+ /** Environment that the SDK is running in */
834
+ environment: z.enum(["node", "hardhat", "web", "react"]).optional().default("node"),
835
+ /** List of supported chain configurations */
836
+ supportedChains: z.array(z.custom()),
837
+ /** How permits are generated */
838
+ permitGeneration: z.enum(["ON_CONNECT", "ON_DECRYPT_HANDLES", "MANUAL"]).optional().default("ON_CONNECT"),
839
+ /** Default permit expiration in seconds, default is 30 days */
840
+ defaultPermitExpiration: z.number().optional().default(60 * 60 * 24 * 30),
841
+ /** Storage method for fhe keys (defaults to indexedDB on web, filesystem on node) */
842
+ fheKeyStorage: z.object({
843
+ getItem: z.function().args(z.string()).returns(z.promise(z.any())),
844
+ setItem: z.function().args(z.string(), z.any()).returns(z.promise(z.void())),
845
+ removeItem: z.function().args(z.string()).returns(z.promise(z.void()))
846
+ }).or(z.null()).default(null),
847
+ /** Whether to use Web Workers for ZK proof generation (web platform only) */
848
+ useWorkers: z.boolean().optional().default(true),
849
+ /** Mocks configs */
850
+ mocks: z.object({
851
+ sealOutputDelay: z.number().optional().default(0)
852
+ }).optional().default({ sealOutputDelay: 0 }),
853
+ /** Internal configuration */
854
+ _internal: z.object({
855
+ zkvWalletClient: z.any().optional()
856
+ }).optional()
857
+ });
858
+ function createCofhesdkConfigBase(config) {
859
+ const result = CofhesdkConfigSchema.safeParse(config);
860
+ if (!result.success) {
861
+ throw new Error(`Invalid cofhesdk configuration: ${result.error.message}`);
988
862
  }
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;
863
+ return result.data;
864
+ }
865
+ var getCofhesdkConfigItem = (config, key) => {
866
+ return config[key];
994
867
  };
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
1003
- };
1004
- const body = JSON.stringify(payload);
1005
- try {
1006
- const response = await fetch(`${verifierUrl}/verify`, {
1007
- method: "POST",
1008
- headers: {
1009
- "Content-Type": "application/json"
1010
- },
1011
- body
868
+ function getSupportedChainOrThrow(config, chainId) {
869
+ const supportedChain = config.supportedChains.find((chain) => chain.id === chainId);
870
+ if (!supportedChain) {
871
+ throw new CofhesdkError({
872
+ code: "UNSUPPORTED_CHAIN" /* UnsupportedChain */,
873
+ message: `Config does not support chain <${chainId}>`,
874
+ hint: "Ensure config passed to client has been created with this chain in the config.supportedChains array.",
875
+ context: {
876
+ chainId,
877
+ supportedChainIds: config.supportedChains.map((c) => c.id)
878
+ }
1012
879
  });
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
- };
880
+ }
881
+ return supportedChain;
882
+ }
883
+ function getCoFheUrlOrThrow(config, chainId) {
884
+ const supportedChain = getSupportedChainOrThrow(config, chainId);
885
+ const url = supportedChain.coFheUrl;
886
+ if (!url) {
887
+ throw new CofhesdkError({
888
+ code: "MISSING_CONFIG" /* MissingConfig */,
889
+ message: `CoFHE URL is not configured for chain <${chainId}>`,
890
+ hint: "Ensure this chain config includes a coFheUrl property.",
891
+ context: { chainId }
1032
892
  });
1033
- } catch (e) {
893
+ }
894
+ return url;
895
+ }
896
+ function getZkVerifierUrlOrThrow(config, chainId) {
897
+ const supportedChain = getSupportedChainOrThrow(config, chainId);
898
+ const url = supportedChain.verifierUrl;
899
+ if (!url) {
1034
900
  throw new CofhesdkError({
1035
- code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
1036
- message: `ZK proof verification failed`,
1037
- cause: e instanceof Error ? e : void 0
901
+ code: "ZK_VERIFIER_URL_UNINITIALIZED" /* ZkVerifierUrlUninitialized */,
902
+ message: `ZK verifier URL is not configured for chain <${chainId}>`,
903
+ hint: "Ensure this chain config includes a verifierUrl property.",
904
+ context: { chainId }
1038
905
  });
1039
906
  }
907
+ return url;
908
+ }
909
+ function getThresholdNetworkUrlOrThrow(config, chainId) {
910
+ const supportedChain = getSupportedChainOrThrow(config, chainId);
911
+ const url = supportedChain.thresholdNetworkUrl;
912
+ if (!url) {
913
+ throw new CofhesdkError({
914
+ code: "THRESHOLD_NETWORK_URL_UNINITIALIZED" /* ThresholdNetworkUrlUninitialized */,
915
+ message: `Threshold network URL is not configured for chain <${chainId}>`,
916
+ hint: "Ensure this chain config includes a thresholdNetworkUrl property.",
917
+ context: { chainId }
918
+ });
919
+ }
920
+ return url;
921
+ }
922
+ function isValidPersistedState(state) {
923
+ if (state && typeof state === "object") {
924
+ if ("fhe" in state && "crs" in state) {
925
+ return true;
926
+ } else {
927
+ throw new Error(
928
+ "Invalid persisted state structure for KeysStore. Is object but doesn't contain required fields 'fhe' and 'crs'."
929
+ );
930
+ }
931
+ }
932
+ return false;
933
+ }
934
+ var DEFAULT_KEYS_STORE = {
935
+ fhe: {},
936
+ crs: {}
1040
937
  };
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
- }
938
+ function isStoreWithPersist(store) {
939
+ return "persist" in store;
940
+ }
941
+ function createKeysStore(storage) {
942
+ const keysStore = storage ? createStoreWithPersit(storage) : createStore()(() => ({
943
+ fhe: {},
944
+ crs: {}
945
+ }));
946
+ const getFheKey = (chainId, securityZone = 0) => {
947
+ if (chainId == null || securityZone == null)
948
+ return void 0;
949
+ const stored = keysStore.getState().fhe[chainId]?.[securityZone];
950
+ return stored;
951
+ };
952
+ const getCrs = (chainId) => {
953
+ if (chainId == null)
954
+ return void 0;
955
+ const stored = keysStore.getState().crs[chainId];
956
+ return stored;
957
+ };
958
+ const setFheKey = (chainId, securityZone, key) => {
959
+ keysStore.setState(
960
+ produce((state) => {
961
+ if (state.fhe[chainId] == null)
962
+ state.fhe[chainId] = {};
963
+ state.fhe[chainId][securityZone] = key;
964
+ })
965
+ );
966
+ };
967
+ const setCrs = (chainId, crs) => {
968
+ keysStore.setState(
969
+ produce((state) => {
970
+ state.crs[chainId] = crs;
971
+ })
972
+ );
973
+ };
974
+ const clearKeysStorage = async () => {
975
+ if (storage) {
976
+ await storage.removeItem("cofhesdk-keys");
1186
977
  }
1187
- }
1188
- if (totalBits > MAX_ENCRYPTABLE_BITS) {
1189
- 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}`,
1193
- context: {
1194
- totalBits,
1195
- maxBits: MAX_ENCRYPTABLE_BITS,
1196
- items
978
+ };
979
+ const rehydrateKeysStore = async () => {
980
+ if (!isStoreWithPersist(keysStore))
981
+ return;
982
+ if (keysStore.persist.hasHydrated())
983
+ return;
984
+ await keysStore.persist.rehydrate();
985
+ };
986
+ return {
987
+ store: keysStore,
988
+ getFheKey,
989
+ getCrs,
990
+ setFheKey,
991
+ setCrs,
992
+ clearKeysStorage,
993
+ rehydrateKeysStore
994
+ };
995
+ }
996
+ function createStoreWithPersit(storage) {
997
+ const result = createStore()(
998
+ persist(() => DEFAULT_KEYS_STORE, {
999
+ // 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)
1000
+ skipHydration: true,
1001
+ // 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
1002
+ onRehydrateStorage: () => (_state, _error) => {
1003
+ if (_error)
1004
+ throw new Error(`onRehydrateStorage: Error rehydrating keys store: ${_error}`);
1005
+ },
1006
+ name: "cofhesdk-keys",
1007
+ storage: createJSONStorage(() => storage),
1008
+ merge: (persistedState, currentState) => {
1009
+ const persisted = isValidPersistedState(persistedState) ? persistedState : DEFAULT_KEYS_STORE;
1010
+ const current = currentState;
1011
+ const mergedFhe = { ...persisted.fhe };
1012
+ const allChainIds = /* @__PURE__ */ new Set([...Object.keys(current.fhe), ...Object.keys(persisted.fhe)]);
1013
+ for (const chainId of allChainIds) {
1014
+ const persistedZones = persisted.fhe[chainId] || {};
1015
+ const currentZones = current.fhe[chainId] || {};
1016
+ mergedFhe[chainId] = { ...persistedZones, ...currentZones };
1017
+ }
1018
+ const mergedCrs = { ...persisted.crs, ...current.crs };
1019
+ return {
1020
+ fhe: mergedFhe,
1021
+ crs: mergedCrs
1022
+ };
1197
1023
  }
1198
- });
1199
- }
1024
+ })
1025
+ );
1026
+ return result;
1200
1027
  }
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;
1028
+
1029
+ // core/fetchKeys.ts
1030
+ var PUBLIC_KEY_LENGTH_MIN = 15e3;
1031
+ var checkKeyValidity = (key, serializer) => {
1032
+ if (key == null || key.length === 0)
1033
+ return [false, `Key is null or empty <${key}>`];
1210
1034
  try {
1211
- ctHashes = await publicClient.readContract({
1212
- address: MocksZkVerifierAddress,
1213
- abi: MockZkVerifierAbi,
1214
- functionName: "zkVerifyCalcCtHashesPacked",
1215
- args: calcCtHashesArgs
1216
- });
1035
+ serializer(key);
1036
+ return [true, `Key is valid`];
1217
1037
  } catch (err) {
1218
- 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,
1222
- context: {
1223
- address: MocksZkVerifierAddress,
1224
- items,
1225
- account,
1226
- securityZone,
1227
- publicClient,
1228
- calcCtHashesArgs
1229
- }
1230
- });
1038
+ return [false, `Serialization failed <${err}> key length <${key.length}>`];
1231
1039
  }
1232
- if (ctHashes.length !== items.length) {
1233
- throw new CofhesdkError({
1234
- code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
1235
- message: `mockZkVerifySign calcCtHashes returned incorrect number of ctHashes`,
1236
- context: {
1237
- items,
1238
- account,
1239
- securityZone,
1240
- publicClient,
1241
- calcCtHashesArgs,
1242
- ctHashes
1243
- }
1040
+ };
1041
+ var fetchFhePublicKey = async (coFheUrl, chainId, securityZone, tfhePublicKeyDeserializer, keysStorage) => {
1042
+ const storedKey = keysStorage?.getFheKey(chainId, securityZone);
1043
+ const [storedKeyValid] = checkKeyValidity(storedKey, tfhePublicKeyDeserializer);
1044
+ if (storedKeyValid)
1045
+ return [storedKey, false];
1046
+ let pk_data = void 0;
1047
+ try {
1048
+ const pk_res = await fetch(`${coFheUrl}/GetNetworkPublicKey`, {
1049
+ method: "POST",
1050
+ headers: {
1051
+ "Content-Type": "application/json"
1052
+ },
1053
+ body: JSON.stringify({ securityZone })
1244
1054
  });
1055
+ const json = await pk_res.json();
1056
+ pk_data = json.publicKey;
1057
+ } catch (err) {
1058
+ throw new Error(`Error fetching FHE publicKey; fetching from CoFHE failed with error ${err}`);
1059
+ }
1060
+ if (pk_data == null || typeof pk_data !== "string") {
1061
+ throw new Error(`Error fetching FHE publicKey; fetched result invalid: missing or not a string`);
1062
+ }
1063
+ if (pk_data === "0x") {
1064
+ throw new Error("Error fetching FHE publicKey; provided chain is not FHE enabled / not found");
1065
+ }
1066
+ if (pk_data.length < PUBLIC_KEY_LENGTH_MIN) {
1067
+ throw new Error(
1068
+ `Error fetching FHE publicKey; got shorter than expected key length: ${pk_data.length}. Expected length >= ${PUBLIC_KEY_LENGTH_MIN}`
1069
+ );
1245
1070
  }
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
1071
  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
1072
+ tfhePublicKeyDeserializer(pk_data);
1073
+ } catch (err) {
1074
+ throw new Error(`Error serializing FHE publicKey; ${err}`);
1075
+ }
1076
+ keysStorage?.setFheKey(chainId, securityZone, pk_data);
1077
+ return [pk_data, true];
1078
+ };
1079
+ var fetchCrs = async (coFheUrl, chainId, securityZone, compactPkeCrsDeserializer, keysStorage) => {
1080
+ const storedKey = keysStorage?.getCrs(chainId);
1081
+ const [storedKeyValid] = checkKeyValidity(storedKey, compactPkeCrsDeserializer);
1082
+ if (storedKeyValid)
1083
+ return [storedKey, false];
1084
+ let crs_data = void 0;
1085
+ try {
1086
+ const crs_res = await fetch(`${coFheUrl}/GetCrs`, {
1087
+ method: "POST",
1088
+ headers: {
1089
+ "Content-Type": "application/json"
1090
+ },
1091
+ body: JSON.stringify({ securityZone })
1262
1092
  });
1093
+ const json = await crs_res.json();
1094
+ crs_data = json.crs;
1095
+ } catch (err) {
1096
+ throw new Error(`Error fetching CRS; fetching failed with error ${err}`);
1097
+ }
1098
+ if (crs_data == null || typeof crs_data !== "string") {
1099
+ throw new Error(`Error fetching CRS; invalid: missing or not a string`);
1100
+ }
1101
+ try {
1102
+ compactPkeCrsDeserializer(crs_data);
1263
1103
  } catch (err) {
1104
+ console.error(`Error serializing CRS ${err}`);
1105
+ throw new Error(`Error serializing CRS; ${err}`);
1106
+ }
1107
+ keysStorage?.setCrs(chainId, crs_data);
1108
+ return [crs_data, true];
1109
+ };
1110
+ var fetchKeys = async (config, chainId, securityZone = 0, tfhePublicKeyDeserializer, compactPkeCrsDeserializer, keysStorage) => {
1111
+ const coFheUrl = getCoFheUrlOrThrow(config, chainId);
1112
+ return await Promise.all([
1113
+ fetchFhePublicKey(coFheUrl, chainId, securityZone, tfhePublicKeyDeserializer, keysStorage),
1114
+ fetchCrs(coFheUrl, chainId, securityZone, compactPkeCrsDeserializer, keysStorage)
1115
+ ]);
1116
+ };
1117
+ var BaseBuilder = class {
1118
+ config;
1119
+ publicClient;
1120
+ walletClient;
1121
+ chainId;
1122
+ account;
1123
+ constructor(params) {
1124
+ if (!params.config) {
1125
+ throw new CofhesdkError({
1126
+ code: "MISSING_CONFIG" /* MissingConfig */,
1127
+ message: "Builder config is undefined",
1128
+ hint: "Ensure client has been created with a config.",
1129
+ context: {
1130
+ config: params.config
1131
+ }
1132
+ });
1133
+ }
1134
+ this.config = params.config;
1135
+ this.publicClient = params.publicClient;
1136
+ this.walletClient = params.walletClient;
1137
+ this.chainId = params.chainId;
1138
+ this.account = params.account;
1139
+ params.requireConnected?.();
1140
+ }
1141
+ /**
1142
+ * Asserts that this.chainId is populated
1143
+ * @throws {CofhesdkError} If chainId is not set
1144
+ */
1145
+ assertChainId() {
1146
+ if (this.chainId)
1147
+ return;
1264
1148
  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,
1149
+ code: "CHAIN_ID_UNINITIALIZED" /* ChainIdUninitialized */,
1150
+ message: "Chain ID is not set",
1151
+ hint: "Ensure client.connect() has been called and awaited, or use setChainId(...) to set the chainId explicitly.",
1268
1152
  context: {
1269
- items,
1270
- walletClient,
1271
- insertPackedCtHashesArgs
1153
+ chainId: this.chainId
1272
1154
  }
1273
1155
  });
1274
1156
  }
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) {
1157
+ /**
1158
+ * Asserts that this.account is populated
1159
+ * @throws {CofhesdkError} If account is not set
1160
+ */
1161
+ assertAccount() {
1162
+ if (this.account)
1163
+ return;
1286
1164
  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,
1165
+ code: "ACCOUNT_UNINITIALIZED" /* AccountUninitialized */,
1166
+ message: "Account is not set",
1167
+ hint: "Ensure client.connect() has been called and awaited, or use setAccount(...) to set the account explicitly.",
1290
1168
  context: {
1291
- MocksEncryptedInputSignerPkey
1169
+ account: this.account
1292
1170
  }
1293
1171
  });
1294
1172
  }
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) {
1173
+ /**
1174
+ * Asserts that this.publicClient is populated
1175
+ * @throws {CofhesdkError} If publicClient is not set
1176
+ */
1177
+ assertPublicClient() {
1178
+ if (this.publicClient)
1179
+ return;
1307
1180
  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
1181
+ code: "MISSING_PUBLIC_CLIENT" /* MissingPublicClient */,
1182
+ message: "Public client not found",
1183
+ hint: "Ensure client.connect() has been called with a publicClient.",
1184
+ context: {
1185
+ publicClient: this.publicClient
1314
1186
  }
1315
1187
  });
1316
1188
  }
1317
- if (signatures.length !== items.length) {
1189
+ /**
1190
+ * Asserts that this.walletClient is populated
1191
+ * @throws {CofhesdkError} If walletClient is not set
1192
+ */
1193
+ assertWalletClient() {
1194
+ if (this.walletClient)
1195
+ return;
1318
1196
  throw new CofhesdkError({
1319
- code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
1320
- message: `mockZkVerifySign createProofSignatures returned incorrect number of signatures`,
1197
+ code: "MISSING_WALLET_CLIENT" /* MissingWalletClient */,
1198
+ message: "Wallet client not found",
1199
+ hint: "Ensure client.connect() has been called with a walletClient.",
1321
1200
  context: {
1322
- items,
1323
- securityZone
1201
+ walletClient: this.walletClient
1324
1202
  }
1325
1203
  });
1326
1204
  }
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
- }
1205
+ };
1421
1206
 
1422
1207
  // core/encrypt/encryptInputsBuilder.ts
1423
1208
  var EncryptInputsBuilder = class extends BaseBuilder {
@@ -1429,7 +1214,10 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1429
1214
  compactPkeCrsDeserializer;
1430
1215
  zkBuilderAndCrsGenerator;
1431
1216
  initTfhe;
1217
+ zkProveWorkerFn;
1432
1218
  keysStorage;
1219
+ // Worker configuration (from config, overrideable)
1220
+ useWorker;
1433
1221
  stepTimestamps = {
1434
1222
  ["initTfhe" /* InitTfhe */]: 0,
1435
1223
  ["fetchKeys" /* FetchKeys */]: 0,
@@ -1449,11 +1237,43 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1449
1237
  this.inputItems = params.inputs;
1450
1238
  this.securityZone = params.securityZone ?? 0;
1451
1239
  this.zkvWalletClient = params.zkvWalletClient;
1240
+ if (!params.tfhePublicKeyDeserializer) {
1241
+ throw new CofhesdkError({
1242
+ code: "MISSING_TFHE_PUBLIC_KEY_DESERIALIZER" /* MissingTfhePublicKeyDeserializer */,
1243
+ message: "EncryptInputsBuilder tfhePublicKeyDeserializer is undefined",
1244
+ hint: "Ensure client has been created with a tfhePublicKeyDeserializer.",
1245
+ context: {
1246
+ tfhePublicKeyDeserializer: params.tfhePublicKeyDeserializer
1247
+ }
1248
+ });
1249
+ }
1452
1250
  this.tfhePublicKeyDeserializer = params.tfhePublicKeyDeserializer;
1251
+ if (!params.compactPkeCrsDeserializer) {
1252
+ throw new CofhesdkError({
1253
+ code: "MISSING_COMPACT_PKE_CRS_DESERIALIZER" /* MissingCompactPkeCrsDeserializer */,
1254
+ message: "EncryptInputsBuilder compactPkeCrsDeserializer is undefined",
1255
+ hint: "Ensure client has been created with a compactPkeCrsDeserializer.",
1256
+ context: {
1257
+ compactPkeCrsDeserializer: params.compactPkeCrsDeserializer
1258
+ }
1259
+ });
1260
+ }
1453
1261
  this.compactPkeCrsDeserializer = params.compactPkeCrsDeserializer;
1262
+ if (!params.zkBuilderAndCrsGenerator) {
1263
+ throw new CofhesdkError({
1264
+ code: "MISSING_ZK_BUILDER_AND_CRS_GENERATOR" /* MissingZkBuilderAndCrsGenerator */,
1265
+ message: "EncryptInputsBuilder zkBuilderAndCrsGenerator is undefined",
1266
+ hint: "Ensure client has been created with a zkBuilderAndCrsGenerator.",
1267
+ context: {
1268
+ zkBuilderAndCrsGenerator: params.zkBuilderAndCrsGenerator
1269
+ }
1270
+ });
1271
+ }
1454
1272
  this.zkBuilderAndCrsGenerator = params.zkBuilderAndCrsGenerator;
1455
1273
  this.initTfhe = params.initTfhe;
1274
+ this.zkProveWorkerFn = params.zkProveWorkerFn;
1456
1275
  this.keysStorage = params.keysStorage;
1276
+ this.useWorker = params.config?.useWorkers ?? true;
1457
1277
  }
1458
1278
  /**
1459
1279
  * @param account - Account that will create the tx using the encrypted inputs.
@@ -1498,611 +1318,1022 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1498
1318
  return this.chainId;
1499
1319
  }
1500
1320
  /**
1501
- * @param securityZone - Security zone to encrypt the inputs for.
1502
- *
1503
- * If not provided, the default securityZone 0 will be used.
1504
- *
1505
- * Example:
1506
- * ```typescript
1507
- * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1508
- * .setSecurityZone(1)
1509
- * .encrypt();
1510
- * ```
1321
+ * @param securityZone - Security zone to encrypt the inputs for.
1322
+ *
1323
+ * If not provided, the default securityZone 0 will be used.
1324
+ *
1325
+ * Example:
1326
+ * ```typescript
1327
+ * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1328
+ * .setSecurityZone(1)
1329
+ * .encrypt();
1330
+ * ```
1331
+ *
1332
+ * @returns The chainable EncryptInputsBuilder instance.
1333
+ */
1334
+ setSecurityZone(securityZone) {
1335
+ this.securityZone = securityZone;
1336
+ return this;
1337
+ }
1338
+ getSecurityZone() {
1339
+ return this.securityZone;
1340
+ }
1341
+ /**
1342
+ * @param useWorker - Whether to use Web Workers for ZK proof generation.
1343
+ *
1344
+ * Overrides the config-level useWorkers setting for this specific encryption.
1345
+ *
1346
+ * Example:
1347
+ * ```typescript
1348
+ * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1349
+ * .setUseWorker(false)
1350
+ * .encrypt();
1351
+ * ```
1352
+ *
1353
+ * @returns The chainable EncryptInputsBuilder instance.
1354
+ */
1355
+ setUseWorker(useWorker) {
1356
+ this.useWorker = useWorker;
1357
+ return this;
1358
+ }
1359
+ /**
1360
+ * Gets the current worker configuration.
1361
+ *
1362
+ * @returns Whether Web Workers are enabled for this encryption.
1363
+ *
1364
+ * Example:
1365
+ * ```typescript
1366
+ * const builder = encryptInputs([Encryptable.uint128(10n)]);
1367
+ * console.log(builder.getUseWorker()); // true (from config)
1368
+ * builder.setUseWorker(false);
1369
+ * console.log(builder.getUseWorker()); // false (overridden)
1370
+ * ```
1371
+ */
1372
+ getUseWorker() {
1373
+ return this.useWorker;
1374
+ }
1375
+ /**
1376
+ * @param callback - Function to be called with the encryption step.
1377
+ *
1378
+ * Useful for debugging and tracking the progress of the encryption process.
1379
+ * Useful for a UI element that shows the progress of the encryption process.
1380
+ *
1381
+ * Example:
1382
+ * ```typescript
1383
+ * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1384
+ * .setStepCallback((step: EncryptStep) => console.log(step))
1385
+ * .encrypt();
1386
+ * ```
1387
+ *
1388
+ * @returns The EncryptInputsBuilder instance.
1389
+ */
1390
+ setStepCallback(callback) {
1391
+ this.stepCallback = callback;
1392
+ return this;
1393
+ }
1394
+ getStepCallback() {
1395
+ return this.stepCallback;
1396
+ }
1397
+ /**
1398
+ * Fires the step callback if set
1399
+ */
1400
+ fireStepStart(step, context = {}) {
1401
+ if (!this.stepCallback)
1402
+ return;
1403
+ this.stepTimestamps[step] = Date.now();
1404
+ this.stepCallback(step, { ...context, isStart: true, isEnd: false, duration: 0 });
1405
+ }
1406
+ fireStepEnd(step, context = {}) {
1407
+ if (!this.stepCallback)
1408
+ return;
1409
+ const duration = Date.now() - this.stepTimestamps[step];
1410
+ this.stepCallback(step, { ...context, isStart: false, isEnd: true, duration });
1411
+ }
1412
+ /**
1413
+ * zkVerifierUrl is included in the chains exported from cofhesdk/chains for use in CofhesdkConfig.supportedChains
1414
+ * Users should generally not set this manually.
1415
+ */
1416
+ async getZkVerifierUrl() {
1417
+ this.assertChainId();
1418
+ return getZkVerifierUrlOrThrow(this.config, this.chainId);
1419
+ }
1420
+ /**
1421
+ * initTfhe is a platform-specific dependency injected into core/createCofhesdkClientBase by web/createCofhesdkClient and node/createCofhesdkClient
1422
+ * web/ uses zama "tfhe"
1423
+ * node/ uses zama "node-tfhe"
1424
+ * Users should not set this manually.
1425
+ */
1426
+ async initTfheOrThrow() {
1427
+ if (!this.initTfhe)
1428
+ return false;
1429
+ try {
1430
+ return await this.initTfhe();
1431
+ } catch (error) {
1432
+ throw CofhesdkError.fromError(error, {
1433
+ code: "INIT_TFHE_FAILED" /* InitTfheFailed */,
1434
+ message: `Failed to initialize TFHE`,
1435
+ context: {
1436
+ initTfhe: this.initTfhe
1437
+ }
1438
+ });
1439
+ }
1440
+ }
1441
+ /**
1442
+ * Fetches the FHE key and CRS from the CoFHE API
1443
+ * If the key/crs already exists in the store it is returned, else it is fetched, stored, and returned
1444
+ */
1445
+ async fetchFheKeyAndCrs() {
1446
+ this.assertChainId();
1447
+ const securityZone = this.getSecurityZone();
1448
+ try {
1449
+ await this.keysStorage?.rehydrateKeysStore();
1450
+ } catch (error) {
1451
+ throw CofhesdkError.fromError(error, {
1452
+ code: "REHYDRATE_KEYS_STORE_FAILED" /* RehydrateKeysStoreFailed */,
1453
+ message: `Failed to rehydrate keys store`,
1454
+ context: {
1455
+ keysStorage: this.keysStorage
1456
+ }
1457
+ });
1458
+ }
1459
+ let fheKey;
1460
+ let fheKeyFetchedFromCoFHE = false;
1461
+ let crs;
1462
+ let crsFetchedFromCoFHE = false;
1463
+ try {
1464
+ [[fheKey, fheKeyFetchedFromCoFHE], [crs, crsFetchedFromCoFHE]] = await fetchKeys(
1465
+ this.config,
1466
+ this.chainId,
1467
+ securityZone,
1468
+ this.tfhePublicKeyDeserializer,
1469
+ this.compactPkeCrsDeserializer,
1470
+ this.keysStorage
1471
+ );
1472
+ } catch (error) {
1473
+ throw CofhesdkError.fromError(error, {
1474
+ code: "FETCH_KEYS_FAILED" /* FetchKeysFailed */,
1475
+ message: `Failed to fetch FHE key and CRS`,
1476
+ context: {
1477
+ config: this.config,
1478
+ chainId: this.chainId,
1479
+ securityZone,
1480
+ compactPkeCrsDeserializer: this.compactPkeCrsDeserializer,
1481
+ tfhePublicKeyDeserializer: this.tfhePublicKeyDeserializer
1482
+ }
1483
+ });
1484
+ }
1485
+ if (!fheKey) {
1486
+ throw new CofhesdkError({
1487
+ code: "MISSING_FHE_KEY" /* MissingFheKey */,
1488
+ message: `FHE key not found`,
1489
+ context: {
1490
+ chainId: this.chainId,
1491
+ securityZone
1492
+ }
1493
+ });
1494
+ }
1495
+ if (!crs) {
1496
+ throw new CofhesdkError({
1497
+ code: "MISSING_CRS" /* MissingCrs */,
1498
+ message: `CRS not found for chainId <${this.chainId}>`,
1499
+ context: {
1500
+ chainId: this.chainId
1501
+ }
1502
+ });
1503
+ }
1504
+ return { fheKey, fheKeyFetchedFromCoFHE, crs, crsFetchedFromCoFHE };
1505
+ }
1506
+ /**
1507
+ * @dev Encrypt against the cofheMocks instead of CoFHE
1511
1508
  *
1512
- * @returns The chainable EncryptInputsBuilder instance.
1509
+ * In the cofheMocks, the MockZkVerifier contract is deployed on hardhat to a fixed address, this contract handles mocking the zk verifying.
1510
+ * cofheMocksInsertPackedHashes - stores the ctHashes and their plaintext values for on-chain mocking of FHE operations.
1511
+ * cofheMocksZkCreateProofSignatures - creates signatures to be included in the encrypted inputs. The signers address is known and verified in the mock contracts.
1513
1512
  */
1514
- setSecurityZone(securityZone) {
1515
- this.securityZone = securityZone;
1516
- return this;
1513
+ async mocksEncrypt() {
1514
+ this.assertAccount();
1515
+ this.assertPublicClient();
1516
+ this.assertWalletClient();
1517
+ this.fireStepStart("initTfhe" /* InitTfhe */);
1518
+ await sleep(100);
1519
+ this.fireStepEnd("initTfhe" /* InitTfhe */, { tfheInitializationExecuted: false });
1520
+ this.fireStepStart("fetchKeys" /* FetchKeys */);
1521
+ await sleep(100);
1522
+ this.fireStepEnd("fetchKeys" /* FetchKeys */, { fheKeyFetchedFromCoFHE: false, crsFetchedFromCoFHE: false });
1523
+ this.fireStepStart("pack" /* Pack */);
1524
+ await cofheMocksCheckEncryptableBits(this.inputItems);
1525
+ await sleep(100);
1526
+ this.fireStepEnd("pack" /* Pack */);
1527
+ this.fireStepStart("prove" /* Prove */);
1528
+ await sleep(500);
1529
+ this.fireStepEnd("prove" /* Prove */);
1530
+ this.fireStepStart("verify" /* Verify */);
1531
+ await sleep(500);
1532
+ const signedResults = await cofheMocksZkVerifySign(
1533
+ this.inputItems,
1534
+ this.account,
1535
+ this.securityZone,
1536
+ this.publicClient,
1537
+ this.walletClient,
1538
+ this.zkvWalletClient
1539
+ );
1540
+ const encryptedInputs = signedResults.map(({ ct_hash, signature }, index) => ({
1541
+ ctHash: BigInt(ct_hash),
1542
+ securityZone: this.securityZone,
1543
+ utype: this.inputItems[index].utype,
1544
+ signature
1545
+ }));
1546
+ this.fireStepEnd("verify" /* Verify */);
1547
+ return encryptedInputs;
1517
1548
  }
1518
- getSecurityZone() {
1519
- return this.securityZone;
1549
+ /**
1550
+ * In the production context, perform a true encryption with the CoFHE coprocessor.
1551
+ */
1552
+ async productionEncrypt() {
1553
+ this.assertAccount();
1554
+ this.assertChainId();
1555
+ this.fireStepStart("initTfhe" /* InitTfhe */);
1556
+ const tfheInitializationExecuted = await this.initTfheOrThrow();
1557
+ this.fireStepEnd("initTfhe" /* InitTfhe */, { tfheInitializationExecuted });
1558
+ this.fireStepStart("fetchKeys" /* FetchKeys */);
1559
+ const { fheKey, fheKeyFetchedFromCoFHE, crs, crsFetchedFromCoFHE } = await this.fetchFheKeyAndCrs();
1560
+ let { zkBuilder, zkCrs } = this.zkBuilderAndCrsGenerator(fheKey, crs);
1561
+ this.fireStepEnd("fetchKeys" /* FetchKeys */, { fheKeyFetchedFromCoFHE, crsFetchedFromCoFHE });
1562
+ this.fireStepStart("pack" /* Pack */);
1563
+ zkBuilder = zkPack(this.inputItems, zkBuilder);
1564
+ this.fireStepEnd("pack" /* Pack */);
1565
+ this.fireStepStart("prove" /* Prove */);
1566
+ const metadata = constructZkPoKMetadata(this.account, this.securityZone, this.chainId);
1567
+ let proof = null;
1568
+ let usedWorker = false;
1569
+ let workerFailedError;
1570
+ if (this.useWorker && this.zkProveWorkerFn) {
1571
+ try {
1572
+ proof = await zkProveWithWorker(this.zkProveWorkerFn, fheKey, crs, this.inputItems, metadata);
1573
+ usedWorker = true;
1574
+ } catch (error) {
1575
+ workerFailedError = error instanceof Error ? error.message : String(error);
1576
+ }
1577
+ }
1578
+ if (proof == null) {
1579
+ proof = await zkProve(zkBuilder, zkCrs, metadata);
1580
+ usedWorker = false;
1581
+ }
1582
+ this.fireStepEnd("prove" /* Prove */, {
1583
+ useWorker: this.useWorker,
1584
+ usedWorker,
1585
+ workerFailedError
1586
+ });
1587
+ this.fireStepStart("verify" /* Verify */);
1588
+ const zkVerifierUrl = await this.getZkVerifierUrl();
1589
+ const verifyResults = await zkVerify(zkVerifierUrl, proof, this.account, this.securityZone, this.chainId);
1590
+ const encryptedInputs = verifyResults.map(
1591
+ ({ ct_hash, signature }, index) => ({
1592
+ ctHash: BigInt(ct_hash),
1593
+ securityZone: this.securityZone,
1594
+ utype: this.inputItems[index].utype,
1595
+ signature
1596
+ })
1597
+ );
1598
+ this.fireStepEnd("verify" /* Verify */);
1599
+ return encryptedInputs;
1520
1600
  }
1521
1601
  /**
1522
- * @param callback - Function to be called with the encryption step.
1602
+ * Final step of the encryption process. MUST BE CALLED LAST IN THE CHAIN.
1523
1603
  *
1524
- * Useful for debugging and tracking the progress of the encryption process.
1525
- * Useful for a UI element that shows the progress of the encryption process.
1604
+ * This will:
1605
+ * - Pack the encryptable items into a zk proof
1606
+ * - Prove the zk proof
1607
+ * - Verify the zk proof with CoFHE
1608
+ * - Package and return the encrypted inputs
1526
1609
  *
1527
1610
  * Example:
1528
1611
  * ```typescript
1529
1612
  * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1530
- * .setStepCallback((step: EncryptStep) => console.log(step))
1531
- * .encrypt();
1613
+ * .setAccount('0x123...890') // optional
1614
+ * .setChainId(11155111) // optional
1615
+ * .encrypt(); // execute
1532
1616
  * ```
1533
1617
  *
1534
- * @returns The EncryptInputsBuilder instance.
1618
+ * @returns The encrypted inputs.
1535
1619
  */
1536
- setStepCallback(callback) {
1537
- this.stepCallback = callback;
1538
- return this;
1620
+ async encrypt() {
1621
+ if (this.chainId === hardhat.id)
1622
+ return this.mocksEncrypt();
1623
+ return this.productionEncrypt();
1624
+ }
1625
+ };
1626
+ var storeActivePermit = async (permit, publicClient, walletClient) => {
1627
+ const chainId = await publicClient.getChainId();
1628
+ const account = walletClient.account.address;
1629
+ permitStore.setPermit(chainId, account, permit);
1630
+ permitStore.setActivePermitHash(chainId, account, PermitUtils.getHash(permit));
1631
+ };
1632
+ var createPermitWithSign = async (options, publicClient, walletClient, permitMethod) => {
1633
+ const permit = await permitMethod(options, publicClient, walletClient);
1634
+ await storeActivePermit(permit, publicClient, walletClient);
1635
+ return permit;
1636
+ };
1637
+ var createSelf = async (options, publicClient, walletClient) => {
1638
+ return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSelfAndSign);
1639
+ };
1640
+ var createSharing = async (options, publicClient, walletClient) => {
1641
+ return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSharingAndSign);
1642
+ };
1643
+ var importShared = async (options, publicClient, walletClient) => {
1644
+ return createPermitWithSign(options, publicClient, walletClient, PermitUtils.importSharedAndSign);
1645
+ };
1646
+ var getHash = (permit) => {
1647
+ return PermitUtils.getHash(permit);
1648
+ };
1649
+ var serialize = (permit) => {
1650
+ return PermitUtils.serialize(permit);
1651
+ };
1652
+ var deserialize = (serialized) => {
1653
+ return PermitUtils.deserialize(serialized);
1654
+ };
1655
+ var getPermit = async (chainId, account, hash) => {
1656
+ return permitStore.getPermit(chainId, account, hash);
1657
+ };
1658
+ var getPermits = async (chainId, account) => {
1659
+ return permitStore.getPermits(chainId, account);
1660
+ };
1661
+ var getActivePermit = async (chainId, account) => {
1662
+ return permitStore.getActivePermit(chainId, account);
1663
+ };
1664
+ var getActivePermitHash = (chainId, account) => {
1665
+ return permitStore.getActivePermitHash(chainId, account);
1666
+ };
1667
+ var selectActivePermit = (chainId, account, hash) => {
1668
+ permitStore.setActivePermitHash(chainId, account, hash);
1669
+ };
1670
+ var getOrCreateSelfPermit = async (publicClient, walletClient, chainId, account, options) => {
1671
+ const _chainId = chainId ?? await publicClient.getChainId();
1672
+ const _account = account ?? walletClient.account.address;
1673
+ const activePermit = await getActivePermit(_chainId, _account);
1674
+ if (activePermit && activePermit.type === "self") {
1675
+ return activePermit;
1676
+ }
1677
+ return createSelf(options ?? { issuer: _account, name: "Autogenerated Self Permit" }, publicClient, walletClient);
1678
+ };
1679
+ var getOrCreateSharingPermit = async (publicClient, walletClient, options, chainId, account) => {
1680
+ const _chainId = chainId ?? await publicClient.getChainId();
1681
+ const _account = account ?? walletClient.account.address;
1682
+ const activePermit = await getActivePermit(_chainId, _account);
1683
+ if (activePermit && activePermit.type === "sharing") {
1684
+ return activePermit;
1685
+ }
1686
+ return createSharing(options, publicClient, walletClient);
1687
+ };
1688
+ var removePermit = async (chainId, account, hash, force) => permitStore.removePermit(chainId, account, hash, force);
1689
+ var removeActivePermit = async (chainId, account) => permitStore.removeActivePermitHash(chainId, account);
1690
+ var permits = {
1691
+ getSnapshot: permitStore.store.getState,
1692
+ subscribe: permitStore.store.subscribe,
1693
+ createSelf,
1694
+ createSharing,
1695
+ importShared,
1696
+ getOrCreateSelfPermit,
1697
+ getOrCreateSharingPermit,
1698
+ getHash,
1699
+ serialize,
1700
+ deserialize,
1701
+ getPermit,
1702
+ getPermits,
1703
+ getActivePermit,
1704
+ getActivePermitHash,
1705
+ removePermit,
1706
+ selectActivePermit,
1707
+ removeActivePermit
1708
+ };
1709
+ function uint160ToAddress(uint160) {
1710
+ const hexStr = uint160.toString(16).padStart(40, "0");
1711
+ return getAddress("0x" + hexStr);
1712
+ }
1713
+ var isValidUtype = (utype) => {
1714
+ return utype === 0 /* Bool */ || utype === 7 /* Uint160 */ || utype == null || FheUintUTypes.includes(utype);
1715
+ };
1716
+ var convertViaUtype = (utype, value) => {
1717
+ if (utype === 0 /* Bool */) {
1718
+ return !!value;
1719
+ } else if (utype === 7 /* Uint160 */) {
1720
+ return uint160ToAddress(value);
1721
+ } else if (utype == null || FheUintUTypes.includes(utype)) {
1722
+ return value;
1723
+ } else {
1724
+ throw new Error(`convertViaUtype :: invalid utype :: ${utype}`);
1725
+ }
1726
+ };
1727
+
1728
+ // core/decrypt/MockQueryDecrypterAbi.ts
1729
+ var MockQueryDecrypterAbi = [
1730
+ {
1731
+ type: "function",
1732
+ name: "acl",
1733
+ inputs: [],
1734
+ outputs: [{ name: "", type: "address", internalType: "contract ACL" }],
1735
+ stateMutability: "view"
1736
+ },
1737
+ {
1738
+ type: "function",
1739
+ name: "decodeLowLevelReversion",
1740
+ inputs: [{ name: "data", type: "bytes", internalType: "bytes" }],
1741
+ outputs: [{ name: "error", type: "string", internalType: "string" }],
1742
+ stateMutability: "pure"
1743
+ },
1744
+ {
1745
+ type: "function",
1746
+ name: "exists",
1747
+ inputs: [],
1748
+ outputs: [{ name: "", type: "bool", internalType: "bool" }],
1749
+ stateMutability: "pure"
1750
+ },
1751
+ {
1752
+ type: "function",
1753
+ name: "initialize",
1754
+ inputs: [
1755
+ { name: "_taskManager", type: "address", internalType: "address" },
1756
+ { name: "_acl", type: "address", internalType: "address" }
1757
+ ],
1758
+ outputs: [],
1759
+ stateMutability: "nonpayable"
1760
+ },
1761
+ {
1762
+ type: "function",
1763
+ name: "queryDecrypt",
1764
+ inputs: [
1765
+ { name: "ctHash", type: "uint256", internalType: "uint256" },
1766
+ { name: "", type: "uint256", internalType: "uint256" },
1767
+ {
1768
+ name: "permission",
1769
+ type: "tuple",
1770
+ internalType: "struct Permission",
1771
+ components: [
1772
+ { name: "issuer", type: "address", internalType: "address" },
1773
+ { name: "expiration", type: "uint64", internalType: "uint64" },
1774
+ { name: "recipient", type: "address", internalType: "address" },
1775
+ { name: "validatorId", type: "uint256", internalType: "uint256" },
1776
+ {
1777
+ name: "validatorContract",
1778
+ type: "address",
1779
+ internalType: "address"
1780
+ },
1781
+ { name: "sealingKey", type: "bytes32", internalType: "bytes32" },
1782
+ { name: "issuerSignature", type: "bytes", internalType: "bytes" },
1783
+ { name: "recipientSignature", type: "bytes", internalType: "bytes" }
1784
+ ]
1785
+ }
1786
+ ],
1787
+ outputs: [
1788
+ { name: "allowed", type: "bool", internalType: "bool" },
1789
+ { name: "error", type: "string", internalType: "string" },
1790
+ { name: "", type: "uint256", internalType: "uint256" }
1791
+ ],
1792
+ stateMutability: "view"
1793
+ },
1794
+ {
1795
+ type: "function",
1796
+ name: "querySealOutput",
1797
+ inputs: [
1798
+ { name: "ctHash", type: "uint256", internalType: "uint256" },
1799
+ { name: "", type: "uint256", internalType: "uint256" },
1800
+ {
1801
+ name: "permission",
1802
+ type: "tuple",
1803
+ internalType: "struct Permission",
1804
+ components: [
1805
+ { name: "issuer", type: "address", internalType: "address" },
1806
+ { name: "expiration", type: "uint64", internalType: "uint64" },
1807
+ { name: "recipient", type: "address", internalType: "address" },
1808
+ { name: "validatorId", type: "uint256", internalType: "uint256" },
1809
+ {
1810
+ name: "validatorContract",
1811
+ type: "address",
1812
+ internalType: "address"
1813
+ },
1814
+ { name: "sealingKey", type: "bytes32", internalType: "bytes32" },
1815
+ { name: "issuerSignature", type: "bytes", internalType: "bytes" },
1816
+ { name: "recipientSignature", type: "bytes", internalType: "bytes" }
1817
+ ]
1818
+ }
1819
+ ],
1820
+ outputs: [
1821
+ { name: "allowed", type: "bool", internalType: "bool" },
1822
+ { name: "error", type: "string", internalType: "string" },
1823
+ { name: "", type: "bytes32", internalType: "bytes32" }
1824
+ ],
1825
+ stateMutability: "view"
1826
+ },
1827
+ {
1828
+ type: "function",
1829
+ name: "seal",
1830
+ inputs: [
1831
+ { name: "input", type: "uint256", internalType: "uint256" },
1832
+ { name: "key", type: "bytes32", internalType: "bytes32" }
1833
+ ],
1834
+ outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
1835
+ stateMutability: "pure"
1836
+ },
1837
+ {
1838
+ type: "function",
1839
+ name: "taskManager",
1840
+ inputs: [],
1841
+ outputs: [{ name: "", type: "address", internalType: "contract TaskManager" }],
1842
+ stateMutability: "view"
1843
+ },
1844
+ {
1845
+ type: "function",
1846
+ name: "unseal",
1847
+ inputs: [
1848
+ { name: "hashed", type: "bytes32", internalType: "bytes32" },
1849
+ { name: "key", type: "bytes32", internalType: "bytes32" }
1850
+ ],
1851
+ outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
1852
+ stateMutability: "pure"
1853
+ },
1854
+ { type: "error", name: "NotAllowed", inputs: [] },
1855
+ { type: "error", name: "SealingKeyInvalid", inputs: [] },
1856
+ { type: "error", name: "SealingKeyMissing", inputs: [] }
1857
+ ];
1858
+
1859
+ // core/decrypt/cofheMocksSealOutput.ts
1860
+ var MockQueryDecrypterAddress = "0x0000000000000000000000000000000000000200";
1861
+ async function cofheMocksSealOutput(ctHash, utype, permit, publicClient, mocksSealOutputDelay) {
1862
+ if (mocksSealOutputDelay > 0)
1863
+ await sleep(mocksSealOutputDelay);
1864
+ const permission = PermitUtils.getPermission(permit, true);
1865
+ const permissionWithBigInts = {
1866
+ ...permission,
1867
+ expiration: BigInt(permission.expiration),
1868
+ validatorId: BigInt(permission.validatorId)
1869
+ };
1870
+ const [allowed, error, result] = await publicClient.readContract({
1871
+ address: MockQueryDecrypterAddress,
1872
+ abi: MockQueryDecrypterAbi,
1873
+ functionName: "querySealOutput",
1874
+ args: [ctHash, BigInt(utype), permissionWithBigInts]
1875
+ });
1876
+ if (error != "") {
1877
+ throw new CofhesdkError({
1878
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1879
+ message: `mocks querySealOutput call failed: ${error}`
1880
+ });
1539
1881
  }
1540
- getStepCallback() {
1541
- return this.stepCallback;
1882
+ if (allowed == false) {
1883
+ throw new CofhesdkError({
1884
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1885
+ message: `mocks querySealOutput call failed: ACL Access Denied (NotAllowed)`
1886
+ });
1542
1887
  }
1543
- /**
1544
- * Fires the step callback if set
1545
- */
1546
- fireStepStart(step, context = {}) {
1547
- if (!this.stepCallback)
1548
- return;
1549
- this.stepTimestamps[step] = Date.now();
1550
- this.stepCallback(step, { ...context, isStart: true, isEnd: false, duration: 0 });
1888
+ const sealedBigInt = BigInt(result);
1889
+ const sealingKeyBigInt = BigInt(permission.sealingKey);
1890
+ const unsealed = sealedBigInt ^ sealingKeyBigInt;
1891
+ return unsealed;
1892
+ }
1893
+
1894
+ // core/decrypt/tnSealOutputV2.ts
1895
+ var POLL_INTERVAL_MS = 1e3;
1896
+ var POLL_TIMEOUT_MS = 5 * 60 * 1e3;
1897
+ function numberArrayToUint8Array(arr) {
1898
+ return new Uint8Array(arr);
1899
+ }
1900
+ function convertSealedData(sealed) {
1901
+ if (!sealed) {
1902
+ throw new CofhesdkError({
1903
+ code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
1904
+ message: "Sealed data is missing from completed response"
1905
+ });
1551
1906
  }
1552
- fireStepEnd(step, context = {}) {
1553
- if (!this.stepCallback)
1554
- return;
1555
- const duration = Date.now() - this.stepTimestamps[step];
1556
- this.stepCallback(step, { ...context, isStart: false, isEnd: true, duration });
1907
+ return {
1908
+ data: numberArrayToUint8Array(sealed.data),
1909
+ public_key: numberArrayToUint8Array(sealed.public_key),
1910
+ nonce: numberArrayToUint8Array(sealed.nonce)
1911
+ };
1912
+ }
1913
+ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission) {
1914
+ const body = {
1915
+ ct_tempkey: ctHash.toString(16).padStart(64, "0"),
1916
+ host_chain_id: chainId,
1917
+ permit: permission
1918
+ };
1919
+ let response;
1920
+ try {
1921
+ response = await fetch(`${thresholdNetworkUrl}/v2/sealoutput`, {
1922
+ method: "POST",
1923
+ headers: {
1924
+ "Content-Type": "application/json"
1925
+ },
1926
+ body: JSON.stringify(body)
1927
+ });
1928
+ } catch (e) {
1929
+ throw new CofhesdkError({
1930
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1931
+ message: `sealOutput request failed`,
1932
+ hint: "Ensure the threshold network URL is valid and reachable.",
1933
+ cause: e instanceof Error ? e : void 0,
1934
+ context: {
1935
+ thresholdNetworkUrl,
1936
+ body
1937
+ }
1938
+ });
1557
1939
  }
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;
1940
+ if (!response.ok) {
1941
+ let errorMessage = `HTTP ${response.status}`;
1942
+ try {
1943
+ const errorBody = await response.json();
1944
+ errorMessage = errorBody.error_message || errorBody.message || errorMessage;
1945
+ } catch {
1946
+ errorMessage = response.statusText || errorMessage;
1947
+ }
1567
1948
  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.",
1949
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1950
+ message: `sealOutput request failed: ${errorMessage}`,
1951
+ hint: "Check the threshold network URL and request parameters.",
1571
1952
  context: {
1572
- tfhePublicKeyDeserializer: this.tfhePublicKeyDeserializer
1953
+ thresholdNetworkUrl,
1954
+ status: response.status,
1955
+ statusText: response.statusText,
1956
+ body
1573
1957
  }
1574
1958
  });
1575
1959
  }
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;
1960
+ let submitResponse;
1961
+ try {
1962
+ submitResponse = await response.json();
1963
+ } catch (e) {
1585
1964
  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.",
1965
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1966
+ message: `Failed to parse sealOutput submit response`,
1967
+ cause: e instanceof Error ? e : void 0,
1589
1968
  context: {
1590
- compactPkeCrsDeserializer: this.compactPkeCrsDeserializer
1969
+ thresholdNetworkUrl,
1970
+ body
1591
1971
  }
1592
1972
  });
1593
1973
  }
1594
- /**
1595
- * zkVerifierUrl is included in the chains exported from cofhesdk/chains for use in CofhesdkConfig.supportedChains
1596
- * Users should generally not set this manually.
1597
- */
1598
- async getZkVerifierUrl() {
1599
- const config = this.getConfigOrThrow();
1600
- const chainId = await this.getChainIdOrThrow();
1601
- return getZkVerifierUrlOrThrow(config, chainId);
1974
+ if (!submitResponse.request_id) {
1975
+ throw new CofhesdkError({
1976
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1977
+ message: `sealOutput submit response missing request_id`,
1978
+ context: {
1979
+ thresholdNetworkUrl,
1980
+ body,
1981
+ submitResponse
1982
+ }
1983
+ });
1602
1984
  }
1603
- /**
1604
- * initTfhe is a platform-specific dependency injected into core/createCofhesdkClientBase by web/createCofhesdkClient and node/createCofhesdkClient
1605
- * web/ uses zama "tfhe"
1606
- * node/ uses zama "node-tfhe"
1607
- * Users should not set this manually.
1608
- */
1609
- async initTfheOrThrow() {
1610
- if (!this.initTfhe)
1611
- return false;
1612
- try {
1613
- return await this.initTfhe();
1614
- } catch (error) {
1615
- throw CofhesdkError.fromError(error, {
1616
- code: "INIT_TFHE_FAILED" /* InitTfheFailed */,
1617
- message: `Failed to initialize TFHE`,
1985
+ return submitResponse.request_id;
1986
+ }
1987
+ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
1988
+ const startTime = Date.now();
1989
+ let completed = false;
1990
+ while (!completed) {
1991
+ if (Date.now() - startTime > POLL_TIMEOUT_MS) {
1992
+ throw new CofhesdkError({
1993
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1994
+ message: `sealOutput polling timed out after ${POLL_TIMEOUT_MS}ms`,
1995
+ hint: "The request may still be processing. Try again later.",
1618
1996
  context: {
1619
- initTfhe: this.initTfhe
1997
+ thresholdNetworkUrl,
1998
+ requestId,
1999
+ timeoutMs: POLL_TIMEOUT_MS
1620
2000
  }
1621
2001
  });
1622
2002
  }
1623
- }
1624
- /**
1625
- * Fetches the FHE key and CRS from the CoFHE API
1626
- * If the key/crs already exists in the store it is returned, else it is fetched, stored, and returned
1627
- */
1628
- async fetchFheKeyAndCrs() {
1629
- const config = this.getConfigOrThrow();
1630
- const chainId = await this.getChainIdOrThrow();
1631
- const compactPkeCrsDeserializer = this.getCompactPkeCrsDeserializerOrThrow();
1632
- const tfhePublicKeyDeserializer = this.getTfhePublicKeyDeserializerOrThrow();
1633
- const securityZone = this.getSecurityZone();
2003
+ let response;
1634
2004
  try {
1635
- await this.keysStorage?.rehydrateKeysStore();
1636
- } catch (error) {
1637
- throw CofhesdkError.fromError(error, {
1638
- code: "REHYDRATE_KEYS_STORE_FAILED" /* RehydrateKeysStoreFailed */,
1639
- message: `Failed to rehydrate keys store`,
2005
+ response = await fetch(`${thresholdNetworkUrl}/v2/sealoutput/${requestId}`, {
2006
+ method: "GET",
2007
+ headers: {
2008
+ "Content-Type": "application/json"
2009
+ }
2010
+ });
2011
+ } catch (e) {
2012
+ throw new CofhesdkError({
2013
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2014
+ message: `sealOutput status poll failed`,
2015
+ hint: "Ensure the threshold network URL is valid and reachable.",
2016
+ cause: e instanceof Error ? e : void 0,
1640
2017
  context: {
1641
- keysStorage: this.keysStorage
2018
+ thresholdNetworkUrl,
2019
+ requestId
1642
2020
  }
1643
2021
  });
1644
2022
  }
1645
- let fheKey;
1646
- let fheKeyFetchedFromCoFHE = false;
1647
- let crs;
1648
- let crsFetchedFromCoFHE = false;
1649
- try {
1650
- [[fheKey, fheKeyFetchedFromCoFHE], [crs, crsFetchedFromCoFHE]] = await fetchKeys(
1651
- config,
1652
- chainId,
1653
- securityZone,
1654
- tfhePublicKeyDeserializer,
1655
- compactPkeCrsDeserializer,
1656
- this.keysStorage
1657
- );
1658
- } catch (error) {
1659
- throw CofhesdkError.fromError(error, {
1660
- code: "FETCH_KEYS_FAILED" /* FetchKeysFailed */,
1661
- message: `Failed to fetch FHE key and CRS`,
2023
+ if (response.status === 404) {
2024
+ throw new CofhesdkError({
2025
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2026
+ message: `sealOutput request not found: ${requestId}`,
2027
+ hint: "The request may have expired or been invalid.",
1662
2028
  context: {
1663
- config,
1664
- chainId,
1665
- securityZone,
1666
- compactPkeCrsDeserializer,
1667
- tfhePublicKeyDeserializer
2029
+ thresholdNetworkUrl,
2030
+ requestId
1668
2031
  }
1669
2032
  });
1670
2033
  }
1671
- if (!fheKey) {
2034
+ if (!response.ok) {
2035
+ let errorMessage = `HTTP ${response.status}`;
2036
+ try {
2037
+ const errorBody = await response.json();
2038
+ errorMessage = errorBody.error_message || errorBody.message || errorMessage;
2039
+ } catch {
2040
+ errorMessage = response.statusText || errorMessage;
2041
+ }
1672
2042
  throw new CofhesdkError({
1673
- code: "MISSING_FHE_KEY" /* MissingFheKey */,
1674
- message: `FHE key not found`,
2043
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2044
+ message: `sealOutput status poll failed: ${errorMessage}`,
1675
2045
  context: {
1676
- chainId,
1677
- securityZone
2046
+ thresholdNetworkUrl,
2047
+ requestId,
2048
+ status: response.status,
2049
+ statusText: response.statusText
1678
2050
  }
1679
2051
  });
1680
2052
  }
1681
- if (!crs) {
2053
+ let statusResponse;
2054
+ try {
2055
+ statusResponse = await response.json();
2056
+ } catch (e) {
1682
2057
  throw new CofhesdkError({
1683
- code: "MISSING_CRS" /* MissingCrs */,
1684
- message: `CRS not found for chainId <${this.chainId}>`,
2058
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2059
+ message: `Failed to parse sealOutput status response`,
2060
+ cause: e instanceof Error ? e : void 0,
1685
2061
  context: {
1686
- chainId
2062
+ thresholdNetworkUrl,
2063
+ requestId
1687
2064
  }
1688
2065
  });
1689
2066
  }
1690
- return { fheKey, fheKeyFetchedFromCoFHE, crs, crsFetchedFromCoFHE };
2067
+ if (statusResponse.status === "COMPLETED") {
2068
+ if (statusResponse.is_succeed === false) {
2069
+ const errorMessage = statusResponse.error_message || "Unknown error";
2070
+ throw new CofhesdkError({
2071
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2072
+ message: `sealOutput request failed: ${errorMessage}`,
2073
+ context: {
2074
+ thresholdNetworkUrl,
2075
+ requestId,
2076
+ statusResponse
2077
+ }
2078
+ });
2079
+ }
2080
+ if (!statusResponse.sealed) {
2081
+ throw new CofhesdkError({
2082
+ code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
2083
+ message: `sealOutput request completed but returned no sealed data`,
2084
+ context: {
2085
+ thresholdNetworkUrl,
2086
+ requestId,
2087
+ statusResponse
2088
+ }
2089
+ });
2090
+ }
2091
+ return convertSealedData(statusResponse.sealed);
2092
+ }
2093
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
2094
+ }
2095
+ throw new CofhesdkError({
2096
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2097
+ message: "Polling loop exited unexpectedly",
2098
+ context: {
2099
+ thresholdNetworkUrl,
2100
+ requestId
2101
+ }
2102
+ });
2103
+ }
2104
+ async function tnSealOutputV2(ctHash, chainId, permission, thresholdNetworkUrl) {
2105
+ const requestId = await submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission);
2106
+ return await pollSealOutputStatus(thresholdNetworkUrl, requestId);
2107
+ }
2108
+
2109
+ // core/decrypt/decryptHandleBuilder.ts
2110
+ var DecryptHandlesBuilder = class extends BaseBuilder {
2111
+ ctHash;
2112
+ utype;
2113
+ permitHash;
2114
+ permit;
2115
+ constructor(params) {
2116
+ super({
2117
+ config: params.config,
2118
+ publicClient: params.publicClient,
2119
+ walletClient: params.walletClient,
2120
+ chainId: params.chainId,
2121
+ account: params.account,
2122
+ requireConnected: params.requireConnected
2123
+ });
2124
+ this.ctHash = params.ctHash;
2125
+ this.utype = params.utype;
2126
+ this.permitHash = params.permitHash;
2127
+ this.permit = params.permit;
1691
2128
  }
1692
2129
  /**
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.
2130
+ * @param chainId - Chain to decrypt values from. Used to fetch the threshold network URL and use the correct permit.
1697
2131
  *
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
- /**
1715
- * @dev Encrypt against the cofheMocks instead of CoFHE
2132
+ * If not provided, the chainId will be fetched from the connected publicClient.
1716
2133
  *
1717
- * In the cofheMocks, the MockZkVerifier contract is deployed on hardhat to a fixed address, this contract handles mocking the zk verifying.
1718
- * cofheMocksInsertPackedHashes - stores the ctHashes and their plaintext values for on-chain mocking of FHE operations.
1719
- * cofheMocksZkCreateProofSignatures - creates signatures to be included in the encrypted inputs. The signers address is known and verified in the mock contracts.
2134
+ * Example:
2135
+ * ```typescript
2136
+ * const unsealed = await decryptHandle(ctHash, utype)
2137
+ * .setChainId(11155111)
2138
+ * .decrypt();
2139
+ * ```
2140
+ *
2141
+ * @returns The chainable DecryptHandlesBuilder instance.
1720
2142
  */
1721
- async mocksEncrypt(account) {
1722
- this.fireStepStart("initTfhe" /* InitTfhe */);
1723
- await sleep(100);
1724
- this.fireStepEnd("initTfhe" /* InitTfhe */, { tfheInitializationExecuted: false });
1725
- this.fireStepStart("fetchKeys" /* FetchKeys */);
1726
- await sleep(100);
1727
- this.fireStepEnd("fetchKeys" /* FetchKeys */, { fheKeyFetchedFromCoFHE: false, crsFetchedFromCoFHE: false });
1728
- this.fireStepStart("pack" /* Pack */);
1729
- await cofheMocksCheckEncryptableBits(this.inputItems);
1730
- await sleep(100);
1731
- this.fireStepEnd("pack" /* Pack */);
1732
- this.fireStepStart("prove" /* Prove */);
1733
- await sleep(500);
1734
- this.fireStepEnd("prove" /* Prove */);
1735
- this.fireStepStart("verify" /* Verify */);
1736
- await sleep(500);
1737
- const signedResults = await cofheMocksZkVerifySign(
1738
- this.inputItems,
1739
- account,
1740
- this.securityZone,
1741
- this.getPublicClientOrThrow(),
1742
- this.getWalletClientOrThrow(),
1743
- this.zkvWalletClient
1744
- );
1745
- const encryptedInputs = signedResults.map(({ ct_hash, signature }, index) => ({
1746
- ctHash: BigInt(ct_hash),
1747
- securityZone: this.securityZone,
1748
- utype: this.inputItems[index].utype,
1749
- signature
1750
- }));
1751
- this.fireStepEnd("verify" /* Verify */);
1752
- return encryptedInputs;
2143
+ setChainId(chainId) {
2144
+ this.chainId = chainId;
2145
+ return this;
1753
2146
  }
1754
- /**
1755
- * In the production context, perform a true encryption with the CoFHE coprocessor.
1756
- */
1757
- async productionEncrypt(account, chainId) {
1758
- this.fireStepStart("initTfhe" /* InitTfhe */);
1759
- const tfheInitializationExecuted = await this.initTfheOrThrow();
1760
- this.fireStepEnd("initTfhe" /* InitTfhe */, { tfheInitializationExecuted });
1761
- this.fireStepStart("fetchKeys" /* FetchKeys */);
1762
- const { fheKey, fheKeyFetchedFromCoFHE, crs, crsFetchedFromCoFHE } = await this.fetchFheKeyAndCrs();
1763
- let { zkBuilder, zkCrs } = this.generateZkBuilderAndCrs(fheKey, crs);
1764
- this.fireStepEnd("fetchKeys" /* FetchKeys */, { fheKeyFetchedFromCoFHE, crsFetchedFromCoFHE });
1765
- this.fireStepStart("pack" /* Pack */);
1766
- zkBuilder = zkPack(this.inputItems, zkBuilder);
1767
- this.fireStepEnd("pack" /* Pack */);
1768
- this.fireStepStart("prove" /* Prove */);
1769
- const proof = await zkProve(zkBuilder, zkCrs, account, this.securityZone, chainId);
1770
- this.fireStepEnd("prove" /* Prove */);
1771
- this.fireStepStart("verify" /* Verify */);
1772
- const zkVerifierUrl = await this.getZkVerifierUrl();
1773
- const verifyResults = await zkVerify(zkVerifierUrl, proof, account, this.securityZone, chainId);
1774
- const encryptedInputs = verifyResults.map(
1775
- ({ ct_hash, signature }, index) => ({
1776
- ctHash: BigInt(ct_hash),
1777
- securityZone: this.securityZone,
1778
- utype: this.inputItems[index].utype,
1779
- signature
1780
- })
1781
- );
1782
- this.fireStepEnd("verify" /* Verify */);
1783
- return encryptedInputs;
2147
+ getChainId() {
2148
+ return this.chainId;
1784
2149
  }
1785
2150
  /**
1786
- * Final step of the encryption process. MUST BE CALLED LAST IN THE CHAIN.
2151
+ * @param account - Account to decrypt values from. Used to fetch the correct permit.
1787
2152
  *
1788
- * This will:
1789
- * - Pack the encryptable items into a zk proof
1790
- * - Prove the zk proof
1791
- * - Verify the zk proof with CoFHE
1792
- * - Package and return the encrypted inputs
2153
+ * If not provided, the account will be fetched from the connected walletClient.
1793
2154
  *
1794
2155
  * Example:
1795
2156
  * ```typescript
1796
- * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1797
- * .setAccount('0x123...890') // optional
1798
- * .setChainId(11155111) // optional
1799
- * .encrypt(); // execute
1800
- * ```
1801
- *
1802
- * @returns The encrypted inputs.
1803
- */
1804
- 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
- });
1814
- }
1815
- };
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,
1882
- };
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
- );
1891
- }
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
-
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}`);
1930
- }
1931
- return result.data;
1932
- }
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) {
1939
- 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.",
1943
- context: {
1944
- chainId,
1945
- supportedChainIds: config.supportedChains.map((c) => c.id)
1946
- }
1947
- });
1948
- }
1949
- return supportedChain;
1950
- }
1951
- function getCoFheUrlOrThrow(config, chainId) {
1952
- const supportedChain = getSupportedChainOrThrow(config, chainId);
1953
- const url = supportedChain.coFheUrl;
1954
- if (!url) {
1955
- 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 }
1960
- });
2157
+ * const unsealed = await decryptHandle(ctHash, utype)
2158
+ * .setAccount('0x1234567890123456789012345678901234567890')
2159
+ * .decrypt();
2160
+ * ```
2161
+ *
2162
+ * @returns The chainable DecryptHandlesBuilder instance.
2163
+ */
2164
+ setAccount(account) {
2165
+ this.account = account;
2166
+ return this;
1961
2167
  }
1962
- return url;
1963
- }
1964
- function getZkVerifierUrlOrThrow(config, chainId) {
1965
- const supportedChain = getSupportedChainOrThrow(config, chainId);
1966
- const url = supportedChain.verifierUrl;
1967
- if (!url) {
1968
- 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 }
1973
- });
2168
+ getAccount() {
2169
+ return this.account;
1974
2170
  }
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
- });
2171
+ /**
2172
+ * @param permitHash - Permit hash to decrypt values from. Used to fetch the correct permit.
2173
+ *
2174
+ * If not provided, the active permit for the chainId and account will be used.
2175
+ * If `setPermit()` is called, it will be used regardless of chainId, account, or permitHash.
2176
+ *
2177
+ * Example:
2178
+ * ```typescript
2179
+ * const unsealed = await decryptHandle(ctHash, utype)
2180
+ * .setPermitHash('0x1234567890123456789012345678901234567890')
2181
+ * .decrypt();
2182
+ * ```
2183
+ *
2184
+ * @returns The chainable DecryptHandlesBuilder instance.
2185
+ */
2186
+ setPermitHash(permitHash) {
2187
+ this.permitHash = permitHash;
2188
+ return this;
1987
2189
  }
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}>`];
2190
+ getPermitHash() {
2191
+ return this.permitHash;
2001
2192
  }
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}`);
2193
+ /**
2194
+ * @param permit - Permit to decrypt values with. If provided, it will be used regardless of chainId, account, or permitHash.
2195
+ *
2196
+ * If not provided, the permit will be determined by chainId, account, and permitHash.
2197
+ *
2198
+ * Example:
2199
+ * ```typescript
2200
+ * const unsealed = await decryptHandle(ctHash, utype)
2201
+ * .setPermit(permit)
2202
+ * .decrypt();
2203
+ * ```
2204
+ *
2205
+ * @returns The chainable DecryptHandlesBuilder instance.
2206
+ */
2207
+ setPermit(permit) {
2208
+ this.permit = permit;
2209
+ return this;
2021
2210
  }
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`);
2211
+ getPermit() {
2212
+ return this.permit;
2024
2213
  }
2025
- if (pk_data === "0x") {
2026
- throw new Error("Error fetching FHE publicKey; provided chain is not FHE enabled / not found");
2214
+ async getThresholdNetworkUrl() {
2215
+ this.assertChainId();
2216
+ return getThresholdNetworkUrlOrThrow(this.config, this.chainId);
2027
2217
  }
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
- );
2218
+ validateUtypeOrThrow() {
2219
+ if (!isValidUtype(this.utype))
2220
+ throw new CofhesdkError({
2221
+ code: "INVALID_UTYPE" /* InvalidUtype */,
2222
+ message: `Invalid utype to decrypt to`,
2223
+ context: {
2224
+ utype: this.utype
2225
+ }
2226
+ });
2032
2227
  }
2033
- try {
2034
- tfhePublicKeyDeserializer(pk_data);
2035
- } catch (err) {
2036
- throw new Error(`Error serializing FHE publicKey; ${err}`);
2228
+ async getResolvedPermit() {
2229
+ if (this.permit)
2230
+ return this.permit;
2231
+ this.assertChainId();
2232
+ this.assertAccount();
2233
+ if (this.permitHash) {
2234
+ const permit2 = await permits.getPermit(this.chainId, this.account, this.permitHash);
2235
+ if (!permit2) {
2236
+ throw new CofhesdkError({
2237
+ code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
2238
+ message: `Permit with hash <${this.permitHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
2239
+ hint: "Ensure the permit exists and is valid.",
2240
+ context: {
2241
+ chainId: this.chainId,
2242
+ account: this.account,
2243
+ permitHash: this.permitHash
2244
+ }
2245
+ });
2246
+ }
2247
+ return permit2;
2248
+ }
2249
+ const permit = await permits.getActivePermit(this.chainId, this.account);
2250
+ if (!permit) {
2251
+ throw new CofhesdkError({
2252
+ code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
2253
+ message: `Active permit not found for chainId <${this.chainId}> and account <${this.account}>`,
2254
+ hint: "Ensure a permit exists for this account on this chain.",
2255
+ context: {
2256
+ chainId: this.chainId,
2257
+ account: this.account
2258
+ }
2259
+ });
2260
+ }
2261
+ return permit;
2037
2262
  }
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}`);
2263
+ /**
2264
+ * On hardhat, interact with MockZkVerifier contract instead of CoFHE
2265
+ */
2266
+ async mocksSealOutput(permit) {
2267
+ this.assertPublicClient();
2268
+ const mocksSealOutputDelay = this.config.mocks.sealOutputDelay;
2269
+ return cofheMocksSealOutput(this.ctHash, this.utype, permit, this.publicClient, mocksSealOutputDelay);
2059
2270
  }
2060
- if (crs_data == null || typeof crs_data !== "string") {
2061
- throw new Error(`Error fetching CRS; invalid: missing or not a string`);
2271
+ /**
2272
+ * In the production context, perform a true decryption with the CoFHE coprocessor.
2273
+ */
2274
+ async productionSealOutput(permit) {
2275
+ this.assertChainId();
2276
+ this.assertPublicClient();
2277
+ const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
2278
+ const permission = PermitUtils.getPermission(permit, true);
2279
+ const sealed = await tnSealOutputV2(this.ctHash, this.chainId, permission, thresholdNetworkUrl);
2280
+ return PermitUtils.unseal(permit, sealed);
2062
2281
  }
2063
- try {
2064
- compactPkeCrsDeserializer(crs_data);
2065
- } catch (err) {
2066
- console.error(`Error serializing CRS ${err}`);
2067
- throw new Error(`Error serializing CRS; ${err}`);
2282
+ /**
2283
+ * Final step of the decryption process. MUST BE CALLED LAST IN THE CHAIN.
2284
+ *
2285
+ * This will:
2286
+ * - Use a permit based on provided permit OR chainId + account + permitHash
2287
+ * - Check permit validity
2288
+ * - Call CoFHE `/sealoutput` with the permit, which returns a sealed (encrypted) item
2289
+ * - Unseal the sealed item with the permit
2290
+ * - Return the unsealed item
2291
+ *
2292
+ * Example:
2293
+ * ```typescript
2294
+ * const unsealed = await decryptHandle(ctHash, utype)
2295
+ * .setChainId(11155111) // optional
2296
+ * .setAccount('0x123...890') // optional
2297
+ * .decrypt(); // execute
2298
+ * ```
2299
+ *
2300
+ * @returns The unsealed item.
2301
+ */
2302
+ async decrypt() {
2303
+ this.validateUtypeOrThrow();
2304
+ const permit = await this.getResolvedPermit();
2305
+ PermitUtils.validate(permit);
2306
+ PermitUtils.isValid(permit);
2307
+ const chainId = permit._signedDomain.chainId;
2308
+ let unsealed;
2309
+ if (chainId === hardhat$1.id) {
2310
+ unsealed = await this.mocksSealOutput(permit);
2311
+ } else {
2312
+ unsealed = await this.productionSealOutput(permit);
2313
+ }
2314
+ return convertViaUtype(this.utype, unsealed);
2068
2315
  }
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
2316
  };
2086
2317
 
2087
2318
  // core/client.ts
2319
+ var InitialConnectStore = {
2320
+ connected: false,
2321
+ connecting: false,
2322
+ connectError: void 0,
2323
+ chainId: void 0,
2324
+ account: void 0,
2325
+ publicClient: void 0,
2326
+ walletClient: void 0
2327
+ };
2088
2328
  function createCofhesdkClientBase(opts) {
2089
2329
  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
- }));
2330
+ const connectStore = createStore(() => InitialConnectStore);
2099
2331
  const updateConnectState = (partial) => {
2100
2332
  connectStore.setState((state) => ({ ...state, ...partial }));
2101
2333
  };
2102
- let _connectPromise = void 0;
2103
2334
  const _requireConnected = () => {
2104
2335
  const state = connectStore.getState();
2105
- const notConnected = !state.connected || !_publicClient || !_walletClient || !state.account || !state.chainId;
2336
+ const notConnected = !state.connected || !state.account || !state.chainId || !state.publicClient || !state.walletClient;
2106
2337
  if (notConnected) {
2107
2338
  throw new CofhesdkError({
2108
2339
  code: "NOT_CONNECTED" /* NotConnected */,
@@ -2112,55 +2343,39 @@ function createCofhesdkClientBase(opts) {
2112
2343
  connected: state.connected,
2113
2344
  account: state.account,
2114
2345
  chainId: state.chainId,
2115
- publicClient: _publicClient,
2116
- walletClient: _walletClient
2346
+ publicClient: state.publicClient,
2347
+ walletClient: state.walletClient
2117
2348
  }
2118
2349
  });
2119
2350
  }
2120
2351
  };
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
2352
  async function connect(publicClient, walletClient) {
2135
2353
  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;
2354
+ if (state.connected && state.publicClient === publicClient && state.walletClient === walletClient)
2355
+ return;
2356
+ updateConnectState({
2357
+ ...InitialConnectStore,
2358
+ connecting: true
2359
+ });
2360
+ try {
2361
+ const chainId = await getPublicClientChainID(publicClient);
2362
+ const account = await getWalletClientAccount(walletClient);
2363
+ updateConnectState({
2364
+ connected: true,
2365
+ connecting: false,
2366
+ connectError: void 0,
2367
+ chainId,
2368
+ account,
2369
+ publicClient,
2370
+ walletClient
2371
+ });
2372
+ } catch (e) {
2373
+ updateConnectState({
2374
+ ...InitialConnectStore,
2375
+ connectError: e
2376
+ });
2377
+ throw e;
2141
2378
  }
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;
2164
2379
  }
2165
2380
  function encryptInputs(inputs) {
2166
2381
  const state = connectStore.getState();
@@ -2169,13 +2384,14 @@ function createCofhesdkClientBase(opts) {
2169
2384
  account: state.account ?? void 0,
2170
2385
  chainId: state.chainId ?? void 0,
2171
2386
  config: opts.config,
2172
- publicClient: _publicClient ?? void 0,
2173
- walletClient: _walletClient ?? void 0,
2387
+ publicClient: state.publicClient ?? void 0,
2388
+ walletClient: state.walletClient ?? void 0,
2174
2389
  zkvWalletClient: opts.config._internal?.zkvWalletClient,
2175
2390
  tfhePublicKeyDeserializer: opts.tfhePublicKeyDeserializer,
2176
2391
  compactPkeCrsDeserializer: opts.compactPkeCrsDeserializer,
2177
2392
  zkBuilderAndCrsGenerator: opts.zkBuilderAndCrsGenerator,
2178
2393
  initTfhe: opts.initTfhe,
2394
+ zkProveWorkerFn: opts.zkProveWorkerFn,
2179
2395
  keysStorage,
2180
2396
  requireConnected: _requireConnected
2181
2397
  });
@@ -2188,8 +2404,8 @@ function createCofhesdkClientBase(opts) {
2188
2404
  chainId: state.chainId ?? void 0,
2189
2405
  account: state.account ?? void 0,
2190
2406
  config: opts.config,
2191
- publicClient: _publicClient ?? void 0,
2192
- walletClient: _walletClient ?? void 0,
2407
+ publicClient: state.publicClient ?? void 0,
2408
+ walletClient: state.walletClient ?? void 0,
2193
2409
  requireConnected: _requireConnected
2194
2410
  });
2195
2411
  }
@@ -2215,48 +2431,64 @@ function createCofhesdkClientBase(opts) {
2215
2431
  getSnapshot: permits.getSnapshot,
2216
2432
  subscribe: permits.subscribe,
2217
2433
  // Creation methods (require connection)
2218
- createSelf: async (options) => resultWrapper(async () => {
2434
+ createSelf: async (options, clients) => {
2435
+ _requireConnected();
2436
+ const { publicClient, walletClient } = clients ?? connectStore.getState();
2437
+ return permits.createSelf(options, publicClient, walletClient);
2438
+ },
2439
+ createSharing: async (options, clients) => {
2440
+ _requireConnected();
2441
+ const { publicClient, walletClient } = clients ?? connectStore.getState();
2442
+ return permits.createSharing(options, publicClient, walletClient);
2443
+ },
2444
+ importShared: async (options, clients) => {
2219
2445
  _requireConnected();
2220
- return permits.createSelf(options, _publicClient, _walletClient);
2221
- }),
2222
- createSharing: async (options) => resultWrapper(async () => {
2446
+ const { publicClient, walletClient } = clients ?? connectStore.getState();
2447
+ return permits.importShared(options, publicClient, walletClient);
2448
+ },
2449
+ // Get or create methods (require connection)
2450
+ getOrCreateSelfPermit: async (chainId, account, options) => {
2223
2451
  _requireConnected();
2224
- return permits.createSharing(options, _publicClient, _walletClient);
2225
- }),
2226
- importShared: async (options) => resultWrapper(async () => {
2452
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2453
+ const { publicClient, walletClient } = connectStore.getState();
2454
+ return permits.getOrCreateSelfPermit(publicClient, walletClient, _chainId, _account, options);
2455
+ },
2456
+ getOrCreateSharingPermit: async (options, chainId, account) => {
2227
2457
  _requireConnected();
2228
- return permits.importShared(options, _publicClient, _walletClient);
2229
- }),
2458
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2459
+ const { publicClient, walletClient } = connectStore.getState();
2460
+ return permits.getOrCreateSharingPermit(publicClient, walletClient, options, _chainId, _account);
2461
+ },
2230
2462
  // Retrieval methods (auto-fill chainId/account)
2231
- getPermit: async (hash, chainId, account) => resultWrapper(async () => {
2463
+ getPermit: async (hash, chainId, account) => {
2232
2464
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2233
2465
  return permits.getPermit(_chainId, _account, hash);
2234
- }),
2235
- getPermits: async (chainId, account) => resultWrapper(async () => {
2466
+ },
2467
+ getPermits: async (chainId, account) => {
2236
2468
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2237
2469
  return permits.getPermits(_chainId, _account);
2238
- }),
2239
- getActivePermit: async (chainId, account) => resultWrapper(async () => {
2470
+ },
2471
+ getActivePermit: async (chainId, account) => {
2240
2472
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2241
2473
  return permits.getActivePermit(_chainId, _account);
2242
- }),
2243
- getActivePermitHash: async (chainId, account) => resultWrapper(async () => {
2474
+ },
2475
+ getActivePermitHash: async (chainId, account) => {
2244
2476
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2245
2477
  return permits.getActivePermitHash(_chainId, _account);
2246
- }),
2478
+ },
2247
2479
  // Mutation methods (auto-fill chainId/account)
2248
- selectActivePermit: async (hash, chainId, account) => resultWrapper(async () => {
2480
+ selectActivePermit: (hash, chainId, account) => {
2249
2481
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2250
2482
  return permits.selectActivePermit(_chainId, _account, hash);
2251
- }),
2252
- removePermit: async (hash, chainId, account) => resultWrapper(async () => {
2483
+ },
2484
+ removePermit: async (hash, chainId, account, force) => {
2253
2485
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2254
- return permits.removePermit(_chainId, _account, hash);
2255
- }),
2256
- removeActivePermit: async (chainId, account) => resultWrapper(async () => {
2486
+ return permits.removePermit(_chainId, _account, hash, force);
2487
+ },
2488
+ removeActivePermit: async (chainId, account) => {
2257
2489
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2258
2490
  return permits.removeActivePermit(_chainId, _account);
2259
- }),
2491
+ },
2260
2492
  // Utils (no context needed)
2261
2493
  getHash: permits.getHash,
2262
2494
  serialize: permits.serialize,
@@ -2266,10 +2498,6 @@ function createCofhesdkClientBase(opts) {
2266
2498
  // Zustand reactive accessors (don't export store directly to prevent mutation)
2267
2499
  getSnapshot: connectStore.getState,
2268
2500
  subscribe: connectStore.subscribe,
2269
- // initialization results
2270
- initializationResults: {
2271
- keyFetchResult
2272
- },
2273
2501
  // flags (read-only: reflect snapshot)
2274
2502
  get connected() {
2275
2503
  return connectStore.getState().connected;
@@ -2287,9 +2515,9 @@ function createCofhesdkClientBase(opts) {
2287
2515
  // Example:
2288
2516
  // async encryptData(data: unknown) {
2289
2517
  // requireConnected();
2290
- // // Use _publicClient and _walletClient for implementation
2518
+ // // Use state.publicClient and state.walletClient for implementation
2291
2519
  // },
2292
2520
  };
2293
2521
  }
2294
2522
 
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 };
2523
+ export { CofhesdkError, CofhesdkErrorCode, DecryptHandlesBuilder, EncryptInputsBuilder, EncryptStep, Encryptable, FheAllUTypes, FheTypes, FheUintUTypes, InitialConnectStore, MOCKS_ZK_VERIFIER_SIGNER_ADDRESS, assertCorrectEncryptedItemInput, createCofhesdkClientBase, createCofhesdkConfigBase, createKeysStore, fetchKeys, fheTypeToString, getCofhesdkConfigItem, isCofhesdkError, isEncryptableItem, isLastEncryptionStep, zkProveWithWorker };