@cofhe/sdk 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/adapters/ethers5.test.ts +174 -0
  3. package/adapters/ethers5.ts +36 -0
  4. package/adapters/ethers6.test.ts +169 -0
  5. package/adapters/ethers6.ts +36 -0
  6. package/adapters/hardhat-node.ts +167 -0
  7. package/adapters/hardhat.hh2.test.ts +159 -0
  8. package/adapters/hardhat.ts +36 -0
  9. package/adapters/index.test.ts +20 -0
  10. package/adapters/index.ts +5 -0
  11. package/adapters/smartWallet.ts +99 -0
  12. package/adapters/test-utils.ts +53 -0
  13. package/adapters/types.ts +6 -0
  14. package/adapters/wagmi.test.ts +156 -0
  15. package/adapters/wagmi.ts +17 -0
  16. package/chains/chains/arbSepolia.ts +14 -0
  17. package/chains/chains/baseSepolia.ts +14 -0
  18. package/chains/chains/hardhat.ts +15 -0
  19. package/chains/chains/localcofhe.ts +14 -0
  20. package/chains/chains/sepolia.ts +14 -0
  21. package/chains/chains.test.ts +50 -0
  22. package/chains/defineChain.ts +18 -0
  23. package/chains/index.ts +35 -0
  24. package/chains/types.ts +32 -0
  25. package/core/baseBuilder.ts +119 -0
  26. package/core/client.test.ts +315 -0
  27. package/core/client.ts +292 -0
  28. package/core/clientTypes.ts +108 -0
  29. package/core/config.test.ts +235 -0
  30. package/core/config.ts +220 -0
  31. package/core/decrypt/MockQueryDecrypterAbi.ts +129 -0
  32. package/core/decrypt/cofheMocksSealOutput.ts +57 -0
  33. package/core/decrypt/decryptHandleBuilder.ts +287 -0
  34. package/core/decrypt/decryptUtils.ts +28 -0
  35. package/core/decrypt/tnSealOutputV1.ts +59 -0
  36. package/core/decrypt/tnSealOutputV2.ts +298 -0
  37. package/core/encrypt/MockZkVerifierAbi.ts +106 -0
  38. package/core/encrypt/cofheMocksZkVerifySign.ts +284 -0
  39. package/core/encrypt/encryptInputsBuilder.test.ts +751 -0
  40. package/core/encrypt/encryptInputsBuilder.ts +560 -0
  41. package/core/encrypt/encryptUtils.ts +67 -0
  42. package/core/encrypt/zkPackProveVerify.ts +335 -0
  43. package/core/error.ts +168 -0
  44. package/core/fetchKeys.test.ts +195 -0
  45. package/core/fetchKeys.ts +144 -0
  46. package/core/index.ts +89 -0
  47. package/core/keyStore.test.ts +226 -0
  48. package/core/keyStore.ts +154 -0
  49. package/core/permits.test.ts +494 -0
  50. package/core/permits.ts +200 -0
  51. package/core/types.ts +398 -0
  52. package/core/utils.ts +130 -0
  53. package/dist/adapters.cjs +88 -0
  54. package/dist/adapters.d.cts +14576 -0
  55. package/dist/adapters.d.ts +14576 -0
  56. package/dist/adapters.js +83 -0
  57. package/dist/chains.cjs +114 -0
  58. package/dist/chains.d.cts +121 -0
  59. package/dist/chains.d.ts +121 -0
  60. package/dist/chains.js +1 -0
  61. package/dist/chunk-UGBVZNRT.js +818 -0
  62. package/dist/chunk-WEAZ25JO.js +105 -0
  63. package/dist/chunk-WGCRJCBR.js +2523 -0
  64. package/dist/clientTypes-5_1nwtUe.d.cts +914 -0
  65. package/dist/clientTypes-Es7fyi65.d.ts +914 -0
  66. package/dist/core.cjs +3414 -0
  67. package/dist/core.d.cts +111 -0
  68. package/dist/core.d.ts +111 -0
  69. package/dist/core.js +3 -0
  70. package/dist/node.cjs +3286 -0
  71. package/dist/node.d.cts +22 -0
  72. package/dist/node.d.ts +22 -0
  73. package/dist/node.js +91 -0
  74. package/dist/permit-fUSe6KKq.d.cts +349 -0
  75. package/dist/permit-fUSe6KKq.d.ts +349 -0
  76. package/dist/permits.cjs +871 -0
  77. package/dist/permits.d.cts +1045 -0
  78. package/dist/permits.d.ts +1045 -0
  79. package/dist/permits.js +1 -0
  80. package/dist/types-KImPrEIe.d.cts +48 -0
  81. package/dist/types-KImPrEIe.d.ts +48 -0
  82. package/dist/web.cjs +3478 -0
  83. package/dist/web.d.cts +38 -0
  84. package/dist/web.d.ts +38 -0
  85. package/dist/web.js +240 -0
  86. package/dist/zkProve.worker.cjs +93 -0
  87. package/dist/zkProve.worker.d.cts +2 -0
  88. package/dist/zkProve.worker.d.ts +2 -0
  89. package/dist/zkProve.worker.js +91 -0
  90. package/node/client.test.ts +147 -0
  91. package/node/config.test.ts +68 -0
  92. package/node/encryptInputs.test.ts +155 -0
  93. package/node/index.ts +97 -0
  94. package/node/storage.ts +51 -0
  95. package/package.json +27 -15
  96. package/permits/index.ts +68 -0
  97. package/permits/localstorage.test.ts +117 -0
  98. package/permits/permit.test.ts +477 -0
  99. package/permits/permit.ts +405 -0
  100. package/permits/sealing.test.ts +84 -0
  101. package/permits/sealing.ts +131 -0
  102. package/permits/signature.ts +79 -0
  103. package/permits/store.test.ts +128 -0
  104. package/permits/store.ts +166 -0
  105. package/permits/test-utils.ts +20 -0
  106. package/permits/types.ts +191 -0
  107. package/permits/utils.ts +62 -0
  108. package/permits/validation.test.ts +288 -0
  109. package/permits/validation.ts +369 -0
  110. package/web/client.web.test.ts +147 -0
  111. package/web/config.web.test.ts +69 -0
  112. package/web/encryptInputs.web.test.ts +172 -0
  113. package/web/index.ts +161 -0
  114. package/web/storage.ts +34 -0
  115. package/web/worker.builder.web.test.ts +148 -0
  116. package/web/worker.config.web.test.ts +329 -0
  117. package/web/worker.output.web.test.ts +84 -0
  118. package/web/workerManager.test.ts +80 -0
  119. package/web/workerManager.ts +214 -0
  120. package/web/workerManager.web.test.ts +114 -0
  121. package/web/zkProve.worker.ts +133 -0
@@ -0,0 +1,2523 @@
1
+ import { hardhat as hardhat$1 } from './chunk-WEAZ25JO.js';
2
+ import { permitStore, PermitUtils } from './chunk-UGBVZNRT.js';
3
+ import { createStore } from 'zustand/vanilla';
4
+ import { createWalletClient, http, encodePacked, keccak256, toBytes, hashMessage, getAddress } from 'viem';
5
+ import { hardhat } from 'viem/chains';
6
+ import { privateKeyToAccount } from 'viem/accounts';
7
+ import { z } from 'zod';
8
+ import { persist, createJSONStorage } from 'zustand/middleware';
9
+ import { produce } from 'immer';
10
+
11
+ // core/error.ts
12
+ var CofhesdkErrorCode = /* @__PURE__ */ ((CofhesdkErrorCode2) => {
13
+ CofhesdkErrorCode2["InternalError"] = "INTERNAL_ERROR";
14
+ CofhesdkErrorCode2["UnknownEnvironment"] = "UNKNOWN_ENVIRONMENT";
15
+ CofhesdkErrorCode2["InitTfheFailed"] = "INIT_TFHE_FAILED";
16
+ CofhesdkErrorCode2["InitViemFailed"] = "INIT_VIEM_FAILED";
17
+ CofhesdkErrorCode2["InitEthersFailed"] = "INIT_ETHERS_FAILED";
18
+ CofhesdkErrorCode2["NotConnected"] = "NOT_CONNECTED";
19
+ CofhesdkErrorCode2["MissingPublicClient"] = "MISSING_PUBLIC_CLIENT";
20
+ CofhesdkErrorCode2["MissingWalletClient"] = "MISSING_WALLET_CLIENT";
21
+ CofhesdkErrorCode2["MissingProviderParam"] = "MISSING_PROVIDER_PARAM";
22
+ CofhesdkErrorCode2["EmptySecurityZonesParam"] = "EMPTY_SECURITY_ZONES_PARAM";
23
+ CofhesdkErrorCode2["InvalidPermitData"] = "INVALID_PERMIT_DATA";
24
+ CofhesdkErrorCode2["InvalidPermitDomain"] = "INVALID_PERMIT_DOMAIN";
25
+ CofhesdkErrorCode2["PermitNotFound"] = "PERMIT_NOT_FOUND";
26
+ CofhesdkErrorCode2["CannotRemoveLastPermit"] = "CANNOT_REMOVE_LAST_PERMIT";
27
+ CofhesdkErrorCode2["AccountUninitialized"] = "ACCOUNT_UNINITIALIZED";
28
+ CofhesdkErrorCode2["ChainIdUninitialized"] = "CHAIN_ID_UNINITIALIZED";
29
+ CofhesdkErrorCode2["SealOutputFailed"] = "SEAL_OUTPUT_FAILED";
30
+ CofhesdkErrorCode2["SealOutputReturnedNull"] = "SEAL_OUTPUT_RETURNED_NULL";
31
+ CofhesdkErrorCode2["InvalidUtype"] = "INVALID_UTYPE";
32
+ CofhesdkErrorCode2["DecryptFailed"] = "DECRYPT_FAILED";
33
+ CofhesdkErrorCode2["DecryptReturnedNull"] = "DECRYPT_RETURNED_NULL";
34
+ CofhesdkErrorCode2["ZkMocksInsertCtHashesFailed"] = "ZK_MOCKS_INSERT_CT_HASHES_FAILED";
35
+ CofhesdkErrorCode2["ZkMocksCalcCtHashesFailed"] = "ZK_MOCKS_CALC_CT_HASHES_FAILED";
36
+ CofhesdkErrorCode2["ZkMocksVerifySignFailed"] = "ZK_MOCKS_VERIFY_SIGN_FAILED";
37
+ CofhesdkErrorCode2["ZkMocksCreateProofSignatureFailed"] = "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED";
38
+ CofhesdkErrorCode2["ZkVerifyFailed"] = "ZK_VERIFY_FAILED";
39
+ CofhesdkErrorCode2["ZkPackFailed"] = "ZK_PACK_FAILED";
40
+ CofhesdkErrorCode2["ZkProveFailed"] = "ZK_PROVE_FAILED";
41
+ CofhesdkErrorCode2["EncryptRemainingInItems"] = "ENCRYPT_REMAINING_IN_ITEMS";
42
+ CofhesdkErrorCode2["ZkUninitialized"] = "ZK_UNINITIALIZED";
43
+ CofhesdkErrorCode2["ZkVerifierUrlUninitialized"] = "ZK_VERIFIER_URL_UNINITIALIZED";
44
+ CofhesdkErrorCode2["ThresholdNetworkUrlUninitialized"] = "THRESHOLD_NETWORK_URL_UNINITIALIZED";
45
+ CofhesdkErrorCode2["MissingConfig"] = "MISSING_CONFIG";
46
+ CofhesdkErrorCode2["UnsupportedChain"] = "UNSUPPORTED_CHAIN";
47
+ CofhesdkErrorCode2["MissingZkBuilderAndCrsGenerator"] = "MISSING_ZK_BUILDER_AND_CRS_GENERATOR";
48
+ CofhesdkErrorCode2["MissingTfhePublicKeyDeserializer"] = "MISSING_TFHE_PUBLIC_KEY_DESERIALIZER";
49
+ CofhesdkErrorCode2["MissingCompactPkeCrsDeserializer"] = "MISSING_COMPACT_PKE_CRS_DESERIALIZER";
50
+ CofhesdkErrorCode2["MissingFheKey"] = "MISSING_FHE_KEY";
51
+ CofhesdkErrorCode2["MissingCrs"] = "MISSING_CRS";
52
+ CofhesdkErrorCode2["FetchKeysFailed"] = "FETCH_KEYS_FAILED";
53
+ CofhesdkErrorCode2["PublicWalletGetChainIdFailed"] = "PUBLIC_WALLET_GET_CHAIN_ID_FAILED";
54
+ CofhesdkErrorCode2["PublicWalletGetAddressesFailed"] = "PUBLIC_WALLET_GET_ADDRESSES_FAILED";
55
+ CofhesdkErrorCode2["RehydrateKeysStoreFailed"] = "REHYDRATE_KEYS_STORE_FAILED";
56
+ return CofhesdkErrorCode2;
57
+ })(CofhesdkErrorCode || {});
58
+ var CofhesdkError = class _CofhesdkError extends Error {
59
+ code;
60
+ cause;
61
+ hint;
62
+ context;
63
+ constructor({ code, message, cause, hint, context }) {
64
+ const fullMessage = cause ? `${message} | Caused by: ${cause.message}` : message;
65
+ super(fullMessage);
66
+ this.name = "CofhesdkError";
67
+ this.code = code;
68
+ this.cause = cause;
69
+ this.hint = hint;
70
+ this.context = context;
71
+ if (Error.captureStackTrace) {
72
+ Error.captureStackTrace(this, _CofhesdkError);
73
+ }
74
+ }
75
+ /**
76
+ * Creates a CofhesdkError from an unknown error
77
+ * If the error is a CofhesdkError, it is returned unchanged, else a new CofhesdkError is created
78
+ * If a wrapperError is provided, it is used to create the new CofhesdkError, else a default is used
79
+ */
80
+ static fromError(error, wrapperError) {
81
+ if (isCofhesdkError(error))
82
+ return error;
83
+ const cause = error instanceof Error ? error : new Error(`${error}`);
84
+ return new _CofhesdkError({
85
+ code: wrapperError?.code ?? "INTERNAL_ERROR" /* InternalError */,
86
+ message: wrapperError?.message ?? "An internal error occurred",
87
+ hint: wrapperError?.hint,
88
+ context: wrapperError?.context,
89
+ cause
90
+ });
91
+ }
92
+ /**
93
+ * Serializes the error to JSON string with proper handling of Error objects
94
+ */
95
+ serialize() {
96
+ return bigintSafeJsonStringify({
97
+ name: this.name,
98
+ code: this.code,
99
+ message: this.message,
100
+ hint: this.hint,
101
+ context: this.context,
102
+ cause: this.cause ? {
103
+ name: this.cause.name,
104
+ message: this.cause.message,
105
+ stack: this.cause.stack
106
+ } : void 0,
107
+ stack: this.stack
108
+ });
109
+ }
110
+ /**
111
+ * Returns a human-readable string representation of the error
112
+ */
113
+ toString() {
114
+ const parts = [`${this.name} [${this.code}]: ${this.message}`];
115
+ if (this.hint) {
116
+ parts.push(`Hint: ${this.hint}`);
117
+ }
118
+ if (this.context && Object.keys(this.context).length > 0) {
119
+ parts.push(`Context: ${bigintSafeJsonStringify(this.context)}`);
120
+ }
121
+ if (this.stack) {
122
+ parts.push(`
123
+ Stack trace:`);
124
+ parts.push(this.stack);
125
+ }
126
+ if (this.cause) {
127
+ parts.push(`
128
+ Caused by: ${this.cause.name}: ${this.cause.message}`);
129
+ if (this.cause.stack) {
130
+ parts.push(this.cause.stack);
131
+ }
132
+ }
133
+ return parts.join("\n");
134
+ }
135
+ };
136
+ var bigintSafeJsonStringify = (value) => {
137
+ return JSON.stringify(value, (key, value2) => {
138
+ if (typeof value2 === "bigint") {
139
+ return `${value2}n`;
140
+ }
141
+ return value2;
142
+ });
143
+ };
144
+ var isCofhesdkError = (error) => error instanceof CofhesdkError;
145
+
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");
203
+ }
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,
215
+ };
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
+ }
237
+ }
238
+ }
239
+ var Encryptable = {
240
+ ...EncryptableFactoriesImpl,
241
+ create: createEncryptableByLiteral
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
+ }
263
+ var toHexString = (bytes) => bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
264
+ var toBigIntOrThrow = (value) => {
265
+ if (typeof value === "bigint") {
266
+ return value;
267
+ }
268
+ try {
269
+ return BigInt(value);
270
+ } catch (error) {
271
+ throw new Error("Invalid input: Unable to convert to bigint");
272
+ }
273
+ };
274
+ var validateBigIntInRange = (value, max, min = 0n) => {
275
+ if (typeof value !== "bigint") {
276
+ throw new Error("Value must be of type bigint");
277
+ }
278
+ if (value > max || value < min) {
279
+ throw new Error(`Value out of range: ${max} - ${min}, try a different uint type`);
280
+ }
281
+ };
282
+ var hexToBytes = (hex) => {
283
+ const bytes = new Uint8Array(hex.length / 2);
284
+ for (let i = 0; i < hex.length; i += 2) {
285
+ bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
286
+ }
287
+ return bytes;
288
+ };
289
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
290
+ async function getPublicClientChainID(publicClient) {
291
+ let chainId = null;
292
+ try {
293
+ chainId = publicClient.chain?.id ?? await publicClient.getChainId();
294
+ } catch (e) {
295
+ throw new CofhesdkError({
296
+ code: "PUBLIC_WALLET_GET_CHAIN_ID_FAILED" /* PublicWalletGetChainIdFailed */,
297
+ message: "getting chain ID from public client failed",
298
+ cause: e instanceof Error ? e : void 0
299
+ });
300
+ }
301
+ if (chainId === null) {
302
+ throw new CofhesdkError({
303
+ code: "PUBLIC_WALLET_GET_CHAIN_ID_FAILED" /* PublicWalletGetChainIdFailed */,
304
+ message: "chain ID from public client is null"
305
+ });
306
+ }
307
+ return chainId;
308
+ }
309
+ async function getWalletClientAccount(walletClient) {
310
+ let address;
311
+ try {
312
+ address = walletClient.account?.address;
313
+ if (!address) {
314
+ address = (await walletClient.getAddresses())?.[0];
315
+ }
316
+ } catch (e) {
317
+ throw new CofhesdkError({
318
+ code: "PUBLIC_WALLET_GET_ADDRESSES_FAILED" /* PublicWalletGetAddressesFailed */,
319
+ message: "getting address from wallet client failed",
320
+ cause: e instanceof Error ? e : void 0
321
+ });
322
+ }
323
+ if (!address) {
324
+ throw new CofhesdkError({
325
+ code: "PUBLIC_WALLET_GET_ADDRESSES_FAILED" /* PublicWalletGetAddressesFailed */,
326
+ message: "address from wallet client is null"
327
+ });
328
+ }
329
+ return address;
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
+ }
367
+
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 = [
536
+ {
537
+ type: "function",
538
+ name: "exists",
539
+ inputs: [],
540
+ outputs: [{ name: "", type: "bool", internalType: "bool" }],
541
+ stateMutability: "pure"
542
+ },
543
+ {
544
+ type: "function",
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"
552
+ },
553
+ {
554
+ type: "function",
555
+ name: "insertPackedCtHashes",
556
+ inputs: [
557
+ { name: "ctHashes", type: "uint256[]", internalType: "uint256[]" },
558
+ { name: "values", type: "uint256[]", internalType: "uint256[]" }
559
+ ],
560
+ outputs: [],
561
+ stateMutability: "nonpayable"
562
+ },
563
+ {
564
+ type: "function",
565
+ name: "zkVerify",
566
+ inputs: [
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: [
574
+ {
575
+ name: "",
576
+ type: "tuple",
577
+ internalType: "struct EncryptedInput",
578
+ components: [
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" }
583
+ ]
584
+ }
585
+ ],
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" },
596
+ { name: "", type: "uint256", internalType: "uint256" }
597
+ ],
598
+ outputs: [{ name: "ctHash", type: "uint256", internalType: "uint256" }],
599
+ stateMutability: "view"
600
+ },
601
+ {
602
+ type: "function",
603
+ name: "zkVerifyCalcCtHashesPacked",
604
+ inputs: [
605
+ { name: "values", type: "uint256[]", internalType: "uint256[]" },
606
+ { name: "utypes", type: "uint8[]", internalType: "uint8[]" },
607
+ { name: "user", type: "address", internalType: "address" },
608
+ { name: "securityZone", type: "uint8", internalType: "uint8" },
609
+ { name: "chainId", type: "uint256", internalType: "uint256" }
610
+ ],
611
+ outputs: [{ name: "ctHashes", type: "uint256[]", internalType: "uint256[]" }],
612
+ stateMutability: "view"
613
+ },
614
+ {
615
+ type: "function",
616
+ name: "zkVerifyPacked",
617
+ inputs: [
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" }
623
+ ],
624
+ outputs: [
625
+ {
626
+ name: "inputs",
627
+ type: "tuple[]",
628
+ internalType: "struct EncryptedInput[]",
629
+ components: [
630
+ { name: "ctHash", type: "uint256", internalType: "uint256" },
631
+ { name: "securityZone", type: "uint8", internalType: "uint8" },
632
+ { name: "utype", type: "uint8", internalType: "uint8" },
633
+ { name: "signature", type: "bytes", internalType: "bytes" }
634
+ ]
635
+ }
636
+ ],
637
+ stateMutability: "nonpayable"
638
+ },
639
+ { type: "error", name: "InvalidInputs", inputs: [] }
640
+ ];
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)
649
+ });
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
+ }
684
+ }
685
+ if (totalBits > MAX_ENCRYPTABLE_BITS) {
686
+ throw new CofhesdkError({
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
+ }
695
+ });
696
+ }
697
+ }
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;
707
+ try {
708
+ ctHashes = await publicClient.readContract({
709
+ address: MocksZkVerifierAddress,
710
+ abi: MockZkVerifierAbi,
711
+ functionName: "zkVerifyCalcCtHashesPacked",
712
+ args: calcCtHashesArgs
713
+ });
714
+ } catch (err) {
715
+ throw new CofhesdkError({
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,
719
+ context: {
720
+ address: MocksZkVerifierAddress,
721
+ items,
722
+ account,
723
+ securityZone,
724
+ publicClient,
725
+ calcCtHashesArgs
726
+ }
727
+ });
728
+ }
729
+ if (ctHashes.length !== items.length) {
730
+ throw new CofhesdkError({
731
+ code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
732
+ message: `mockZkVerifySign calcCtHashes returned incorrect number of ctHashes`,
733
+ context: {
734
+ items,
735
+ account,
736
+ securityZone,
737
+ publicClient,
738
+ calcCtHashesArgs,
739
+ ctHashes
740
+ }
741
+ });
742
+ }
743
+ return items.map((item, index) => ({
744
+ ...item,
745
+ ctHash: ctHashes[index]
746
+ }));
747
+ }
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
+ }
770
+ });
771
+ }
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
785
+ }
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
796
+ });
797
+ signatures.push(signature);
798
+ }
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
807
+ }
808
+ });
809
+ }
810
+ if (signatures.length !== items.length) {
811
+ throw new CofhesdkError({
812
+ code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
813
+ message: `mockZkVerifySign createProofSignatures returned incorrect number of signatures`,
814
+ context: {
815
+ items,
816
+ securityZone
817
+ }
818
+ });
819
+ }
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}`);
862
+ }
863
+ return result.data;
864
+ }
865
+ var getCofhesdkConfigItem = (config, key) => {
866
+ return config[key];
867
+ };
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
+ }
879
+ });
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 }
892
+ });
893
+ }
894
+ return url;
895
+ }
896
+ function getZkVerifierUrlOrThrow(config, chainId) {
897
+ const supportedChain = getSupportedChainOrThrow(config, chainId);
898
+ const url = supportedChain.verifierUrl;
899
+ if (!url) {
900
+ throw new CofhesdkError({
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 }
905
+ });
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: {}
937
+ };
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");
977
+ }
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
+ };
1023
+ }
1024
+ })
1025
+ );
1026
+ return result;
1027
+ }
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}>`];
1034
+ try {
1035
+ serializer(key);
1036
+ return [true, `Key is valid`];
1037
+ } catch (err) {
1038
+ return [false, `Serialization failed <${err}> key length <${key.length}>`];
1039
+ }
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 })
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
+ );
1070
+ }
1071
+ try {
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 })
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);
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;
1148
+ throw new CofhesdkError({
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.",
1152
+ context: {
1153
+ chainId: this.chainId
1154
+ }
1155
+ });
1156
+ }
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;
1164
+ throw new CofhesdkError({
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.",
1168
+ context: {
1169
+ account: this.account
1170
+ }
1171
+ });
1172
+ }
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;
1180
+ throw new CofhesdkError({
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
1186
+ }
1187
+ });
1188
+ }
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;
1196
+ throw new CofhesdkError({
1197
+ code: "MISSING_WALLET_CLIENT" /* MissingWalletClient */,
1198
+ message: "Wallet client not found",
1199
+ hint: "Ensure client.connect() has been called with a walletClient.",
1200
+ context: {
1201
+ walletClient: this.walletClient
1202
+ }
1203
+ });
1204
+ }
1205
+ };
1206
+
1207
+ // core/encrypt/encryptInputsBuilder.ts
1208
+ var EncryptInputsBuilder = class extends BaseBuilder {
1209
+ securityZone;
1210
+ stepCallback;
1211
+ inputItems;
1212
+ zkvWalletClient;
1213
+ tfhePublicKeyDeserializer;
1214
+ compactPkeCrsDeserializer;
1215
+ zkBuilderAndCrsGenerator;
1216
+ initTfhe;
1217
+ zkProveWorkerFn;
1218
+ keysStorage;
1219
+ // Worker configuration (from config, overrideable)
1220
+ useWorker;
1221
+ stepTimestamps = {
1222
+ ["initTfhe" /* InitTfhe */]: 0,
1223
+ ["fetchKeys" /* FetchKeys */]: 0,
1224
+ ["pack" /* Pack */]: 0,
1225
+ ["prove" /* Prove */]: 0,
1226
+ ["verify" /* Verify */]: 0
1227
+ };
1228
+ constructor(params) {
1229
+ super({
1230
+ config: params.config,
1231
+ publicClient: params.publicClient,
1232
+ walletClient: params.walletClient,
1233
+ chainId: params.chainId,
1234
+ account: params.account,
1235
+ requireConnected: params.requireConnected
1236
+ });
1237
+ this.inputItems = params.inputs;
1238
+ this.securityZone = params.securityZone ?? 0;
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
+ }
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
+ }
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
+ }
1272
+ this.zkBuilderAndCrsGenerator = params.zkBuilderAndCrsGenerator;
1273
+ this.initTfhe = params.initTfhe;
1274
+ this.zkProveWorkerFn = params.zkProveWorkerFn;
1275
+ this.keysStorage = params.keysStorage;
1276
+ this.useWorker = params.config?.useWorkers ?? true;
1277
+ }
1278
+ /**
1279
+ * @param account - Account that will create the tx using the encrypted inputs.
1280
+ *
1281
+ * If not provided, the account will be fetched from the connected walletClient.
1282
+ *
1283
+ * Example:
1284
+ * ```typescript
1285
+ * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1286
+ * .setAccount("0x123")
1287
+ * .encrypt();
1288
+ * ```
1289
+ *
1290
+ * @returns The chainable EncryptInputsBuilder instance.
1291
+ */
1292
+ setAccount(account) {
1293
+ this.account = account;
1294
+ return this;
1295
+ }
1296
+ getAccount() {
1297
+ return this.account;
1298
+ }
1299
+ /**
1300
+ * @param chainId - Chain that will consume the encrypted inputs.
1301
+ *
1302
+ * If not provided, the chainId will be fetched from the connected publicClient.
1303
+ *
1304
+ * Example:
1305
+ * ```typescript
1306
+ * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1307
+ * .setChainId(11155111)
1308
+ * .encrypt();
1309
+ * ```
1310
+ *
1311
+ * @returns The chainable EncryptInputsBuilder instance.
1312
+ */
1313
+ setChainId(chainId) {
1314
+ this.chainId = chainId;
1315
+ return this;
1316
+ }
1317
+ getChainId() {
1318
+ return this.chainId;
1319
+ }
1320
+ /**
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
1508
+ *
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.
1512
+ */
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;
1548
+ }
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;
1600
+ }
1601
+ /**
1602
+ * Final step of the encryption process. MUST BE CALLED LAST IN THE CHAIN.
1603
+ *
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
1609
+ *
1610
+ * Example:
1611
+ * ```typescript
1612
+ * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1613
+ * .setAccount('0x123...890') // optional
1614
+ * .setChainId(11155111) // optional
1615
+ * .encrypt(); // execute
1616
+ * ```
1617
+ *
1618
+ * @returns The encrypted inputs.
1619
+ */
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
+ });
1881
+ }
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
+ });
1887
+ }
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
+ });
1906
+ }
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
+ });
1939
+ }
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
+ }
1948
+ throw new CofhesdkError({
1949
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1950
+ message: `sealOutput request failed: ${errorMessage}`,
1951
+ hint: "Check the threshold network URL and request parameters.",
1952
+ context: {
1953
+ thresholdNetworkUrl,
1954
+ status: response.status,
1955
+ statusText: response.statusText,
1956
+ body
1957
+ }
1958
+ });
1959
+ }
1960
+ let submitResponse;
1961
+ try {
1962
+ submitResponse = await response.json();
1963
+ } catch (e) {
1964
+ throw new CofhesdkError({
1965
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1966
+ message: `Failed to parse sealOutput submit response`,
1967
+ cause: e instanceof Error ? e : void 0,
1968
+ context: {
1969
+ thresholdNetworkUrl,
1970
+ body
1971
+ }
1972
+ });
1973
+ }
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
+ });
1984
+ }
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.",
1996
+ context: {
1997
+ thresholdNetworkUrl,
1998
+ requestId,
1999
+ timeoutMs: POLL_TIMEOUT_MS
2000
+ }
2001
+ });
2002
+ }
2003
+ let response;
2004
+ try {
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,
2017
+ context: {
2018
+ thresholdNetworkUrl,
2019
+ requestId
2020
+ }
2021
+ });
2022
+ }
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.",
2028
+ context: {
2029
+ thresholdNetworkUrl,
2030
+ requestId
2031
+ }
2032
+ });
2033
+ }
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
+ }
2042
+ throw new CofhesdkError({
2043
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2044
+ message: `sealOutput status poll failed: ${errorMessage}`,
2045
+ context: {
2046
+ thresholdNetworkUrl,
2047
+ requestId,
2048
+ status: response.status,
2049
+ statusText: response.statusText
2050
+ }
2051
+ });
2052
+ }
2053
+ let statusResponse;
2054
+ try {
2055
+ statusResponse = await response.json();
2056
+ } catch (e) {
2057
+ throw new CofhesdkError({
2058
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2059
+ message: `Failed to parse sealOutput status response`,
2060
+ cause: e instanceof Error ? e : void 0,
2061
+ context: {
2062
+ thresholdNetworkUrl,
2063
+ requestId
2064
+ }
2065
+ });
2066
+ }
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;
2128
+ }
2129
+ /**
2130
+ * @param chainId - Chain to decrypt values from. Used to fetch the threshold network URL and use the correct permit.
2131
+ *
2132
+ * If not provided, the chainId will be fetched from the connected publicClient.
2133
+ *
2134
+ * Example:
2135
+ * ```typescript
2136
+ * const unsealed = await decryptHandle(ctHash, utype)
2137
+ * .setChainId(11155111)
2138
+ * .decrypt();
2139
+ * ```
2140
+ *
2141
+ * @returns The chainable DecryptHandlesBuilder instance.
2142
+ */
2143
+ setChainId(chainId) {
2144
+ this.chainId = chainId;
2145
+ return this;
2146
+ }
2147
+ getChainId() {
2148
+ return this.chainId;
2149
+ }
2150
+ /**
2151
+ * @param account - Account to decrypt values from. Used to fetch the correct permit.
2152
+ *
2153
+ * If not provided, the account will be fetched from the connected walletClient.
2154
+ *
2155
+ * Example:
2156
+ * ```typescript
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;
2167
+ }
2168
+ getAccount() {
2169
+ return this.account;
2170
+ }
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;
2189
+ }
2190
+ getPermitHash() {
2191
+ return this.permitHash;
2192
+ }
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;
2210
+ }
2211
+ getPermit() {
2212
+ return this.permit;
2213
+ }
2214
+ async getThresholdNetworkUrl() {
2215
+ this.assertChainId();
2216
+ return getThresholdNetworkUrlOrThrow(this.config, this.chainId);
2217
+ }
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
+ });
2227
+ }
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;
2262
+ }
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);
2270
+ }
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);
2281
+ }
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);
2315
+ }
2316
+ };
2317
+
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
+ };
2328
+ function createCofhesdkClientBase(opts) {
2329
+ const keysStorage = createKeysStore(opts.config.fheKeyStorage);
2330
+ const connectStore = createStore(() => InitialConnectStore);
2331
+ const updateConnectState = (partial) => {
2332
+ connectStore.setState((state) => ({ ...state, ...partial }));
2333
+ };
2334
+ const _requireConnected = () => {
2335
+ const state = connectStore.getState();
2336
+ const notConnected = !state.connected || !state.account || !state.chainId || !state.publicClient || !state.walletClient;
2337
+ if (notConnected) {
2338
+ throw new CofhesdkError({
2339
+ code: "NOT_CONNECTED" /* NotConnected */,
2340
+ message: "Client must be connected, account and chainId must be initialized",
2341
+ hint: "Ensure client.connect() has been called and awaited.",
2342
+ context: {
2343
+ connected: state.connected,
2344
+ account: state.account,
2345
+ chainId: state.chainId,
2346
+ publicClient: state.publicClient,
2347
+ walletClient: state.walletClient
2348
+ }
2349
+ });
2350
+ }
2351
+ };
2352
+ async function connect(publicClient, walletClient) {
2353
+ const state = connectStore.getState();
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;
2378
+ }
2379
+ }
2380
+ function encryptInputs(inputs) {
2381
+ const state = connectStore.getState();
2382
+ return new EncryptInputsBuilder({
2383
+ inputs,
2384
+ account: state.account ?? void 0,
2385
+ chainId: state.chainId ?? void 0,
2386
+ config: opts.config,
2387
+ publicClient: state.publicClient ?? void 0,
2388
+ walletClient: state.walletClient ?? void 0,
2389
+ zkvWalletClient: opts.config._internal?.zkvWalletClient,
2390
+ tfhePublicKeyDeserializer: opts.tfhePublicKeyDeserializer,
2391
+ compactPkeCrsDeserializer: opts.compactPkeCrsDeserializer,
2392
+ zkBuilderAndCrsGenerator: opts.zkBuilderAndCrsGenerator,
2393
+ initTfhe: opts.initTfhe,
2394
+ zkProveWorkerFn: opts.zkProveWorkerFn,
2395
+ keysStorage,
2396
+ requireConnected: _requireConnected
2397
+ });
2398
+ }
2399
+ function decryptHandle(ctHash, utype) {
2400
+ const state = connectStore.getState();
2401
+ return new DecryptHandlesBuilder({
2402
+ ctHash,
2403
+ utype,
2404
+ chainId: state.chainId ?? void 0,
2405
+ account: state.account ?? void 0,
2406
+ config: opts.config,
2407
+ publicClient: state.publicClient ?? void 0,
2408
+ walletClient: state.walletClient ?? void 0,
2409
+ requireConnected: _requireConnected
2410
+ });
2411
+ }
2412
+ const _getChainIdAndAccount = (chainId, account) => {
2413
+ const state = connectStore.getState();
2414
+ const _chainId = chainId ?? state.chainId;
2415
+ const _account = account ?? state.account;
2416
+ if (_chainId == null || _account == null) {
2417
+ throw new CofhesdkError({
2418
+ code: "NOT_CONNECTED" /* NotConnected */,
2419
+ message: "ChainId or account not available.",
2420
+ hint: "Ensure client.connect() has been called, or provide chainId and account explicitly.",
2421
+ context: {
2422
+ chainId: _chainId,
2423
+ account: _account
2424
+ }
2425
+ });
2426
+ }
2427
+ return { chainId: _chainId, account: _account };
2428
+ };
2429
+ const clientPermits = {
2430
+ // Pass through store access
2431
+ getSnapshot: permits.getSnapshot,
2432
+ subscribe: permits.subscribe,
2433
+ // Creation methods (require connection)
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) => {
2445
+ _requireConnected();
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) => {
2451
+ _requireConnected();
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) => {
2457
+ _requireConnected();
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
+ },
2462
+ // Retrieval methods (auto-fill chainId/account)
2463
+ getPermit: async (hash, chainId, account) => {
2464
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2465
+ return permits.getPermit(_chainId, _account, hash);
2466
+ },
2467
+ getPermits: async (chainId, account) => {
2468
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2469
+ return permits.getPermits(_chainId, _account);
2470
+ },
2471
+ getActivePermit: async (chainId, account) => {
2472
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2473
+ return permits.getActivePermit(_chainId, _account);
2474
+ },
2475
+ getActivePermitHash: async (chainId, account) => {
2476
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2477
+ return permits.getActivePermitHash(_chainId, _account);
2478
+ },
2479
+ // Mutation methods (auto-fill chainId/account)
2480
+ selectActivePermit: (hash, chainId, account) => {
2481
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2482
+ return permits.selectActivePermit(_chainId, _account, hash);
2483
+ },
2484
+ removePermit: async (hash, chainId, account, force) => {
2485
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2486
+ return permits.removePermit(_chainId, _account, hash, force);
2487
+ },
2488
+ removeActivePermit: async (chainId, account) => {
2489
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2490
+ return permits.removeActivePermit(_chainId, _account);
2491
+ },
2492
+ // Utils (no context needed)
2493
+ getHash: permits.getHash,
2494
+ serialize: permits.serialize,
2495
+ deserialize: permits.deserialize
2496
+ };
2497
+ return {
2498
+ // Zustand reactive accessors (don't export store directly to prevent mutation)
2499
+ getSnapshot: connectStore.getState,
2500
+ subscribe: connectStore.subscribe,
2501
+ // flags (read-only: reflect snapshot)
2502
+ get connected() {
2503
+ return connectStore.getState().connected;
2504
+ },
2505
+ get connecting() {
2506
+ return connectStore.getState().connecting;
2507
+ },
2508
+ // config & platform-specific (read-only)
2509
+ config: opts.config,
2510
+ connect,
2511
+ encryptInputs,
2512
+ decryptHandle,
2513
+ permits: clientPermits
2514
+ // Add SDK-specific methods below that require connection
2515
+ // Example:
2516
+ // async encryptData(data: unknown) {
2517
+ // requireConnected();
2518
+ // // Use state.publicClient and state.walletClient for implementation
2519
+ // },
2520
+ };
2521
+ }
2522
+
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 };