@cofhe/sdk 0.0.0-beta-20251027110729

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 (110) hide show
  1. package/CHANGELOG.md +47 -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 +37 -0
  9. package/adapters/index.test.ts +25 -0
  10. package/adapters/index.ts +5 -0
  11. package/adapters/smartWallet.ts +91 -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/sepolia.ts +14 -0
  20. package/chains/chains.test.ts +49 -0
  21. package/chains/defineChain.ts +18 -0
  22. package/chains/index.ts +33 -0
  23. package/chains/types.ts +32 -0
  24. package/core/baseBuilder.ts +138 -0
  25. package/core/client.test.ts +298 -0
  26. package/core/client.ts +308 -0
  27. package/core/config.test.ts +224 -0
  28. package/core/config.ts +213 -0
  29. package/core/decrypt/MockQueryDecrypterAbi.ts +129 -0
  30. package/core/decrypt/cofheMocksSealOutput.ts +57 -0
  31. package/core/decrypt/decryptHandleBuilder.ts +281 -0
  32. package/core/decrypt/decryptUtils.ts +28 -0
  33. package/core/decrypt/tnSealOutput.ts +59 -0
  34. package/core/encrypt/MockZkVerifierAbi.ts +106 -0
  35. package/core/encrypt/cofheMocksZkVerifySign.ts +278 -0
  36. package/core/encrypt/encryptInputsBuilder.test.ts +735 -0
  37. package/core/encrypt/encryptInputsBuilder.ts +512 -0
  38. package/core/encrypt/encryptUtils.ts +64 -0
  39. package/core/encrypt/zkPackProveVerify.ts +273 -0
  40. package/core/error.ts +170 -0
  41. package/core/fetchKeys.test.ts +212 -0
  42. package/core/fetchKeys.ts +170 -0
  43. package/core/index.ts +77 -0
  44. package/core/keyStore.test.ts +226 -0
  45. package/core/keyStore.ts +127 -0
  46. package/core/permits.test.ts +242 -0
  47. package/core/permits.ts +136 -0
  48. package/core/result.test.ts +180 -0
  49. package/core/result.ts +67 -0
  50. package/core/test-utils.ts +45 -0
  51. package/core/types.ts +352 -0
  52. package/core/utils.ts +88 -0
  53. package/dist/adapters.cjs +88 -0
  54. package/dist/adapters.d.cts +14558 -0
  55. package/dist/adapters.d.ts +14558 -0
  56. package/dist/adapters.js +83 -0
  57. package/dist/chains.cjs +101 -0
  58. package/dist/chains.d.cts +99 -0
  59. package/dist/chains.d.ts +99 -0
  60. package/dist/chains.js +1 -0
  61. package/dist/chunk-GZCQQYVI.js +93 -0
  62. package/dist/chunk-KFGPTJ6X.js +2295 -0
  63. package/dist/chunk-LU7BMUUT.js +804 -0
  64. package/dist/core.cjs +3174 -0
  65. package/dist/core.d.cts +16 -0
  66. package/dist/core.d.ts +16 -0
  67. package/dist/core.js +3 -0
  68. package/dist/node.cjs +3090 -0
  69. package/dist/node.d.cts +22 -0
  70. package/dist/node.d.ts +22 -0
  71. package/dist/node.js +90 -0
  72. package/dist/permit-S9CnI6MF.d.cts +333 -0
  73. package/dist/permit-S9CnI6MF.d.ts +333 -0
  74. package/dist/permits.cjs +856 -0
  75. package/dist/permits.d.cts +1056 -0
  76. package/dist/permits.d.ts +1056 -0
  77. package/dist/permits.js +1 -0
  78. package/dist/types-KImPrEIe.d.cts +48 -0
  79. package/dist/types-KImPrEIe.d.ts +48 -0
  80. package/dist/types-PhwGgQvs.d.ts +953 -0
  81. package/dist/types-bB7wLj0q.d.cts +953 -0
  82. package/dist/web.cjs +3067 -0
  83. package/dist/web.d.cts +22 -0
  84. package/dist/web.d.ts +22 -0
  85. package/dist/web.js +64 -0
  86. package/node/client.test.ts +152 -0
  87. package/node/config.test.ts +68 -0
  88. package/node/encryptInputs.test.ts +175 -0
  89. package/node/index.ts +96 -0
  90. package/node/storage.ts +51 -0
  91. package/package.json +120 -0
  92. package/permits/index.ts +67 -0
  93. package/permits/localstorage.test.ts +118 -0
  94. package/permits/permit.test.ts +474 -0
  95. package/permits/permit.ts +396 -0
  96. package/permits/sealing.test.ts +84 -0
  97. package/permits/sealing.ts +131 -0
  98. package/permits/signature.ts +79 -0
  99. package/permits/store.test.ts +128 -0
  100. package/permits/store.ts +168 -0
  101. package/permits/test-utils.ts +20 -0
  102. package/permits/types.ts +174 -0
  103. package/permits/utils.ts +63 -0
  104. package/permits/validation.test.ts +288 -0
  105. package/permits/validation.ts +349 -0
  106. package/web/client.web.test.ts +152 -0
  107. package/web/config.web.test.ts +71 -0
  108. package/web/encryptInputs.web.test.ts +195 -0
  109. package/web/index.ts +97 -0
  110. package/web/storage.ts +20 -0
package/dist/node.cjs ADDED
@@ -0,0 +1,3090 @@
1
+ 'use strict';
2
+
3
+ var vanilla = require('zustand/vanilla');
4
+ var viem = require('viem');
5
+ var zod = require('zod');
6
+ var nacl = require('tweetnacl');
7
+ var middleware = require('zustand/middleware');
8
+ var immer = require('immer');
9
+ var chains = require('viem/chains');
10
+ var accounts = require('viem/accounts');
11
+ var fs = require('fs');
12
+ var path = require('path');
13
+ var nodeTfhe = require('node-tfhe');
14
+
15
+ function _interopNamespace(e) {
16
+ if (e && e.__esModule) return e;
17
+ var n = Object.create(null);
18
+ if (e) {
19
+ Object.keys(e).forEach(function (k) {
20
+ if (k !== 'default') {
21
+ var d = Object.getOwnPropertyDescriptor(e, k);
22
+ Object.defineProperty(n, k, d.get ? d : {
23
+ enumerable: true,
24
+ get: function () { return e[k]; }
25
+ });
26
+ }
27
+ });
28
+ }
29
+ n.default = e;
30
+ return Object.freeze(n);
31
+ }
32
+
33
+ var nacl__namespace = /*#__PURE__*/_interopNamespace(nacl);
34
+
35
+ // core/client.ts
36
+ var EnvironmentSchema = zod.z.enum(["MOCK", "TESTNET", "MAINNET"]);
37
+ var CofheChainSchema = zod.z.object({
38
+ /** Chain ID */
39
+ id: zod.z.number().int().positive(),
40
+ /** Human-readable chain name */
41
+ name: zod.z.string().min(1),
42
+ /** Network identifier */
43
+ network: zod.z.string().min(1),
44
+ /** coFhe service URL */
45
+ coFheUrl: zod.z.string().url(),
46
+ /** Verifier service URL */
47
+ verifierUrl: zod.z.string().url(),
48
+ /** Threshold network service URL */
49
+ thresholdNetworkUrl: zod.z.string().url(),
50
+ /** Environment type */
51
+ environment: EnvironmentSchema
52
+ });
53
+
54
+ // chains/defineChain.ts
55
+ function defineChain(chainConfig) {
56
+ const result = CofheChainSchema.safeParse(chainConfig);
57
+ if (!result.success) {
58
+ const errorMessages = result.error.errors.map((err) => `${err.path.join(".")}: ${err.message}`);
59
+ throw new Error(`Invalid chain configuration: ${errorMessages.join(", ")}`);
60
+ }
61
+ return result.data;
62
+ }
63
+
64
+ // chains/chains/hardhat.ts
65
+ var hardhat = defineChain({
66
+ id: 31337,
67
+ name: "Hardhat",
68
+ network: "localhost",
69
+ // These are unused in the mock environment
70
+ coFheUrl: "http://127.0.0.1:8448",
71
+ verifierUrl: "http://127.0.0.1:3001",
72
+ thresholdNetworkUrl: "http://127.0.0.1:3000",
73
+ environment: "MOCK"
74
+ });
75
+
76
+ // core/error.ts
77
+ var CofhesdkError = class _CofhesdkError extends Error {
78
+ code;
79
+ cause;
80
+ hint;
81
+ context;
82
+ constructor({ code, message, cause, hint, context }) {
83
+ const fullMessage = cause ? `${message} | Caused by: ${cause.message}` : message;
84
+ super(fullMessage);
85
+ this.name = "CofhesdkError";
86
+ this.code = code;
87
+ this.cause = cause;
88
+ this.hint = hint;
89
+ this.context = context;
90
+ if (Error.captureStackTrace) {
91
+ Error.captureStackTrace(this, _CofhesdkError);
92
+ }
93
+ }
94
+ /**
95
+ * Creates a CofhesdkError from an unknown error
96
+ * If the error is a CofhesdkError, it is returned unchanged, else a new CofhesdkError is created
97
+ * If a wrapperError is provided, it is used to create the new CofhesdkError, else a default is used
98
+ */
99
+ static fromError(error, wrapperError) {
100
+ if (isCofhesdkError(error))
101
+ return error;
102
+ const cause = error instanceof Error ? error : new Error(`${error}`);
103
+ return new _CofhesdkError({
104
+ code: wrapperError?.code ?? "INTERNAL_ERROR" /* InternalError */,
105
+ message: wrapperError?.message ?? "An internal error occurred",
106
+ hint: wrapperError?.hint,
107
+ context: wrapperError?.context,
108
+ cause
109
+ });
110
+ }
111
+ /**
112
+ * Serializes the error to JSON string with proper handling of Error objects
113
+ */
114
+ serialize() {
115
+ return bigintSafeJsonStringify({
116
+ name: this.name,
117
+ code: this.code,
118
+ message: this.message,
119
+ hint: this.hint,
120
+ context: this.context,
121
+ cause: this.cause ? {
122
+ name: this.cause.name,
123
+ message: this.cause.message,
124
+ stack: this.cause.stack
125
+ } : void 0,
126
+ stack: this.stack
127
+ });
128
+ }
129
+ /**
130
+ * Returns a human-readable string representation of the error
131
+ */
132
+ toString() {
133
+ const parts = [`${this.name} [${this.code}]: ${this.message}`];
134
+ if (this.hint) {
135
+ parts.push(`Hint: ${this.hint}`);
136
+ }
137
+ if (this.context && Object.keys(this.context).length > 0) {
138
+ parts.push(`Context: ${bigintSafeJsonStringify(this.context)}`);
139
+ }
140
+ if (this.stack) {
141
+ parts.push(`
142
+ Stack trace:`);
143
+ parts.push(this.stack);
144
+ }
145
+ if (this.cause) {
146
+ parts.push(`
147
+ Caused by: ${this.cause.name}: ${this.cause.message}`);
148
+ if (this.cause.stack) {
149
+ parts.push(this.cause.stack);
150
+ }
151
+ }
152
+ return parts.join("\n");
153
+ }
154
+ };
155
+ var bigintSafeJsonStringify = (value) => {
156
+ return JSON.stringify(value, (key, value2) => {
157
+ if (typeof value2 === "bigint") {
158
+ return `${value2}n`;
159
+ }
160
+ return value2;
161
+ });
162
+ };
163
+ var isCofhesdkError = (error) => error instanceof CofhesdkError;
164
+
165
+ // permits/utils.ts
166
+ var fromHexString = (hexString) => {
167
+ const cleanString = hexString.length % 2 === 1 ? `0${hexString}` : hexString;
168
+ const arr = cleanString.replace(/^0x/, "").match(/.{1,2}/g);
169
+ if (!arr)
170
+ return new Uint8Array();
171
+ return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
172
+ };
173
+ var toHexString = (bytes) => bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
174
+ function toBigInt(value) {
175
+ if (typeof value === "string") {
176
+ return BigInt(value);
177
+ } else if (typeof value === "number") {
178
+ return BigInt(value);
179
+ } else if (typeof value === "object") {
180
+ return BigInt("0x" + toHexString(value));
181
+ } else {
182
+ return value;
183
+ }
184
+ }
185
+ function toBeArray(value) {
186
+ const bigIntValue = typeof value === "number" ? BigInt(value) : value;
187
+ const hex = bigIntValue.toString(16);
188
+ const paddedHex = hex.length % 2 === 0 ? hex : "0" + hex;
189
+ return fromHexString(paddedHex);
190
+ }
191
+ function isString(value) {
192
+ if (typeof value !== "string") {
193
+ throw new Error(`Expected value which is \`string\`, received value of type \`${typeof value}\`.`);
194
+ }
195
+ }
196
+ function isNumber(value) {
197
+ const is = typeof value === "number" && !Number.isNaN(value);
198
+ if (!is) {
199
+ throw new Error(`Expected value which is \`number\`, received value of type \`${typeof value}\`.`);
200
+ }
201
+ }
202
+ function isBigIntOrNumber(value) {
203
+ const is = typeof value === "bigint";
204
+ if (!is) {
205
+ try {
206
+ isNumber(value);
207
+ } catch (e) {
208
+ throw new Error(`Value ${value} is not a number or bigint: ${typeof value}`);
209
+ }
210
+ }
211
+ }
212
+ function is0xPrefixed(value) {
213
+ return value.startsWith("0x");
214
+ }
215
+
216
+ // permits/sealing.ts
217
+ var PRIVATE_KEY_LENGTH = 64;
218
+ var PUBLIC_KEY_LENGTH = 64;
219
+ var SealingKey = class _SealingKey {
220
+ /**
221
+ * The private key used for decryption.
222
+ */
223
+ privateKey;
224
+ /**
225
+ * The public key used for encryption.
226
+ */
227
+ publicKey;
228
+ /**
229
+ * Constructs a SealingKey instance with the given private and public keys.
230
+ *
231
+ * @param {string} privateKey - The private key used for decryption.
232
+ * @param {string} publicKey - The public key used for encryption.
233
+ * @throws Will throw an error if the provided keys lengths do not match
234
+ * the required lengths for private and public keys.
235
+ */
236
+ constructor(privateKey, publicKey) {
237
+ if (privateKey.length !== PRIVATE_KEY_LENGTH) {
238
+ throw new Error(`Private key must be of length ${PRIVATE_KEY_LENGTH}`);
239
+ }
240
+ if (publicKey.length !== PUBLIC_KEY_LENGTH) {
241
+ throw new Error(`Public key must be of length ${PUBLIC_KEY_LENGTH}`);
242
+ }
243
+ this.privateKey = privateKey;
244
+ this.publicKey = publicKey;
245
+ }
246
+ unseal = (parsedData) => {
247
+ const nonce = parsedData.nonce instanceof Uint8Array ? parsedData.nonce : new Uint8Array(parsedData.nonce);
248
+ const ephemPublicKey = parsedData.public_key instanceof Uint8Array ? parsedData.public_key : new Uint8Array(parsedData.public_key);
249
+ const dataToDecrypt = parsedData.data instanceof Uint8Array ? parsedData.data : new Uint8Array(parsedData.data);
250
+ const privateKeyBytes = fromHexString(this.privateKey);
251
+ const decryptedMessage = nacl__namespace.box.open(dataToDecrypt, nonce, ephemPublicKey, privateKeyBytes);
252
+ if (!decryptedMessage) {
253
+ throw new Error("Failed to decrypt message");
254
+ }
255
+ return toBigInt(decryptedMessage);
256
+ };
257
+ /**
258
+ * Serializes the SealingKey to a JSON object.
259
+ */
260
+ serialize = () => {
261
+ return {
262
+ privateKey: this.privateKey,
263
+ publicKey: this.publicKey
264
+ };
265
+ };
266
+ /**
267
+ * Deserializes the SealingKey from a JSON object.
268
+ */
269
+ static deserialize = (privateKey, publicKey) => {
270
+ return new _SealingKey(privateKey, publicKey);
271
+ };
272
+ /**
273
+ * Seals (encrypts) the provided message for a receiver with the specified public key.
274
+ *
275
+ * @param {bigint | number} value - The message to be encrypted.
276
+ * @param {string} publicKey - The public key of the intended recipient.
277
+ * @returns string - The encrypted message in hexadecimal format.
278
+ * @static
279
+ * @throws Will throw if the provided publicKey or value do not meet defined preconditions.
280
+ */
281
+ static seal = (value, publicKey) => {
282
+ isString(publicKey);
283
+ isBigIntOrNumber(value);
284
+ const ephemeralKeyPair = nacl__namespace.box.keyPair();
285
+ const nonce = nacl__namespace.randomBytes(nacl__namespace.box.nonceLength);
286
+ const encryptedMessage = nacl__namespace.box(toBeArray(value), nonce, fromHexString(publicKey), ephemeralKeyPair.secretKey);
287
+ return {
288
+ data: encryptedMessage,
289
+ public_key: ephemeralKeyPair.publicKey,
290
+ nonce
291
+ };
292
+ };
293
+ };
294
+ var GenerateSealingKey = async () => {
295
+ const sodiumKeypair = nacl__namespace.box.keyPair();
296
+ return new SealingKey(toHexString(sodiumKeypair.secretKey), toHexString(sodiumKeypair.publicKey));
297
+ };
298
+ var SerializedSealingPair = zod.z.object({
299
+ privateKey: zod.z.string(),
300
+ publicKey: zod.z.string()
301
+ });
302
+ var zPermitWithDefaults = zod.z.object({
303
+ name: zod.z.string().optional().default("Unnamed Permit"),
304
+ type: zod.z.enum(["self", "sharing", "recipient"]),
305
+ issuer: zod.z.string().refine((val) => viem.isAddress(val), {
306
+ message: "Permit issuer :: invalid address"
307
+ }).refine((val) => val !== viem.zeroAddress, {
308
+ message: "Permit issuer :: must not be zeroAddress"
309
+ }),
310
+ expiration: zod.z.number().optional().default(1e12),
311
+ recipient: zod.z.string().optional().default(viem.zeroAddress).refine((val) => viem.isAddress(val), {
312
+ message: "Permit recipient :: invalid address"
313
+ }),
314
+ validatorId: zod.z.number().optional().default(0),
315
+ validatorContract: zod.z.string().optional().default(viem.zeroAddress).refine((val) => viem.isAddress(val), {
316
+ message: "Permit validatorContract :: invalid address"
317
+ }),
318
+ issuerSignature: zod.z.string().optional().default("0x"),
319
+ recipientSignature: zod.z.string().optional().default("0x")
320
+ });
321
+ var zPermitWithSealingPair = zPermitWithDefaults.extend({
322
+ sealingPair: SerializedSealingPair.optional()
323
+ });
324
+ var ValidatorContractRefinement = [
325
+ (data) => data.validatorId !== 0 && data.validatorContract !== viem.zeroAddress || data.validatorId === 0 && data.validatorContract === viem.zeroAddress,
326
+ {
327
+ message: "Permit external validator :: validatorId and validatorContract must either both be set or both be unset.",
328
+ path: ["validatorId", "validatorContract"]
329
+ }
330
+ ];
331
+ var SelfPermitOptionsValidator = zod.z.object({
332
+ type: zod.z.literal("self").optional().default("self"),
333
+ issuer: zod.z.string().refine((val) => viem.isAddress(val), {
334
+ message: "Self permit issuer :: invalid address"
335
+ }).refine((val) => val !== viem.zeroAddress, {
336
+ message: "Self permit issuer :: must not be zeroAddress"
337
+ }),
338
+ name: zod.z.string().optional().default("Unnamed Permit"),
339
+ expiration: zod.z.number().optional().default(1e12),
340
+ recipient: zod.z.string().optional().default(viem.zeroAddress).refine((val) => viem.isAddress(val), {
341
+ message: "Self permit recipient :: invalid address"
342
+ }).refine((val) => val === viem.zeroAddress, {
343
+ message: "Self permit recipient :: must be zeroAddress"
344
+ }),
345
+ validatorId: zod.z.number().optional().default(0),
346
+ validatorContract: zod.z.string().optional().default(viem.zeroAddress).refine((val) => viem.isAddress(val), {
347
+ message: "Self permit validatorContract :: invalid address"
348
+ }),
349
+ issuerSignature: zod.z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
350
+ message: "Self permit issuerSignature :: must be 0x prefixed"
351
+ }),
352
+ recipientSignature: zod.z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
353
+ message: "Self permit recipientSignature :: must be 0x prefixed"
354
+ })
355
+ }).refine(...ValidatorContractRefinement);
356
+ var SelfPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "self", {
357
+ message: "Self permit :: type must be 'self'"
358
+ }).refine((data) => data.recipient === viem.zeroAddress, {
359
+ message: "Self permit :: recipient must be zeroAddress"
360
+ }).refine((data) => data.issuerSignature !== "0x", {
361
+ message: "Self permit :: issuerSignature must be populated"
362
+ }).refine((data) => data.recipientSignature === "0x", {
363
+ message: "Self permit :: recipientSignature must be empty"
364
+ }).refine(...ValidatorContractRefinement);
365
+ var SharingPermitOptionsValidator = zod.z.object({
366
+ type: zod.z.literal("sharing").optional().default("sharing"),
367
+ issuer: zod.z.string().refine((val) => viem.isAddress(val), {
368
+ message: "Sharing permit issuer :: invalid address"
369
+ }).refine((val) => val !== viem.zeroAddress, {
370
+ message: "Sharing permit issuer :: must not be zeroAddress"
371
+ }),
372
+ recipient: zod.z.string().refine((val) => viem.isAddress(val), {
373
+ message: "Sharing permit recipient :: invalid address"
374
+ }).refine((val) => val !== viem.zeroAddress, {
375
+ message: "Sharing permit recipient :: must not be zeroAddress"
376
+ }),
377
+ name: zod.z.string().optional().default("Unnamed Permit"),
378
+ expiration: zod.z.number().optional().default(1e12),
379
+ validatorId: zod.z.number().optional().default(0),
380
+ validatorContract: zod.z.string().optional().default(viem.zeroAddress).refine((val) => viem.isAddress(val), {
381
+ message: "Sharing permit validatorContract :: invalid address"
382
+ }),
383
+ issuerSignature: zod.z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
384
+ message: "Sharing permit issuerSignature :: must be 0x prefixed"
385
+ }),
386
+ recipientSignature: zod.z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
387
+ message: "Sharing permit recipientSignature :: must be 0x prefixed"
388
+ })
389
+ }).refine(...ValidatorContractRefinement);
390
+ var SharingPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "sharing", {
391
+ message: "Sharing permit :: type must be 'sharing'"
392
+ }).refine((data) => data.recipient !== viem.zeroAddress, {
393
+ message: "Sharing permit :: recipient must not be zeroAddress"
394
+ }).refine((data) => data.issuerSignature !== "0x", {
395
+ message: "Sharing permit :: issuerSignature must be populated"
396
+ }).refine((data) => data.recipientSignature === "0x", {
397
+ message: "Sharing permit :: recipientSignature must be empty"
398
+ }).refine(...ValidatorContractRefinement);
399
+ var ImportPermitOptionsValidator = zod.z.object({
400
+ type: zod.z.literal("recipient").optional().default("recipient"),
401
+ issuer: zod.z.string().refine((val) => viem.isAddress(val), {
402
+ message: "Import permit issuer :: invalid address"
403
+ }).refine((val) => val !== viem.zeroAddress, {
404
+ message: "Import permit issuer :: must not be zeroAddress"
405
+ }),
406
+ recipient: zod.z.string().refine((val) => viem.isAddress(val), {
407
+ message: "Import permit recipient :: invalid address"
408
+ }).refine((val) => val !== viem.zeroAddress, {
409
+ message: "Import permit recipient :: must not be zeroAddress"
410
+ }),
411
+ issuerSignature: zod.z.string().refine((val) => is0xPrefixed(val), {
412
+ message: "Import permit issuerSignature :: must be 0x prefixed"
413
+ }).refine((val) => val !== "0x", {
414
+ message: "Import permit :: issuerSignature must be provided"
415
+ }),
416
+ name: zod.z.string().optional().default("Unnamed Permit"),
417
+ expiration: zod.z.number().optional().default(1e12),
418
+ validatorId: zod.z.number().optional().default(0),
419
+ validatorContract: zod.z.string().optional().default(viem.zeroAddress).refine((val) => viem.isAddress(val), {
420
+ message: "Import permit validatorContract :: invalid address"
421
+ }),
422
+ recipientSignature: zod.z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
423
+ message: "Import permit recipientSignature :: must be 0x prefixed"
424
+ })
425
+ }).refine(...ValidatorContractRefinement);
426
+ var ImportPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "recipient", {
427
+ message: "Import permit :: type must be 'recipient'"
428
+ }).refine((data) => data.recipient !== viem.zeroAddress, {
429
+ message: "Import permit :: recipient must not be zeroAddress"
430
+ }).refine((data) => data.issuerSignature !== "0x", {
431
+ message: "Import permit :: issuerSignature must be populated"
432
+ }).refine((data) => data.recipientSignature !== "0x", {
433
+ message: "Import permit :: recipientSignature must be populated"
434
+ }).refine(...ValidatorContractRefinement);
435
+ var validateSelfPermitOptions = (options) => SelfPermitOptionsValidator.safeParse(options);
436
+ var validateSharingPermitOptions = (options) => SharingPermitOptionsValidator.safeParse(options);
437
+ var validateImportPermitOptions = (options) => ImportPermitOptionsValidator.safeParse(options);
438
+ var validateSelfPermit = (permit) => SelfPermitValidator.safeParse(permit);
439
+ var validateSharingPermit = (permit) => SharingPermitValidator.safeParse(permit);
440
+ var validateImportPermit = (permit) => ImportPermitValidator.safeParse(permit);
441
+ var ValidationUtils = {
442
+ /**
443
+ * Check if permit is expired
444
+ */
445
+ isExpired: (permit) => {
446
+ return permit.expiration < Math.floor(Date.now() / 1e3);
447
+ },
448
+ /**
449
+ * Check if permit is signed by the active party
450
+ */
451
+ isSigned: (permit) => {
452
+ if (permit.type === "self" || permit.type === "sharing") {
453
+ return permit.issuerSignature !== "0x";
454
+ }
455
+ if (permit.type === "recipient") {
456
+ return permit.recipientSignature !== "0x";
457
+ }
458
+ return false;
459
+ },
460
+ /**
461
+ * Overall validity checker of a permit
462
+ */
463
+ isValid: (permit) => {
464
+ if (ValidationUtils.isExpired(permit)) {
465
+ return { valid: false, error: "expired" };
466
+ }
467
+ if (!ValidationUtils.isSigned(permit)) {
468
+ return { valid: false, error: "not-signed" };
469
+ }
470
+ return { valid: true, error: null };
471
+ }
472
+ };
473
+
474
+ // permits/signature.ts
475
+ var PermitSignatureAllFields = [
476
+ { name: "issuer", type: "address" },
477
+ { name: "expiration", type: "uint64" },
478
+ { name: "recipient", type: "address" },
479
+ { name: "validatorId", type: "uint256" },
480
+ { name: "validatorContract", type: "address" },
481
+ { name: "sealingKey", type: "bytes32" },
482
+ { name: "issuerSignature", type: "bytes" }
483
+ ];
484
+ var SignatureTypes = {
485
+ PermissionedV2IssuerSelf: [
486
+ "issuer",
487
+ "expiration",
488
+ "recipient",
489
+ "validatorId",
490
+ "validatorContract",
491
+ "sealingKey"
492
+ ],
493
+ PermissionedV2IssuerShared: [
494
+ "issuer",
495
+ "expiration",
496
+ "recipient",
497
+ "validatorId",
498
+ "validatorContract"
499
+ ],
500
+ PermissionedV2Recipient: ["sealingKey", "issuerSignature"]
501
+ };
502
+ var getSignatureTypesAndMessage = (primaryType, fields, values) => {
503
+ const types = {
504
+ [primaryType]: PermitSignatureAllFields.filter((fieldType) => fields.includes(fieldType.name))
505
+ };
506
+ const message = {};
507
+ fields.forEach((field) => {
508
+ if (field in values) {
509
+ message[field] = values[field];
510
+ }
511
+ });
512
+ return { types, primaryType, message };
513
+ };
514
+ var SignatureUtils = {
515
+ /**
516
+ * Get signature parameters for a permit
517
+ */
518
+ getSignatureParams: (permit, primaryType) => {
519
+ return getSignatureTypesAndMessage(primaryType, SignatureTypes[primaryType], permit);
520
+ },
521
+ /**
522
+ * Determine the required signature type based on permit type
523
+ */
524
+ getPrimaryType: (permitType) => {
525
+ if (permitType === "self")
526
+ return "PermissionedV2IssuerSelf";
527
+ if (permitType === "sharing")
528
+ return "PermissionedV2IssuerShared";
529
+ if (permitType === "recipient")
530
+ return "PermissionedV2Recipient";
531
+ throw new Error(`Unknown permit type: ${permitType}`);
532
+ }
533
+ };
534
+
535
+ // permits/permit.ts
536
+ var PermitUtils = {
537
+ /**
538
+ * Create a self permit for personal use
539
+ */
540
+ createSelf: async (options) => {
541
+ const validation = validateSelfPermitOptions(options);
542
+ if (!validation.success) {
543
+ throw new Error(
544
+ "PermitUtils :: createSelf :: Parsing SelfPermitOptions failed " + JSON.stringify(validation.error, null, 2)
545
+ );
546
+ }
547
+ const sealingPair = await GenerateSealingKey();
548
+ return {
549
+ ...validation.data,
550
+ sealingPair,
551
+ _signedDomain: void 0
552
+ };
553
+ },
554
+ /**
555
+ * Create a sharing permit to be shared with another user
556
+ */
557
+ createSharing: async (options) => {
558
+ const validation = validateSharingPermitOptions(options);
559
+ if (!validation.success) {
560
+ throw new Error(
561
+ "PermitUtils :: createSharing :: Parsing SharingPermitOptions failed " + JSON.stringify(validation.error, null, 2)
562
+ );
563
+ }
564
+ const sealingPair = await GenerateSealingKey();
565
+ return {
566
+ ...validation.data,
567
+ sealingPair,
568
+ _signedDomain: void 0
569
+ };
570
+ },
571
+ /**
572
+ * Import a shared permit from various input formats
573
+ */
574
+ importShared: async (options) => {
575
+ let parsedOptions;
576
+ if (typeof options === "string") {
577
+ try {
578
+ parsedOptions = JSON.parse(options);
579
+ } catch (error) {
580
+ throw new Error(`PermitUtils :: importShared :: Failed to parse JSON string: ${error}`);
581
+ }
582
+ } else if (typeof options === "object" && options !== null) {
583
+ parsedOptions = options;
584
+ } else {
585
+ throw new Error(
586
+ "PermitUtils :: importShared :: Invalid input type, expected ImportSharedPermitOptions, object, or string"
587
+ );
588
+ }
589
+ if (parsedOptions.type != null && parsedOptions.type !== "sharing") {
590
+ throw new Error(`PermitUtils :: importShared :: Invalid permit type <${parsedOptions.type}>, must be "sharing"`);
591
+ }
592
+ const validation = validateImportPermitOptions({ ...parsedOptions, type: "recipient" });
593
+ if (!validation.success) {
594
+ throw new Error(
595
+ "PermitUtils :: importShared :: Parsing ImportPermitOptions failed " + JSON.stringify(validation.error, null, 2)
596
+ );
597
+ }
598
+ const sealingPair = await GenerateSealingKey();
599
+ return {
600
+ ...validation.data,
601
+ sealingPair,
602
+ _signedDomain: void 0
603
+ };
604
+ },
605
+ /**
606
+ * Sign a permit with the provided wallet client
607
+ */
608
+ sign: async (permit, publicClient, walletClient) => {
609
+ if (walletClient == null || walletClient.account == null) {
610
+ throw new Error(
611
+ "PermitUtils :: sign - walletClient undefined, you must pass in a `walletClient` for the connected user to create a permit signature"
612
+ );
613
+ }
614
+ const primaryType = SignatureUtils.getPrimaryType(permit.type);
615
+ const domain = await PermitUtils.fetchEIP712Domain(publicClient);
616
+ const { types, message } = SignatureUtils.getSignatureParams(PermitUtils.getPermission(permit, true), primaryType);
617
+ const signature = await walletClient.signTypedData({
618
+ domain,
619
+ types,
620
+ primaryType,
621
+ message,
622
+ account: walletClient.account
623
+ });
624
+ let updatedPermit;
625
+ if (permit.type === "self" || permit.type === "sharing") {
626
+ updatedPermit = {
627
+ ...permit,
628
+ issuerSignature: signature,
629
+ _signedDomain: domain
630
+ };
631
+ } else {
632
+ updatedPermit = {
633
+ ...permit,
634
+ recipientSignature: signature,
635
+ _signedDomain: domain
636
+ };
637
+ }
638
+ return updatedPermit;
639
+ },
640
+ /**
641
+ * Create and sign a self permit in one operation
642
+ */
643
+ createSelfAndSign: async (options, publicClient, walletClient) => {
644
+ const permit = await PermitUtils.createSelf(options);
645
+ return PermitUtils.sign(permit, publicClient, walletClient);
646
+ },
647
+ /**
648
+ * Create and sign a sharing permit in one operation
649
+ */
650
+ createSharingAndSign: async (options, publicClient, walletClient) => {
651
+ const permit = await PermitUtils.createSharing(options);
652
+ return PermitUtils.sign(permit, publicClient, walletClient);
653
+ },
654
+ /**
655
+ * Import and sign a shared permit in one operation from various input formats
656
+ */
657
+ importSharedAndSign: async (options, publicClient, walletClient) => {
658
+ const permit = await PermitUtils.importShared(options);
659
+ return PermitUtils.sign(permit, publicClient, walletClient);
660
+ },
661
+ /**
662
+ * Deserialize a permit from serialized data
663
+ */
664
+ deserialize: (data) => {
665
+ return {
666
+ ...data,
667
+ sealingPair: SealingKey.deserialize(data.sealingPair.privateKey, data.sealingPair.publicKey)
668
+ };
669
+ },
670
+ /**
671
+ * Serialize a permit for storage
672
+ */
673
+ serialize: (permit) => {
674
+ return {
675
+ name: permit.name,
676
+ type: permit.type,
677
+ issuer: permit.issuer,
678
+ expiration: permit.expiration,
679
+ recipient: permit.recipient,
680
+ validatorId: permit.validatorId,
681
+ validatorContract: permit.validatorContract,
682
+ issuerSignature: permit.issuerSignature,
683
+ recipientSignature: permit.recipientSignature,
684
+ _signedDomain: permit._signedDomain,
685
+ sealingPair: permit.sealingPair.serialize()
686
+ };
687
+ },
688
+ /**
689
+ * Validate a permit
690
+ */
691
+ validate: (permit) => {
692
+ if (permit.type === "self") {
693
+ return validateSelfPermit(permit);
694
+ } else if (permit.type === "sharing") {
695
+ return validateSharingPermit(permit);
696
+ } else if (permit.type === "recipient") {
697
+ return validateImportPermit(permit);
698
+ } else {
699
+ throw new Error("PermitUtils :: validate :: Invalid permit type");
700
+ }
701
+ },
702
+ /**
703
+ * Get the permission object from a permit (for use in contracts)
704
+ */
705
+ getPermission: (permit, skipValidation = false) => {
706
+ if (!skipValidation) {
707
+ const validationResult = PermitUtils.validate(permit);
708
+ if (!validationResult.success) {
709
+ throw new Error(
710
+ `PermitUtils :: getPermission :: permit validation failed - ${JSON.stringify(validationResult.error, null, 2)} ${JSON.stringify(permit, null, 2)}`
711
+ );
712
+ }
713
+ }
714
+ return {
715
+ issuer: permit.issuer,
716
+ expiration: permit.expiration,
717
+ recipient: permit.recipient,
718
+ validatorId: permit.validatorId,
719
+ validatorContract: permit.validatorContract,
720
+ sealingKey: `0x${permit.sealingPair.publicKey}`,
721
+ issuerSignature: permit.issuerSignature,
722
+ recipientSignature: permit.recipientSignature
723
+ };
724
+ },
725
+ /**
726
+ * Get a stable hash for the permit (used as key in storage)
727
+ */
728
+ getHash: (permit) => {
729
+ const data = JSON.stringify({
730
+ type: permit.type,
731
+ issuer: permit.issuer,
732
+ expiration: permit.expiration,
733
+ recipient: permit.recipient,
734
+ validatorId: permit.validatorId,
735
+ validatorContract: permit.validatorContract
736
+ });
737
+ return viem.keccak256(viem.toHex(data));
738
+ },
739
+ /**
740
+ * Export permit data for sharing (removes sensitive fields)
741
+ */
742
+ export: (permit) => {
743
+ const cleanedPermit = {
744
+ name: permit.name,
745
+ type: permit.type,
746
+ issuer: permit.issuer,
747
+ expiration: permit.expiration
748
+ };
749
+ if (permit.recipient !== viem.zeroAddress)
750
+ cleanedPermit.recipient = permit.recipient;
751
+ if (permit.validatorId !== 0)
752
+ cleanedPermit.validatorId = permit.validatorId;
753
+ if (permit.validatorContract !== viem.zeroAddress)
754
+ cleanedPermit.validatorContract = permit.validatorContract;
755
+ if (permit.type === "sharing" && permit.issuerSignature !== "0x")
756
+ cleanedPermit.issuerSignature = permit.issuerSignature;
757
+ return JSON.stringify(cleanedPermit, void 0, 2);
758
+ },
759
+ /**
760
+ * Unseal encrypted data using the permit's sealing key
761
+ */
762
+ unseal: (permit, ciphertext) => {
763
+ return permit.sealingPair.unseal(ciphertext);
764
+ },
765
+ /**
766
+ * Check if permit is expired
767
+ */
768
+ isExpired: (permit) => {
769
+ return ValidationUtils.isExpired(permit);
770
+ },
771
+ /**
772
+ * Check if permit is signed
773
+ */
774
+ isSigned: (permit) => {
775
+ return ValidationUtils.isSigned(permit);
776
+ },
777
+ /**
778
+ * Check if permit is valid
779
+ */
780
+ isValid: (permit) => {
781
+ return ValidationUtils.isValid(permit);
782
+ },
783
+ /**
784
+ * Update permit name (returns new permit instance)
785
+ */
786
+ updateName: (permit, name) => {
787
+ return { ...permit, name };
788
+ },
789
+ /**
790
+ * Fetch EIP712 domain from the blockchain
791
+ */
792
+ fetchEIP712Domain: async (publicClient) => {
793
+ const TASK_MANAGER_ADDRESS = "0xeA30c4B8b44078Bbf8a6ef5b9f1eC1626C7848D9";
794
+ const ACL_IFACE = "function acl() view returns (address)";
795
+ const EIP712_DOMAIN_IFACE = "function eip712Domain() public view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions)";
796
+ const aclAbi = viem.parseAbi([ACL_IFACE]);
797
+ const aclAddress = await publicClient.readContract({
798
+ address: TASK_MANAGER_ADDRESS,
799
+ abi: aclAbi,
800
+ functionName: "acl"
801
+ });
802
+ const domainAbi = viem.parseAbi([EIP712_DOMAIN_IFACE]);
803
+ const domain = await publicClient.readContract({
804
+ address: aclAddress,
805
+ abi: domainAbi,
806
+ functionName: "eip712Domain"
807
+ });
808
+ const [_fields, name, version, chainId, verifyingContract, _salt, _extensions] = domain;
809
+ return {
810
+ name,
811
+ version,
812
+ chainId: Number(chainId),
813
+ verifyingContract
814
+ };
815
+ },
816
+ /**
817
+ * Check if permit's signed domain matches the provided domain
818
+ */
819
+ matchesDomain: (permit, domain) => {
820
+ return permit._signedDomain?.name === domain.name && permit._signedDomain?.version === domain.version && permit._signedDomain?.verifyingContract === domain.verifyingContract && permit._signedDomain?.chainId === domain.chainId;
821
+ },
822
+ /**
823
+ * Check if permit's signed domain is valid for the current chain
824
+ */
825
+ checkSignedDomainValid: async (permit, publicClient) => {
826
+ if (permit._signedDomain == null)
827
+ return false;
828
+ const domain = await PermitUtils.fetchEIP712Domain(publicClient);
829
+ return PermitUtils.matchesDomain(permit, domain);
830
+ }
831
+ };
832
+ var _permitStore = vanilla.createStore()(
833
+ middleware.persist(
834
+ () => ({
835
+ permits: {},
836
+ activePermitHash: {}
837
+ }),
838
+ { name: "cofhesdk-permits" }
839
+ )
840
+ );
841
+ var clearStaleStore = () => {
842
+ const state = _permitStore.getState();
843
+ const hasExpectedStructure = state && typeof state === "object" && "permits" in state && "activePermitHash" in state && typeof state.permits === "object" && typeof state.activePermitHash === "object";
844
+ if (hasExpectedStructure)
845
+ return;
846
+ _permitStore.setState({ permits: {}, activePermitHash: {} });
847
+ };
848
+ var getPermit = (chainId, account, hash) => {
849
+ clearStaleStore();
850
+ if (chainId == null || account == null || hash == null)
851
+ return;
852
+ const savedPermit = _permitStore.getState().permits[chainId]?.[account]?.[hash];
853
+ if (savedPermit == null)
854
+ return;
855
+ return PermitUtils.deserialize(savedPermit);
856
+ };
857
+ var getActivePermit = (chainId, account) => {
858
+ clearStaleStore();
859
+ if (chainId == null || account == null)
860
+ return;
861
+ const activePermitHash = _permitStore.getState().activePermitHash[chainId]?.[account];
862
+ return getPermit(chainId, account, activePermitHash);
863
+ };
864
+ var getPermits = (chainId, account) => {
865
+ clearStaleStore();
866
+ if (chainId == null || account == null)
867
+ return {};
868
+ return Object.entries(_permitStore.getState().permits[chainId]?.[account] ?? {}).reduce(
869
+ (acc, [hash, permit]) => {
870
+ if (permit == void 0)
871
+ return acc;
872
+ return { ...acc, [hash]: PermitUtils.deserialize(permit) };
873
+ },
874
+ {}
875
+ );
876
+ };
877
+ var setPermit = (chainId, account, permit) => {
878
+ clearStaleStore();
879
+ _permitStore.setState(
880
+ immer.produce((state) => {
881
+ if (state.permits[chainId] == null)
882
+ state.permits[chainId] = {};
883
+ if (state.permits[chainId][account] == null)
884
+ state.permits[chainId][account] = {};
885
+ state.permits[chainId][account][PermitUtils.getHash(permit)] = PermitUtils.serialize(permit);
886
+ })
887
+ );
888
+ };
889
+ var removePermit = (chainId, account, hash, force) => {
890
+ clearStaleStore();
891
+ _permitStore.setState(
892
+ immer.produce((state) => {
893
+ if (state.permits[chainId] == null)
894
+ state.permits[chainId] = {};
895
+ if (state.activePermitHash[chainId] == null)
896
+ state.activePermitHash[chainId] = {};
897
+ const accountPermits = state.permits[chainId][account];
898
+ if (accountPermits == null)
899
+ return;
900
+ if (accountPermits[hash] == null)
901
+ return;
902
+ if (state.activePermitHash[chainId][account] === hash) {
903
+ const otherPermitHash = Object.keys(accountPermits).find((key) => key !== hash && accountPermits[key] != null);
904
+ if (otherPermitHash) {
905
+ state.activePermitHash[chainId][account] = otherPermitHash;
906
+ } else {
907
+ if (!force) {
908
+ throw new Error("Cannot remove the last permit without force flag");
909
+ }
910
+ state.activePermitHash[chainId][account] = void 0;
911
+ }
912
+ }
913
+ accountPermits[hash] = void 0;
914
+ })
915
+ );
916
+ };
917
+ var getActivePermitHash = (chainId, account) => {
918
+ clearStaleStore();
919
+ if (chainId == null || account == null)
920
+ return void 0;
921
+ return _permitStore.getState().activePermitHash[chainId]?.[account];
922
+ };
923
+ var setActivePermitHash = (chainId, account, hash) => {
924
+ clearStaleStore();
925
+ _permitStore.setState(
926
+ immer.produce((state) => {
927
+ if (state.activePermitHash[chainId] == null)
928
+ state.activePermitHash[chainId] = {};
929
+ state.activePermitHash[chainId][account] = hash;
930
+ })
931
+ );
932
+ };
933
+ var removeActivePermitHash = (chainId, account) => {
934
+ clearStaleStore();
935
+ _permitStore.setState(
936
+ immer.produce((state) => {
937
+ if (state.activePermitHash[chainId])
938
+ state.activePermitHash[chainId][account] = void 0;
939
+ })
940
+ );
941
+ };
942
+ var resetStore = () => {
943
+ clearStaleStore();
944
+ _permitStore.setState({ permits: {}, activePermitHash: {} });
945
+ };
946
+ var permitStore = {
947
+ store: _permitStore,
948
+ getPermit,
949
+ getActivePermit,
950
+ getPermits,
951
+ setPermit,
952
+ removePermit,
953
+ getActivePermitHash,
954
+ setActivePermitHash,
955
+ removeActivePermitHash,
956
+ resetStore
957
+ };
958
+
959
+ // core/result.ts
960
+ var ResultErr = (error) => ({
961
+ success: false,
962
+ data: null,
963
+ error
964
+ });
965
+ var ResultOk = (data) => ({
966
+ success: true,
967
+ data,
968
+ error: null
969
+ });
970
+ var ResultErrOrInternal = (error) => {
971
+ return ResultErr(CofhesdkError.fromError(error));
972
+ };
973
+ var resultWrapper = async (tryFn, catchFn, finallyFn) => {
974
+ try {
975
+ const result = await tryFn();
976
+ return ResultOk(result);
977
+ } catch (error) {
978
+ const result = ResultErrOrInternal(error);
979
+ catchFn?.(result.error);
980
+ return result;
981
+ } finally {
982
+ finallyFn?.();
983
+ }
984
+ };
985
+ var storeActivePermit = async (permit, publicClient, walletClient) => {
986
+ const chainId = await publicClient.getChainId();
987
+ const account = walletClient.account.address;
988
+ permitStore.setPermit(chainId, account, permit);
989
+ permitStore.setActivePermitHash(chainId, account, PermitUtils.getHash(permit));
990
+ };
991
+ var createPermitWithSign = async (options, publicClient, walletClient, permitMethod) => {
992
+ const permit = await permitMethod(options, publicClient, walletClient);
993
+ await storeActivePermit(permit, publicClient, walletClient);
994
+ return permit;
995
+ };
996
+ var createSelf = async (options, publicClient, walletClient) => {
997
+ return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSelfAndSign);
998
+ };
999
+ var createSharing = async (options, publicClient, walletClient) => {
1000
+ return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSharingAndSign);
1001
+ };
1002
+ var importShared = async (options, publicClient, walletClient) => {
1003
+ return createPermitWithSign(options, publicClient, walletClient, PermitUtils.importSharedAndSign);
1004
+ };
1005
+ var getHash = (permit) => {
1006
+ return PermitUtils.getHash(permit);
1007
+ };
1008
+ var serialize = (permit) => {
1009
+ return PermitUtils.serialize(permit);
1010
+ };
1011
+ var deserialize = (serialized) => {
1012
+ return PermitUtils.deserialize(serialized);
1013
+ };
1014
+ var getPermit2 = async (chainId, account, hash) => {
1015
+ return permitStore.getPermit(chainId, account, hash);
1016
+ };
1017
+ var getPermits2 = async (chainId, account) => {
1018
+ return permitStore.getPermits(chainId, account);
1019
+ };
1020
+ var getActivePermit2 = async (chainId, account) => {
1021
+ return permitStore.getActivePermit(chainId, account);
1022
+ };
1023
+ var getActivePermitHash2 = async (chainId, account) => {
1024
+ return permitStore.getActivePermitHash(chainId, account);
1025
+ };
1026
+ var selectActivePermit = async (chainId, account, hash) => {
1027
+ await permitStore.setActivePermitHash(chainId, account, hash);
1028
+ };
1029
+ var removePermit2 = async (chainId, account, hash) => {
1030
+ await permitStore.removePermit(chainId, account, hash);
1031
+ };
1032
+ var removeActivePermit = async (chainId, account) => {
1033
+ await permitStore.removeActivePermitHash(chainId, account);
1034
+ };
1035
+ var permits = {
1036
+ getSnapshot: permitStore.store.getState,
1037
+ subscribe: permitStore.store.subscribe,
1038
+ createSelf,
1039
+ createSharing,
1040
+ importShared,
1041
+ getHash,
1042
+ serialize,
1043
+ deserialize,
1044
+ getPermit: getPermit2,
1045
+ getPermits: getPermits2,
1046
+ getActivePermit: getActivePermit2,
1047
+ getActivePermitHash: getActivePermitHash2,
1048
+ removePermit: removePermit2,
1049
+ selectActivePermit,
1050
+ removeActivePermit
1051
+ };
1052
+ function uint160ToAddress(uint160) {
1053
+ const hexStr = uint160.toString(16).padStart(40, "0");
1054
+ return viem.getAddress("0x" + hexStr);
1055
+ }
1056
+ var isValidUtype = (utype) => {
1057
+ return utype === 0 /* Bool */ || utype === 7 /* Uint160 */ || utype == null || FheUintUTypes.includes(utype);
1058
+ };
1059
+ var convertViaUtype = (utype, value) => {
1060
+ if (utype === 0 /* Bool */) {
1061
+ return !!value;
1062
+ } else if (utype === 7 /* Uint160 */) {
1063
+ return uint160ToAddress(value);
1064
+ } else if (utype == null || FheUintUTypes.includes(utype)) {
1065
+ return value;
1066
+ } else {
1067
+ throw new Error(`convertViaUtype :: invalid utype :: ${utype}`);
1068
+ }
1069
+ };
1070
+ var BaseBuilder = class {
1071
+ config;
1072
+ publicClient;
1073
+ walletClient;
1074
+ chainId;
1075
+ account;
1076
+ requireConnected;
1077
+ constructor(params) {
1078
+ this.config = params.config;
1079
+ this.publicClient = params.publicClient;
1080
+ this.walletClient = params.walletClient;
1081
+ this.chainId = params.chainId;
1082
+ this.account = params.account;
1083
+ this.requireConnected = params.requireConnected;
1084
+ }
1085
+ /**
1086
+ * Gets the chain ID from the instance or fetches it from the public client
1087
+ * @returns The chain ID
1088
+ * @throws {CofhesdkError} If chainId is not set and publicClient is not available
1089
+ */
1090
+ async getChainIdOrThrow() {
1091
+ if (this.chainId)
1092
+ return this.chainId;
1093
+ throw new CofhesdkError({
1094
+ code: "CHAIN_ID_UNINITIALIZED" /* ChainIdUninitialized */,
1095
+ message: "Chain ID is not set",
1096
+ hint: "Ensure client.connect() has been called and awaited, or use setChainId(...) to set the chainId explicitly.",
1097
+ context: {
1098
+ chainId: this.chainId
1099
+ }
1100
+ });
1101
+ }
1102
+ /**
1103
+ * Gets the account address from the instance or fetches it from the wallet client
1104
+ * @returns The account address
1105
+ * @throws {CofhesdkError} If account is not set and walletClient is not available
1106
+ */
1107
+ async getAccountOrThrow() {
1108
+ if (this.account)
1109
+ return this.account;
1110
+ throw new CofhesdkError({
1111
+ code: "ACCOUNT_UNINITIALIZED" /* AccountUninitialized */,
1112
+ message: "Account is not set",
1113
+ hint: "Ensure client.connect() has been called and awaited, or use setAccount(...) to set the account explicitly.",
1114
+ context: {
1115
+ account: this.account
1116
+ }
1117
+ });
1118
+ }
1119
+ /**
1120
+ * Gets the config or throws an error if not available
1121
+ * @returns The config
1122
+ * @throws {CofhesdkError} If config is not set
1123
+ */
1124
+ getConfigOrThrow() {
1125
+ if (this.config)
1126
+ return this.config;
1127
+ throw new CofhesdkError({
1128
+ code: "MISSING_CONFIG" /* MissingConfig */,
1129
+ message: "Builder config is undefined",
1130
+ hint: "Ensure client has been created with a config.",
1131
+ context: {
1132
+ config: this.config
1133
+ }
1134
+ });
1135
+ }
1136
+ /**
1137
+ * Gets the public client or throws an error if not available
1138
+ * @returns The public client
1139
+ * @throws {CofhesdkError} If publicClient is not set
1140
+ */
1141
+ getPublicClientOrThrow() {
1142
+ if (this.publicClient)
1143
+ return this.publicClient;
1144
+ throw new CofhesdkError({
1145
+ code: "MISSING_PUBLIC_CLIENT" /* MissingPublicClient */,
1146
+ message: "Public client not found",
1147
+ hint: "Ensure client.connect() has been called with a publicClient.",
1148
+ context: {
1149
+ publicClient: this.publicClient
1150
+ }
1151
+ });
1152
+ }
1153
+ /**
1154
+ * Gets the wallet client or throws an error if not available
1155
+ * @returns The wallet client
1156
+ * @throws {CofhesdkError} If walletClient is not set
1157
+ */
1158
+ getWalletClientOrThrow() {
1159
+ if (this.walletClient)
1160
+ return this.walletClient;
1161
+ throw new CofhesdkError({
1162
+ code: "MISSING_WALLET_CLIENT" /* MissingWalletClient */,
1163
+ message: "Wallet client not found",
1164
+ hint: "Ensure client.connect() has been called with a walletClient.",
1165
+ context: {
1166
+ walletClient: this.walletClient
1167
+ }
1168
+ });
1169
+ }
1170
+ /**
1171
+ * Requires the client to be connected
1172
+ * @throws {CofhesdkError} If client is not connected
1173
+ */
1174
+ requireConnectedOrThrow() {
1175
+ if (this.requireConnected)
1176
+ this.requireConnected();
1177
+ }
1178
+ };
1179
+ var toHexString2 = (bytes) => bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
1180
+ var toBigIntOrThrow = (value) => {
1181
+ if (typeof value === "bigint") {
1182
+ return value;
1183
+ }
1184
+ try {
1185
+ return BigInt(value);
1186
+ } catch (error) {
1187
+ throw new Error("Invalid input: Unable to convert to bigint");
1188
+ }
1189
+ };
1190
+ var validateBigIntInRange = (value, max, min = 0n) => {
1191
+ if (typeof value !== "bigint") {
1192
+ throw new Error("Value must be of type bigint");
1193
+ }
1194
+ if (value > max || value < min) {
1195
+ throw new Error(`Value out of range: ${max} - ${min}, try a different uint type`);
1196
+ }
1197
+ };
1198
+ var hexToBytes = (hex) => {
1199
+ const bytes = new Uint8Array(hex.length / 2);
1200
+ for (let i = 0; i < hex.length; i += 2) {
1201
+ bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
1202
+ }
1203
+ return bytes;
1204
+ };
1205
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
1206
+ async function getPublicClientChainID(publicClient) {
1207
+ let chainId = null;
1208
+ try {
1209
+ chainId = publicClient.chain?.id ?? await publicClient.getChainId();
1210
+ } catch (e) {
1211
+ throw new CofhesdkError({
1212
+ code: "PUBLIC_WALLET_GET_CHAIN_ID_FAILED" /* PublicWalletGetChainIdFailed */,
1213
+ message: "getting chain ID from public client failed",
1214
+ cause: e instanceof Error ? e : void 0
1215
+ });
1216
+ }
1217
+ if (chainId === null) {
1218
+ throw new CofhesdkError({
1219
+ code: "PUBLIC_WALLET_GET_CHAIN_ID_FAILED" /* PublicWalletGetChainIdFailed */,
1220
+ message: "chain ID from public client is null"
1221
+ });
1222
+ }
1223
+ return chainId;
1224
+ }
1225
+ async function getWalletClientAccount(walletClient) {
1226
+ let address;
1227
+ try {
1228
+ address = walletClient.account?.address;
1229
+ if (!address) {
1230
+ address = (await walletClient.getAddresses())?.[0];
1231
+ }
1232
+ } catch (e) {
1233
+ throw new CofhesdkError({
1234
+ code: "PUBLIC_WALLET_GET_ADDRESSES_FAILED" /* PublicWalletGetAddressesFailed */,
1235
+ message: "getting address from wallet client failed",
1236
+ cause: e instanceof Error ? e : void 0
1237
+ });
1238
+ }
1239
+ if (!address) {
1240
+ throw new CofhesdkError({
1241
+ code: "PUBLIC_WALLET_GET_ADDRESSES_FAILED" /* PublicWalletGetAddressesFailed */,
1242
+ message: "address from wallet client is null"
1243
+ });
1244
+ }
1245
+ return address;
1246
+ }
1247
+
1248
+ // core/decrypt/MockQueryDecrypterAbi.ts
1249
+ var MockQueryDecrypterAbi = [
1250
+ {
1251
+ type: "function",
1252
+ name: "acl",
1253
+ inputs: [],
1254
+ outputs: [{ name: "", type: "address", internalType: "contract ACL" }],
1255
+ stateMutability: "view"
1256
+ },
1257
+ {
1258
+ type: "function",
1259
+ name: "decodeLowLevelReversion",
1260
+ inputs: [{ name: "data", type: "bytes", internalType: "bytes" }],
1261
+ outputs: [{ name: "error", type: "string", internalType: "string" }],
1262
+ stateMutability: "pure"
1263
+ },
1264
+ {
1265
+ type: "function",
1266
+ name: "exists",
1267
+ inputs: [],
1268
+ outputs: [{ name: "", type: "bool", internalType: "bool" }],
1269
+ stateMutability: "pure"
1270
+ },
1271
+ {
1272
+ type: "function",
1273
+ name: "initialize",
1274
+ inputs: [
1275
+ { name: "_taskManager", type: "address", internalType: "address" },
1276
+ { name: "_acl", type: "address", internalType: "address" }
1277
+ ],
1278
+ outputs: [],
1279
+ stateMutability: "nonpayable"
1280
+ },
1281
+ {
1282
+ type: "function",
1283
+ name: "queryDecrypt",
1284
+ inputs: [
1285
+ { name: "ctHash", type: "uint256", internalType: "uint256" },
1286
+ { name: "", type: "uint256", internalType: "uint256" },
1287
+ {
1288
+ name: "permission",
1289
+ type: "tuple",
1290
+ internalType: "struct Permission",
1291
+ components: [
1292
+ { name: "issuer", type: "address", internalType: "address" },
1293
+ { name: "expiration", type: "uint64", internalType: "uint64" },
1294
+ { name: "recipient", type: "address", internalType: "address" },
1295
+ { name: "validatorId", type: "uint256", internalType: "uint256" },
1296
+ {
1297
+ name: "validatorContract",
1298
+ type: "address",
1299
+ internalType: "address"
1300
+ },
1301
+ { name: "sealingKey", type: "bytes32", internalType: "bytes32" },
1302
+ { name: "issuerSignature", type: "bytes", internalType: "bytes" },
1303
+ { name: "recipientSignature", type: "bytes", internalType: "bytes" }
1304
+ ]
1305
+ }
1306
+ ],
1307
+ outputs: [
1308
+ { name: "allowed", type: "bool", internalType: "bool" },
1309
+ { name: "error", type: "string", internalType: "string" },
1310
+ { name: "", type: "uint256", internalType: "uint256" }
1311
+ ],
1312
+ stateMutability: "view"
1313
+ },
1314
+ {
1315
+ type: "function",
1316
+ name: "querySealOutput",
1317
+ inputs: [
1318
+ { name: "ctHash", type: "uint256", internalType: "uint256" },
1319
+ { name: "", type: "uint256", internalType: "uint256" },
1320
+ {
1321
+ name: "permission",
1322
+ type: "tuple",
1323
+ internalType: "struct Permission",
1324
+ components: [
1325
+ { name: "issuer", type: "address", internalType: "address" },
1326
+ { name: "expiration", type: "uint64", internalType: "uint64" },
1327
+ { name: "recipient", type: "address", internalType: "address" },
1328
+ { name: "validatorId", type: "uint256", internalType: "uint256" },
1329
+ {
1330
+ name: "validatorContract",
1331
+ type: "address",
1332
+ internalType: "address"
1333
+ },
1334
+ { name: "sealingKey", type: "bytes32", internalType: "bytes32" },
1335
+ { name: "issuerSignature", type: "bytes", internalType: "bytes" },
1336
+ { name: "recipientSignature", type: "bytes", internalType: "bytes" }
1337
+ ]
1338
+ }
1339
+ ],
1340
+ outputs: [
1341
+ { name: "allowed", type: "bool", internalType: "bool" },
1342
+ { name: "error", type: "string", internalType: "string" },
1343
+ { name: "", type: "bytes32", internalType: "bytes32" }
1344
+ ],
1345
+ stateMutability: "view"
1346
+ },
1347
+ {
1348
+ type: "function",
1349
+ name: "seal",
1350
+ inputs: [
1351
+ { name: "input", type: "uint256", internalType: "uint256" },
1352
+ { name: "key", type: "bytes32", internalType: "bytes32" }
1353
+ ],
1354
+ outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
1355
+ stateMutability: "pure"
1356
+ },
1357
+ {
1358
+ type: "function",
1359
+ name: "taskManager",
1360
+ inputs: [],
1361
+ outputs: [{ name: "", type: "address", internalType: "contract TaskManager" }],
1362
+ stateMutability: "view"
1363
+ },
1364
+ {
1365
+ type: "function",
1366
+ name: "unseal",
1367
+ inputs: [
1368
+ { name: "hashed", type: "bytes32", internalType: "bytes32" },
1369
+ { name: "key", type: "bytes32", internalType: "bytes32" }
1370
+ ],
1371
+ outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
1372
+ stateMutability: "pure"
1373
+ },
1374
+ { type: "error", name: "NotAllowed", inputs: [] },
1375
+ { type: "error", name: "SealingKeyInvalid", inputs: [] },
1376
+ { type: "error", name: "SealingKeyMissing", inputs: [] }
1377
+ ];
1378
+
1379
+ // core/decrypt/cofheMocksSealOutput.ts
1380
+ var MockQueryDecrypterAddress = "0x0000000000000000000000000000000000000200";
1381
+ async function cofheMocksSealOutput(ctHash, utype, permit, publicClient, mocksSealOutputDelay) {
1382
+ if (mocksSealOutputDelay > 0)
1383
+ await sleep(mocksSealOutputDelay);
1384
+ const permission = PermitUtils.getPermission(permit, true);
1385
+ const permissionWithBigInts = {
1386
+ ...permission,
1387
+ expiration: BigInt(permission.expiration),
1388
+ validatorId: BigInt(permission.validatorId)
1389
+ };
1390
+ const [allowed, error, result] = await publicClient.readContract({
1391
+ address: MockQueryDecrypterAddress,
1392
+ abi: MockQueryDecrypterAbi,
1393
+ functionName: "querySealOutput",
1394
+ args: [ctHash, BigInt(utype), permissionWithBigInts]
1395
+ });
1396
+ if (error != "") {
1397
+ throw new CofhesdkError({
1398
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1399
+ message: `mocks querySealOutput call failed: ${error}`
1400
+ });
1401
+ }
1402
+ if (allowed == false) {
1403
+ throw new CofhesdkError({
1404
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1405
+ message: `mocks querySealOutput call failed: ACL Access Denied (NotAllowed)`
1406
+ });
1407
+ }
1408
+ const sealedBigInt = BigInt(result);
1409
+ const sealingKeyBigInt = BigInt(permission.sealingKey);
1410
+ const unsealed = sealedBigInt ^ sealingKeyBigInt;
1411
+ return unsealed;
1412
+ }
1413
+
1414
+ // core/decrypt/tnSealOutput.ts
1415
+ async function tnSealOutput(ctHash, chainId, permission, thresholdNetworkUrl) {
1416
+ let sealed;
1417
+ let errorMessage;
1418
+ let sealOutputResult;
1419
+ const body = {
1420
+ ct_tempkey: ctHash.toString(16).padStart(64, "0"),
1421
+ host_chain_id: chainId,
1422
+ permit: permission
1423
+ };
1424
+ try {
1425
+ const sealOutputRes = await fetch(`${thresholdNetworkUrl}/sealoutput`, {
1426
+ method: "POST",
1427
+ headers: {
1428
+ "Content-Type": "application/json"
1429
+ },
1430
+ body: JSON.stringify(body)
1431
+ });
1432
+ sealOutputResult = await sealOutputRes.json();
1433
+ sealed = sealOutputResult.sealed;
1434
+ errorMessage = sealOutputResult.error_message;
1435
+ } catch (e) {
1436
+ throw new CofhesdkError({
1437
+ code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
1438
+ message: `sealOutput request failed`,
1439
+ hint: "Ensure the threshold network URL is valid.",
1440
+ cause: e instanceof Error ? e : void 0,
1441
+ context: {
1442
+ thresholdNetworkUrl,
1443
+ body
1444
+ }
1445
+ });
1446
+ }
1447
+ if (sealed == null) {
1448
+ throw new CofhesdkError({
1449
+ code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
1450
+ message: `sealOutput request returned no data | Caused by: ${errorMessage}`,
1451
+ context: {
1452
+ thresholdNetworkUrl,
1453
+ body,
1454
+ sealOutputResult
1455
+ }
1456
+ });
1457
+ }
1458
+ return sealed;
1459
+ }
1460
+
1461
+ // core/decrypt/decryptHandleBuilder.ts
1462
+ var DecryptHandlesBuilder = class extends BaseBuilder {
1463
+ ctHash;
1464
+ utype;
1465
+ permitHash;
1466
+ permit;
1467
+ constructor(params) {
1468
+ super({
1469
+ config: params.config,
1470
+ publicClient: params.publicClient,
1471
+ walletClient: params.walletClient,
1472
+ chainId: params.chainId,
1473
+ account: params.account,
1474
+ requireConnected: params.requireConnected
1475
+ });
1476
+ this.ctHash = params.ctHash;
1477
+ this.utype = params.utype;
1478
+ this.permitHash = params.permitHash;
1479
+ this.permit = params.permit;
1480
+ }
1481
+ /**
1482
+ * @param chainId - Chain to decrypt values from. Used to fetch the threshold network URL and use the correct permit.
1483
+ *
1484
+ * If not provided, the chainId will be fetched from the connected publicClient.
1485
+ *
1486
+ * Example:
1487
+ * ```typescript
1488
+ * const unsealed = await decryptHandle(ctHash, utype)
1489
+ * .setChainId(11155111)
1490
+ * .decrypt();
1491
+ * ```
1492
+ *
1493
+ * @returns The chainable DecryptHandlesBuilder instance.
1494
+ */
1495
+ setChainId(chainId) {
1496
+ this.chainId = chainId;
1497
+ return this;
1498
+ }
1499
+ getChainId() {
1500
+ return this.chainId;
1501
+ }
1502
+ /**
1503
+ * @param account - Account to decrypt values from. Used to fetch the correct permit.
1504
+ *
1505
+ * If not provided, the account will be fetched from the connected walletClient.
1506
+ *
1507
+ * Example:
1508
+ * ```typescript
1509
+ * const unsealed = await decryptHandle(ctHash, utype)
1510
+ * .setAccount('0x1234567890123456789012345678901234567890')
1511
+ * .decrypt();
1512
+ * ```
1513
+ *
1514
+ * @returns The chainable DecryptHandlesBuilder instance.
1515
+ */
1516
+ setAccount(account) {
1517
+ this.account = account;
1518
+ return this;
1519
+ }
1520
+ getAccount() {
1521
+ return this.account;
1522
+ }
1523
+ /**
1524
+ * @param permitHash - Permit hash to decrypt values from. Used to fetch the correct permit.
1525
+ *
1526
+ * If not provided, the active permit for the chainId and account will be used.
1527
+ * If `setPermit()` is called, it will be used regardless of chainId, account, or permitHash.
1528
+ *
1529
+ * Example:
1530
+ * ```typescript
1531
+ * const unsealed = await decryptHandle(ctHash, utype)
1532
+ * .setPermitHash('0x1234567890123456789012345678901234567890')
1533
+ * .decrypt();
1534
+ * ```
1535
+ *
1536
+ * @returns The chainable DecryptHandlesBuilder instance.
1537
+ */
1538
+ setPermitHash(permitHash) {
1539
+ this.permitHash = permitHash;
1540
+ return this;
1541
+ }
1542
+ getPermitHash() {
1543
+ return this.permitHash;
1544
+ }
1545
+ /**
1546
+ * @param permit - Permit to decrypt values with. If provided, it will be used regardless of chainId, account, or permitHash.
1547
+ *
1548
+ * If not provided, the permit will be determined by chainId, account, and permitHash.
1549
+ *
1550
+ * Example:
1551
+ * ```typescript
1552
+ * const unsealed = await decryptHandle(ctHash, utype)
1553
+ * .setPermit(permit)
1554
+ * .decrypt();
1555
+ * ```
1556
+ *
1557
+ * @returns The chainable DecryptHandlesBuilder instance.
1558
+ */
1559
+ setPermit(permit) {
1560
+ this.permit = permit;
1561
+ return this;
1562
+ }
1563
+ getPermit() {
1564
+ return this.permit;
1565
+ }
1566
+ getThresholdNetworkUrl(chainId) {
1567
+ const config = this.getConfigOrThrow();
1568
+ return getThresholdNetworkUrlOrThrow(config, chainId);
1569
+ }
1570
+ validateUtypeOrThrow() {
1571
+ if (!isValidUtype(this.utype))
1572
+ throw new CofhesdkError({
1573
+ code: "INVALID_UTYPE" /* InvalidUtype */,
1574
+ message: `Invalid utype to decrypt to`,
1575
+ context: {
1576
+ utype: this.utype
1577
+ }
1578
+ });
1579
+ }
1580
+ async getResolvedPermit() {
1581
+ if (this.permit)
1582
+ return this.permit;
1583
+ const chainId = await this.getChainIdOrThrow();
1584
+ const account = await this.getAccountOrThrow();
1585
+ if (this.permitHash) {
1586
+ const permit2 = await permits.getPermit(chainId, account, this.permitHash);
1587
+ if (!permit2) {
1588
+ throw new CofhesdkError({
1589
+ code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
1590
+ message: `Permit with hash <${this.permitHash}> not found for account <${account}> and chainId <${chainId}>`,
1591
+ hint: "Ensure the permit exists and is valid.",
1592
+ context: {
1593
+ chainId,
1594
+ account,
1595
+ permitHash: this.permitHash
1596
+ }
1597
+ });
1598
+ }
1599
+ return permit2;
1600
+ }
1601
+ const permit = await permits.getActivePermit(chainId, account);
1602
+ if (!permit) {
1603
+ throw new CofhesdkError({
1604
+ code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
1605
+ message: `Active permit not found for chainId <${chainId}> and account <${account}>`,
1606
+ hint: "Ensure a permit exists for this account on this chain.",
1607
+ context: {
1608
+ chainId,
1609
+ account
1610
+ }
1611
+ });
1612
+ }
1613
+ return permit;
1614
+ }
1615
+ /**
1616
+ * On hardhat, interact with MockZkVerifier contract instead of CoFHE
1617
+ */
1618
+ async mocksSealOutput(permit) {
1619
+ const config = this.getConfigOrThrow();
1620
+ const mocksSealOutputDelay = config.mocks.sealOutputDelay;
1621
+ return cofheMocksSealOutput(this.ctHash, this.utype, permit, this.getPublicClientOrThrow(), mocksSealOutputDelay);
1622
+ }
1623
+ /**
1624
+ * In the production context, perform a true decryption with the CoFHE coprocessor.
1625
+ */
1626
+ async productionSealOutput(chainId, permit) {
1627
+ const thresholdNetworkUrl = this.getThresholdNetworkUrl(chainId);
1628
+ const permission = PermitUtils.getPermission(permit, true);
1629
+ const sealed = await tnSealOutput(this.ctHash, chainId, permission, thresholdNetworkUrl);
1630
+ return PermitUtils.unseal(permit, sealed);
1631
+ }
1632
+ /**
1633
+ * Final step of the decryption process. MUST BE CALLED LAST IN THE CHAIN.
1634
+ *
1635
+ * This will:
1636
+ * - Use a permit based on provided permit OR chainId + account + permitHash
1637
+ * - Check permit validity
1638
+ * - Call CoFHE `/sealoutput` with the permit, which returns a sealed (encrypted) item
1639
+ * - Unseal the sealed item with the permit
1640
+ * - Return the unsealed item
1641
+ *
1642
+ * Example:
1643
+ * ```typescript
1644
+ * const unsealed = await decryptHandle(ctHash, utype)
1645
+ * .setChainId(11155111) // optional
1646
+ * .setAccount('0x123...890') // optional
1647
+ * .decrypt(); // execute
1648
+ * ```
1649
+ *
1650
+ * @returns The unsealed item.
1651
+ */
1652
+ decrypt() {
1653
+ return resultWrapper(async () => {
1654
+ await this.requireConnectedOrThrow();
1655
+ this.validateUtypeOrThrow();
1656
+ const permit = await this.getResolvedPermit();
1657
+ await PermitUtils.validate(permit);
1658
+ const chainId = permit._signedDomain.chainId;
1659
+ let unsealed;
1660
+ if (chainId === hardhat.id) {
1661
+ unsealed = await this.mocksSealOutput(permit);
1662
+ } else {
1663
+ unsealed = await this.productionSealOutput(chainId, permit);
1664
+ }
1665
+ return convertViaUtype(this.utype, unsealed);
1666
+ });
1667
+ }
1668
+ };
1669
+
1670
+ // core/encrypt/zkPackProveVerify.ts
1671
+ var MAX_UINT8 = 255n;
1672
+ var MAX_UINT16 = 65535n;
1673
+ var MAX_UINT32 = 4294967295n;
1674
+ var MAX_UINT64 = 18446744073709551615n;
1675
+ var MAX_UINT128 = 340282366920938463463374607431768211455n;
1676
+ var MAX_UINT160 = 1461501637330902918203684832716283019655932542975n;
1677
+ var MAX_ENCRYPTABLE_BITS = 2048;
1678
+ var zkPack = (items, builder) => {
1679
+ let totalBits = 0;
1680
+ for (const item of items) {
1681
+ switch (item.utype) {
1682
+ case 0 /* Bool */: {
1683
+ builder.push_boolean(item.data);
1684
+ totalBits += 1;
1685
+ break;
1686
+ }
1687
+ case 2 /* Uint8 */: {
1688
+ const bint = toBigIntOrThrow(item.data);
1689
+ validateBigIntInRange(bint, MAX_UINT8);
1690
+ builder.push_u8(parseInt(bint.toString()));
1691
+ totalBits += 8;
1692
+ break;
1693
+ }
1694
+ case 3 /* Uint16 */: {
1695
+ const bint = toBigIntOrThrow(item.data);
1696
+ validateBigIntInRange(bint, MAX_UINT16);
1697
+ builder.push_u16(parseInt(bint.toString()));
1698
+ totalBits += 16;
1699
+ break;
1700
+ }
1701
+ case 4 /* Uint32 */: {
1702
+ const bint = toBigIntOrThrow(item.data);
1703
+ validateBigIntInRange(bint, MAX_UINT32);
1704
+ builder.push_u32(parseInt(bint.toString()));
1705
+ totalBits += 32;
1706
+ break;
1707
+ }
1708
+ case 5 /* Uint64 */: {
1709
+ const bint = toBigIntOrThrow(item.data);
1710
+ validateBigIntInRange(bint, MAX_UINT64);
1711
+ builder.push_u64(bint);
1712
+ totalBits += 64;
1713
+ break;
1714
+ }
1715
+ case 6 /* Uint128 */: {
1716
+ const bint = toBigIntOrThrow(item.data);
1717
+ validateBigIntInRange(bint, MAX_UINT128);
1718
+ builder.push_u128(bint);
1719
+ totalBits += 128;
1720
+ break;
1721
+ }
1722
+ case 7 /* Uint160 */: {
1723
+ const bint = toBigIntOrThrow(item.data);
1724
+ validateBigIntInRange(bint, MAX_UINT160);
1725
+ builder.push_u160(bint);
1726
+ totalBits += 160;
1727
+ break;
1728
+ }
1729
+ default: {
1730
+ throw new CofhesdkError({
1731
+ code: "ZK_PACK_FAILED" /* ZkPackFailed */,
1732
+ message: `Invalid utype: ${item.utype}`,
1733
+ hint: `Ensure that the utype is valid, using the Encryptable type, for example: Encryptable.uint128(100n)`,
1734
+ context: {
1735
+ item
1736
+ }
1737
+ });
1738
+ }
1739
+ }
1740
+ }
1741
+ if (totalBits > MAX_ENCRYPTABLE_BITS) {
1742
+ throw new CofhesdkError({
1743
+ code: "ZK_PACK_FAILED" /* ZkPackFailed */,
1744
+ message: `Total bits ${totalBits} exceeds ${MAX_ENCRYPTABLE_BITS}`,
1745
+ hint: `Ensure that the total bits of the items to encrypt does not exceed ${MAX_ENCRYPTABLE_BITS}`,
1746
+ context: {
1747
+ totalBits,
1748
+ maxBits: MAX_ENCRYPTABLE_BITS,
1749
+ items
1750
+ }
1751
+ });
1752
+ }
1753
+ return builder;
1754
+ };
1755
+ var zkProve = async (builder, crs, address, securityZone, chainId) => {
1756
+ const metadata = constructZkPoKMetadata(address, securityZone, chainId);
1757
+ return new Promise((resolve) => {
1758
+ setTimeout(() => {
1759
+ const compactList = builder.build_with_proof_packed(
1760
+ crs,
1761
+ metadata,
1762
+ 1
1763
+ // ZkComputeLoad.Verify
1764
+ );
1765
+ resolve(compactList.serialize());
1766
+ }, 0);
1767
+ });
1768
+ };
1769
+ var constructZkPoKMetadata = (accountAddr, securityZone, chainId) => {
1770
+ const accountAddrNoPrefix = accountAddr.startsWith("0x") ? accountAddr.slice(2) : accountAddr;
1771
+ const accountBytes = hexToBytes(accountAddrNoPrefix);
1772
+ const chainIdBytes = new Uint8Array(32);
1773
+ let value = chainId;
1774
+ for (let i = 31; i >= 0 && value > 0; i--) {
1775
+ chainIdBytes[i] = value & 255;
1776
+ value = value >>> 8;
1777
+ }
1778
+ const metadata = new Uint8Array(1 + accountBytes.length + 32);
1779
+ metadata[0] = securityZone;
1780
+ metadata.set(accountBytes, 1);
1781
+ metadata.set(chainIdBytes, 1 + accountBytes.length);
1782
+ return metadata;
1783
+ };
1784
+ var zkVerify = async (verifierUrl, serializedBytes, address, securityZone, chainId) => {
1785
+ const packed_list = toHexString2(serializedBytes);
1786
+ const sz_byte = new Uint8Array([securityZone]);
1787
+ const payload = {
1788
+ packed_list,
1789
+ account_addr: address,
1790
+ security_zone: sz_byte[0],
1791
+ chain_id: chainId
1792
+ };
1793
+ const body = JSON.stringify(payload);
1794
+ try {
1795
+ const response = await fetch(`${verifierUrl}/verify`, {
1796
+ method: "POST",
1797
+ headers: {
1798
+ "Content-Type": "application/json"
1799
+ },
1800
+ body
1801
+ });
1802
+ if (!response.ok) {
1803
+ const errorBody = await response.text();
1804
+ throw new CofhesdkError({
1805
+ code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
1806
+ message: `HTTP error! ZK proof verification failed - ${errorBody}`
1807
+ });
1808
+ }
1809
+ const json = await response.json();
1810
+ if (json.status !== "success") {
1811
+ throw new CofhesdkError({
1812
+ code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
1813
+ message: `ZK proof verification response malformed - ${json.error}`
1814
+ });
1815
+ }
1816
+ return json.data.map(({ ct_hash, signature, recid }) => {
1817
+ return {
1818
+ ct_hash,
1819
+ signature: concatSigRecid(signature, recid)
1820
+ };
1821
+ });
1822
+ } catch (e) {
1823
+ throw new CofhesdkError({
1824
+ code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
1825
+ message: `ZK proof verification failed`,
1826
+ cause: e instanceof Error ? e : void 0
1827
+ });
1828
+ }
1829
+ };
1830
+ var concatSigRecid = (signature, recid) => {
1831
+ return signature + (recid + 27).toString(16).padStart(2, "0");
1832
+ };
1833
+
1834
+ // core/encrypt/MockZkVerifierAbi.ts
1835
+ var MockZkVerifierAbi = [
1836
+ {
1837
+ type: "function",
1838
+ name: "exists",
1839
+ inputs: [],
1840
+ outputs: [{ name: "", type: "bool", internalType: "bool" }],
1841
+ stateMutability: "pure"
1842
+ },
1843
+ {
1844
+ type: "function",
1845
+ name: "insertCtHash",
1846
+ inputs: [
1847
+ { name: "ctHash", type: "uint256", internalType: "uint256" },
1848
+ { name: "value", type: "uint256", internalType: "uint256" }
1849
+ ],
1850
+ outputs: [],
1851
+ stateMutability: "nonpayable"
1852
+ },
1853
+ {
1854
+ type: "function",
1855
+ name: "insertPackedCtHashes",
1856
+ inputs: [
1857
+ { name: "ctHashes", type: "uint256[]", internalType: "uint256[]" },
1858
+ { name: "values", type: "uint256[]", internalType: "uint256[]" }
1859
+ ],
1860
+ outputs: [],
1861
+ stateMutability: "nonpayable"
1862
+ },
1863
+ {
1864
+ type: "function",
1865
+ name: "zkVerify",
1866
+ inputs: [
1867
+ { name: "value", type: "uint256", internalType: "uint256" },
1868
+ { name: "utype", type: "uint8", internalType: "uint8" },
1869
+ { name: "user", type: "address", internalType: "address" },
1870
+ { name: "securityZone", type: "uint8", internalType: "uint8" },
1871
+ { name: "", type: "uint256", internalType: "uint256" }
1872
+ ],
1873
+ outputs: [
1874
+ {
1875
+ name: "",
1876
+ type: "tuple",
1877
+ internalType: "struct EncryptedInput",
1878
+ components: [
1879
+ { name: "ctHash", type: "uint256", internalType: "uint256" },
1880
+ { name: "securityZone", type: "uint8", internalType: "uint8" },
1881
+ { name: "utype", type: "uint8", internalType: "uint8" },
1882
+ { name: "signature", type: "bytes", internalType: "bytes" }
1883
+ ]
1884
+ }
1885
+ ],
1886
+ stateMutability: "nonpayable"
1887
+ },
1888
+ {
1889
+ type: "function",
1890
+ name: "zkVerifyCalcCtHash",
1891
+ inputs: [
1892
+ { name: "value", type: "uint256", internalType: "uint256" },
1893
+ { name: "utype", type: "uint8", internalType: "uint8" },
1894
+ { name: "user", type: "address", internalType: "address" },
1895
+ { name: "securityZone", type: "uint8", internalType: "uint8" },
1896
+ { name: "", type: "uint256", internalType: "uint256" }
1897
+ ],
1898
+ outputs: [{ name: "ctHash", type: "uint256", internalType: "uint256" }],
1899
+ stateMutability: "view"
1900
+ },
1901
+ {
1902
+ type: "function",
1903
+ name: "zkVerifyCalcCtHashesPacked",
1904
+ inputs: [
1905
+ { name: "values", type: "uint256[]", internalType: "uint256[]" },
1906
+ { name: "utypes", type: "uint8[]", internalType: "uint8[]" },
1907
+ { name: "user", type: "address", internalType: "address" },
1908
+ { name: "securityZone", type: "uint8", internalType: "uint8" },
1909
+ { name: "chainId", type: "uint256", internalType: "uint256" }
1910
+ ],
1911
+ outputs: [{ name: "ctHashes", type: "uint256[]", internalType: "uint256[]" }],
1912
+ stateMutability: "view"
1913
+ },
1914
+ {
1915
+ type: "function",
1916
+ name: "zkVerifyPacked",
1917
+ inputs: [
1918
+ { name: "values", type: "uint256[]", internalType: "uint256[]" },
1919
+ { name: "utypes", type: "uint8[]", internalType: "uint8[]" },
1920
+ { name: "user", type: "address", internalType: "address" },
1921
+ { name: "securityZone", type: "uint8", internalType: "uint8" },
1922
+ { name: "chainId", type: "uint256", internalType: "uint256" }
1923
+ ],
1924
+ outputs: [
1925
+ {
1926
+ name: "inputs",
1927
+ type: "tuple[]",
1928
+ internalType: "struct EncryptedInput[]",
1929
+ components: [
1930
+ { name: "ctHash", type: "uint256", internalType: "uint256" },
1931
+ { name: "securityZone", type: "uint8", internalType: "uint8" },
1932
+ { name: "utype", type: "uint8", internalType: "uint8" },
1933
+ { name: "signature", type: "bytes", internalType: "bytes" }
1934
+ ]
1935
+ }
1936
+ ],
1937
+ stateMutability: "nonpayable"
1938
+ },
1939
+ { type: "error", name: "InvalidInputs", inputs: [] }
1940
+ ];
1941
+ var MocksZkVerifierAddress = "0x0000000000000000000000000000000000000100";
1942
+ var MocksEncryptedInputSignerPkey = "0x6c8d7f768a6bb4aafe85e8a2f5a9680355239c7e14646ed62b044e39de154512";
1943
+ async function cofheMocksCheckEncryptableBits(items) {
1944
+ let totalBits = 0;
1945
+ for (const item of items) {
1946
+ switch (item.utype) {
1947
+ case 0 /* Bool */: {
1948
+ totalBits += 1;
1949
+ break;
1950
+ }
1951
+ case 2 /* Uint8 */: {
1952
+ totalBits += 8;
1953
+ break;
1954
+ }
1955
+ case 3 /* Uint16 */: {
1956
+ totalBits += 16;
1957
+ break;
1958
+ }
1959
+ case 4 /* Uint32 */: {
1960
+ totalBits += 32;
1961
+ break;
1962
+ }
1963
+ case 5 /* Uint64 */: {
1964
+ totalBits += 64;
1965
+ break;
1966
+ }
1967
+ case 6 /* Uint128 */: {
1968
+ totalBits += 128;
1969
+ break;
1970
+ }
1971
+ case 7 /* Uint160 */: {
1972
+ totalBits += 160;
1973
+ break;
1974
+ }
1975
+ }
1976
+ }
1977
+ if (totalBits > MAX_ENCRYPTABLE_BITS) {
1978
+ throw new CofhesdkError({
1979
+ code: "ZK_PACK_FAILED" /* ZkPackFailed */,
1980
+ message: `Total bits ${totalBits} exceeds ${MAX_ENCRYPTABLE_BITS}`,
1981
+ hint: `Ensure that the total bits of the items to encrypt does not exceed ${MAX_ENCRYPTABLE_BITS}`,
1982
+ context: {
1983
+ totalBits,
1984
+ maxBits: MAX_ENCRYPTABLE_BITS,
1985
+ items
1986
+ }
1987
+ });
1988
+ }
1989
+ }
1990
+ async function calcCtHashes(items, account, securityZone, publicClient) {
1991
+ const calcCtHashesArgs = [
1992
+ items.map(({ data }) => BigInt(data)),
1993
+ items.map(({ utype }) => utype),
1994
+ account,
1995
+ securityZone,
1996
+ BigInt(chains.hardhat.id)
1997
+ ];
1998
+ let ctHashes;
1999
+ try {
2000
+ ctHashes = await publicClient.readContract({
2001
+ address: MocksZkVerifierAddress,
2002
+ abi: MockZkVerifierAbi,
2003
+ functionName: "zkVerifyCalcCtHashesPacked",
2004
+ args: calcCtHashesArgs
2005
+ });
2006
+ } catch (err) {
2007
+ throw new CofhesdkError({
2008
+ code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
2009
+ message: `mockZkVerifySign calcCtHashes failed while calling zkVerifyCalcCtHashesPacked`,
2010
+ cause: err instanceof Error ? err : void 0,
2011
+ context: {
2012
+ address: MocksZkVerifierAddress,
2013
+ items,
2014
+ account,
2015
+ securityZone,
2016
+ publicClient,
2017
+ calcCtHashesArgs
2018
+ }
2019
+ });
2020
+ }
2021
+ if (ctHashes.length !== items.length) {
2022
+ throw new CofhesdkError({
2023
+ code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
2024
+ message: `mockZkVerifySign calcCtHashes returned incorrect number of ctHashes`,
2025
+ context: {
2026
+ items,
2027
+ account,
2028
+ securityZone,
2029
+ publicClient,
2030
+ calcCtHashesArgs,
2031
+ ctHashes
2032
+ }
2033
+ });
2034
+ }
2035
+ return items.map((item, index) => ({
2036
+ ...item,
2037
+ ctHash: ctHashes[index]
2038
+ }));
2039
+ }
2040
+ async function insertCtHashes(items, walletClient) {
2041
+ const insertPackedCtHashesArgs = [items.map(({ ctHash }) => ctHash), items.map(({ data }) => BigInt(data))];
2042
+ try {
2043
+ const account = walletClient.account;
2044
+ await walletClient.writeContract({
2045
+ address: MocksZkVerifierAddress,
2046
+ abi: MockZkVerifierAbi,
2047
+ functionName: "insertPackedCtHashes",
2048
+ args: insertPackedCtHashesArgs,
2049
+ chain: chains.hardhat,
2050
+ account
2051
+ });
2052
+ } catch (err) {
2053
+ throw new CofhesdkError({
2054
+ code: "ZK_MOCKS_INSERT_CT_HASHES_FAILED" /* ZkMocksInsertCtHashesFailed */,
2055
+ message: `mockZkVerifySign insertPackedCtHashes failed while calling insertPackedCtHashes`,
2056
+ cause: err instanceof Error ? err : void 0,
2057
+ context: {
2058
+ items,
2059
+ walletClient,
2060
+ insertPackedCtHashesArgs
2061
+ }
2062
+ });
2063
+ }
2064
+ }
2065
+ async function createProofSignatures(items, securityZone) {
2066
+ let signatures = [];
2067
+ let encInputSignerClient;
2068
+ try {
2069
+ encInputSignerClient = viem.createWalletClient({
2070
+ chain: chains.hardhat,
2071
+ transport: viem.http(),
2072
+ account: accounts.privateKeyToAccount(MocksEncryptedInputSignerPkey)
2073
+ });
2074
+ } catch (err) {
2075
+ throw new CofhesdkError({
2076
+ code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
2077
+ message: `mockZkVerifySign createProofSignatures failed while creating wallet client`,
2078
+ cause: err instanceof Error ? err : void 0,
2079
+ context: {
2080
+ MocksEncryptedInputSignerPkey
2081
+ }
2082
+ });
2083
+ }
2084
+ try {
2085
+ for (const item of items) {
2086
+ const packedData = viem.encodePacked(["uint256", "int32", "uint8"], [BigInt(item.data), securityZone, item.utype]);
2087
+ const messageHash = viem.keccak256(packedData);
2088
+ const ethSignedHash = viem.hashMessage({ raw: viem.toBytes(messageHash) });
2089
+ const signature = await encInputSignerClient.signMessage({
2090
+ message: { raw: viem.toBytes(ethSignedHash) },
2091
+ account: encInputSignerClient.account
2092
+ });
2093
+ signatures.push(signature);
2094
+ }
2095
+ } catch (err) {
2096
+ throw new CofhesdkError({
2097
+ code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
2098
+ message: `mockZkVerifySign createProofSignatures failed while calling signMessage`,
2099
+ cause: err instanceof Error ? err : void 0,
2100
+ context: {
2101
+ items,
2102
+ securityZone
2103
+ }
2104
+ });
2105
+ }
2106
+ if (signatures.length !== items.length) {
2107
+ throw new CofhesdkError({
2108
+ code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
2109
+ message: `mockZkVerifySign createProofSignatures returned incorrect number of signatures`,
2110
+ context: {
2111
+ items,
2112
+ securityZone
2113
+ }
2114
+ });
2115
+ }
2116
+ return signatures;
2117
+ }
2118
+ async function cofheMocksZkVerifySign(items, account, securityZone, publicClient, walletClient, zkvWalletClient) {
2119
+ const _walletClient = zkvWalletClient ?? walletClient;
2120
+ const encryptableItems = await calcCtHashes(items, account, securityZone, publicClient);
2121
+ await insertCtHashes(encryptableItems, _walletClient);
2122
+ const signatures = await createProofSignatures(encryptableItems, securityZone);
2123
+ return encryptableItems.map((item, index) => ({
2124
+ ct_hash: item.ctHash.toString(),
2125
+ signature: signatures[index]
2126
+ }));
2127
+ }
2128
+ function createKeysStore(storage) {
2129
+ const keysStore = storage ? vanilla.createStore()(
2130
+ middleware.persist(
2131
+ () => ({
2132
+ fhe: {},
2133
+ crs: {}
2134
+ }),
2135
+ {
2136
+ name: "cofhesdk-keys",
2137
+ storage: middleware.createJSONStorage(() => storage),
2138
+ merge: (persistedState, currentState) => {
2139
+ const persisted = persistedState;
2140
+ const current = currentState;
2141
+ const mergedFhe = { ...persisted.fhe };
2142
+ const allChainIds = /* @__PURE__ */ new Set([...Object.keys(current.fhe), ...Object.keys(persisted.fhe)]);
2143
+ for (const chainId of allChainIds) {
2144
+ const persistedZones = persisted.fhe[chainId] || {};
2145
+ const currentZones = current.fhe[chainId] || {};
2146
+ mergedFhe[chainId] = { ...persistedZones, ...currentZones };
2147
+ }
2148
+ const mergedCrs = { ...persisted.crs, ...current.crs };
2149
+ return {
2150
+ fhe: mergedFhe,
2151
+ crs: mergedCrs
2152
+ };
2153
+ }
2154
+ }
2155
+ )
2156
+ ) : vanilla.createStore()(() => ({
2157
+ fhe: {},
2158
+ crs: {}
2159
+ }));
2160
+ const getFheKey = (chainId, securityZone = 0) => {
2161
+ if (chainId == null || securityZone == null)
2162
+ return void 0;
2163
+ const stored = keysStore.getState().fhe[chainId]?.[securityZone];
2164
+ return stored;
2165
+ };
2166
+ const getCrs = (chainId) => {
2167
+ if (chainId == null)
2168
+ return void 0;
2169
+ const stored = keysStore.getState().crs[chainId];
2170
+ return stored;
2171
+ };
2172
+ const setFheKey = (chainId, securityZone, key) => {
2173
+ keysStore.setState(
2174
+ immer.produce((state) => {
2175
+ if (state.fhe[chainId] == null)
2176
+ state.fhe[chainId] = {};
2177
+ state.fhe[chainId][securityZone] = key;
2178
+ })
2179
+ );
2180
+ };
2181
+ const setCrs = (chainId, crs) => {
2182
+ keysStore.setState(
2183
+ immer.produce((state) => {
2184
+ state.crs[chainId] = crs;
2185
+ })
2186
+ );
2187
+ };
2188
+ const clearKeysStorage = async () => {
2189
+ if (storage) {
2190
+ await storage.removeItem("cofhesdk-keys");
2191
+ }
2192
+ };
2193
+ const rehydrateKeysStore = async () => {
2194
+ if ("persist" in keysStore) {
2195
+ if (keysStore.persist.hasHydrated())
2196
+ return;
2197
+ await keysStore.persist.rehydrate();
2198
+ }
2199
+ };
2200
+ return {
2201
+ store: keysStore,
2202
+ getFheKey,
2203
+ getCrs,
2204
+ setFheKey,
2205
+ setCrs,
2206
+ clearKeysStorage,
2207
+ rehydrateKeysStore
2208
+ };
2209
+ }
2210
+
2211
+ // core/encrypt/encryptInputsBuilder.ts
2212
+ var EncryptInputsBuilder = class extends BaseBuilder {
2213
+ securityZone;
2214
+ stepCallback;
2215
+ inputItems;
2216
+ zkvWalletClient;
2217
+ tfhePublicKeyDeserializer;
2218
+ compactPkeCrsDeserializer;
2219
+ zkBuilderAndCrsGenerator;
2220
+ initTfhe;
2221
+ keysStorage;
2222
+ stepTimestamps = {
2223
+ ["initTfhe" /* InitTfhe */]: 0,
2224
+ ["fetchKeys" /* FetchKeys */]: 0,
2225
+ ["pack" /* Pack */]: 0,
2226
+ ["prove" /* Prove */]: 0,
2227
+ ["verify" /* Verify */]: 0
2228
+ };
2229
+ constructor(params) {
2230
+ super({
2231
+ config: params.config,
2232
+ publicClient: params.publicClient,
2233
+ walletClient: params.walletClient,
2234
+ chainId: params.chainId,
2235
+ account: params.account,
2236
+ requireConnected: params.requireConnected
2237
+ });
2238
+ this.inputItems = params.inputs;
2239
+ this.securityZone = params.securityZone ?? 0;
2240
+ this.zkvWalletClient = params.zkvWalletClient;
2241
+ this.tfhePublicKeyDeserializer = params.tfhePublicKeyDeserializer;
2242
+ this.compactPkeCrsDeserializer = params.compactPkeCrsDeserializer;
2243
+ this.zkBuilderAndCrsGenerator = params.zkBuilderAndCrsGenerator;
2244
+ this.initTfhe = params.initTfhe;
2245
+ this.keysStorage = params.keysStorage;
2246
+ }
2247
+ /**
2248
+ * @param account - Account that will create the tx using the encrypted inputs.
2249
+ *
2250
+ * If not provided, the account will be fetched from the connected walletClient.
2251
+ *
2252
+ * Example:
2253
+ * ```typescript
2254
+ * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
2255
+ * .setAccount("0x123")
2256
+ * .encrypt();
2257
+ * ```
2258
+ *
2259
+ * @returns The chainable EncryptInputsBuilder instance.
2260
+ */
2261
+ setAccount(account) {
2262
+ this.account = account;
2263
+ return this;
2264
+ }
2265
+ getAccount() {
2266
+ return this.account;
2267
+ }
2268
+ /**
2269
+ * @param chainId - Chain that will consume the encrypted inputs.
2270
+ *
2271
+ * If not provided, the chainId will be fetched from the connected publicClient.
2272
+ *
2273
+ * Example:
2274
+ * ```typescript
2275
+ * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
2276
+ * .setChainId(11155111)
2277
+ * .encrypt();
2278
+ * ```
2279
+ *
2280
+ * @returns The chainable EncryptInputsBuilder instance.
2281
+ */
2282
+ setChainId(chainId) {
2283
+ this.chainId = chainId;
2284
+ return this;
2285
+ }
2286
+ getChainId() {
2287
+ return this.chainId;
2288
+ }
2289
+ /**
2290
+ * @param securityZone - Security zone to encrypt the inputs for.
2291
+ *
2292
+ * If not provided, the default securityZone 0 will be used.
2293
+ *
2294
+ * Example:
2295
+ * ```typescript
2296
+ * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
2297
+ * .setSecurityZone(1)
2298
+ * .encrypt();
2299
+ * ```
2300
+ *
2301
+ * @returns The chainable EncryptInputsBuilder instance.
2302
+ */
2303
+ setSecurityZone(securityZone) {
2304
+ this.securityZone = securityZone;
2305
+ return this;
2306
+ }
2307
+ getSecurityZone() {
2308
+ return this.securityZone;
2309
+ }
2310
+ /**
2311
+ * @param callback - Function to be called with the encryption step.
2312
+ *
2313
+ * Useful for debugging and tracking the progress of the encryption process.
2314
+ * Useful for a UI element that shows the progress of the encryption process.
2315
+ *
2316
+ * Example:
2317
+ * ```typescript
2318
+ * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
2319
+ * .setStepCallback((step: EncryptStep) => console.log(step))
2320
+ * .encrypt();
2321
+ * ```
2322
+ *
2323
+ * @returns The EncryptInputsBuilder instance.
2324
+ */
2325
+ setStepCallback(callback) {
2326
+ this.stepCallback = callback;
2327
+ return this;
2328
+ }
2329
+ getStepCallback() {
2330
+ return this.stepCallback;
2331
+ }
2332
+ /**
2333
+ * Fires the step callback if set
2334
+ */
2335
+ fireStepStart(step, context = {}) {
2336
+ if (!this.stepCallback)
2337
+ return;
2338
+ this.stepTimestamps[step] = Date.now();
2339
+ this.stepCallback(step, { ...context, isStart: true, isEnd: false, duration: 0 });
2340
+ }
2341
+ fireStepEnd(step, context = {}) {
2342
+ if (!this.stepCallback)
2343
+ return;
2344
+ const duration = Date.now() - this.stepTimestamps[step];
2345
+ this.stepCallback(step, { ...context, isStart: false, isEnd: true, duration });
2346
+ }
2347
+ /**
2348
+ * tfhePublicKeyDeserializer is a platform-specific dependency injected into core/createCofhesdkClientBase by web/createCofhesdkClient and node/createCofhesdkClient
2349
+ * web/ uses zama "tfhe"
2350
+ * node/ uses zama "node-tfhe"
2351
+ * Users should not set this manually.
2352
+ */
2353
+ getTfhePublicKeyDeserializerOrThrow() {
2354
+ if (this.tfhePublicKeyDeserializer)
2355
+ return this.tfhePublicKeyDeserializer;
2356
+ throw new CofhesdkError({
2357
+ code: "MISSING_TFHE_PUBLIC_KEY_DESERIALIZER" /* MissingTfhePublicKeyDeserializer */,
2358
+ message: "EncryptInputsBuilder tfhePublicKeyDeserializer is undefined",
2359
+ hint: "Ensure client has been created with a tfhePublicKeyDeserializer.",
2360
+ context: {
2361
+ tfhePublicKeyDeserializer: this.tfhePublicKeyDeserializer
2362
+ }
2363
+ });
2364
+ }
2365
+ /**
2366
+ * compactPkeCrsDeserializer is a platform-specific dependency injected into core/createCofhesdkClientBase by web/createCofhesdkClient and node/createCofhesdkClient
2367
+ * web/ uses zama "tfhe"
2368
+ * node/ uses zama "node-tfhe"
2369
+ * Users should not set this manually.
2370
+ */
2371
+ getCompactPkeCrsDeserializerOrThrow() {
2372
+ if (this.compactPkeCrsDeserializer)
2373
+ return this.compactPkeCrsDeserializer;
2374
+ throw new CofhesdkError({
2375
+ code: "MISSING_COMPACT_PKE_CRS_DESERIALIZER" /* MissingCompactPkeCrsDeserializer */,
2376
+ message: "EncryptInputsBuilder compactPkeCrsDeserializer is undefined",
2377
+ hint: "Ensure client has been created with a compactPkeCrsDeserializer.",
2378
+ context: {
2379
+ compactPkeCrsDeserializer: this.compactPkeCrsDeserializer
2380
+ }
2381
+ });
2382
+ }
2383
+ /**
2384
+ * zkVerifierUrl is included in the chains exported from cofhesdk/chains for use in CofhesdkConfig.supportedChains
2385
+ * Users should generally not set this manually.
2386
+ */
2387
+ async getZkVerifierUrl() {
2388
+ const config = this.getConfigOrThrow();
2389
+ const chainId = await this.getChainIdOrThrow();
2390
+ return getZkVerifierUrlOrThrow(config, chainId);
2391
+ }
2392
+ /**
2393
+ * initTfhe is a platform-specific dependency injected into core/createCofhesdkClientBase by web/createCofhesdkClient and node/createCofhesdkClient
2394
+ * web/ uses zama "tfhe"
2395
+ * node/ uses zama "node-tfhe"
2396
+ * Users should not set this manually.
2397
+ */
2398
+ async initTfheOrThrow() {
2399
+ if (!this.initTfhe)
2400
+ return false;
2401
+ try {
2402
+ return await this.initTfhe();
2403
+ } catch (error) {
2404
+ throw CofhesdkError.fromError(error, {
2405
+ code: "INIT_TFHE_FAILED" /* InitTfheFailed */,
2406
+ message: `Failed to initialize TFHE`,
2407
+ context: {
2408
+ initTfhe: this.initTfhe
2409
+ }
2410
+ });
2411
+ }
2412
+ }
2413
+ /**
2414
+ * Fetches the FHE key and CRS from the CoFHE API
2415
+ * If the key/crs already exists in the store it is returned, else it is fetched, stored, and returned
2416
+ */
2417
+ async fetchFheKeyAndCrs() {
2418
+ const config = this.getConfigOrThrow();
2419
+ const chainId = await this.getChainIdOrThrow();
2420
+ const compactPkeCrsDeserializer2 = this.getCompactPkeCrsDeserializerOrThrow();
2421
+ const tfhePublicKeyDeserializer2 = this.getTfhePublicKeyDeserializerOrThrow();
2422
+ const securityZone = this.getSecurityZone();
2423
+ try {
2424
+ await this.keysStorage?.rehydrateKeysStore();
2425
+ } catch (error) {
2426
+ throw CofhesdkError.fromError(error, {
2427
+ code: "REHYDRATE_KEYS_STORE_FAILED" /* RehydrateKeysStoreFailed */,
2428
+ message: `Failed to rehydrate keys store`,
2429
+ context: {
2430
+ keysStorage: this.keysStorage
2431
+ }
2432
+ });
2433
+ }
2434
+ let fheKey;
2435
+ let fheKeyFetchedFromCoFHE = false;
2436
+ let crs;
2437
+ let crsFetchedFromCoFHE = false;
2438
+ try {
2439
+ [[fheKey, fheKeyFetchedFromCoFHE], [crs, crsFetchedFromCoFHE]] = await fetchKeys(
2440
+ config,
2441
+ chainId,
2442
+ securityZone,
2443
+ tfhePublicKeyDeserializer2,
2444
+ compactPkeCrsDeserializer2,
2445
+ this.keysStorage
2446
+ );
2447
+ } catch (error) {
2448
+ throw CofhesdkError.fromError(error, {
2449
+ code: "FETCH_KEYS_FAILED" /* FetchKeysFailed */,
2450
+ message: `Failed to fetch FHE key and CRS`,
2451
+ context: {
2452
+ config,
2453
+ chainId,
2454
+ securityZone,
2455
+ compactPkeCrsDeserializer: compactPkeCrsDeserializer2,
2456
+ tfhePublicKeyDeserializer: tfhePublicKeyDeserializer2
2457
+ }
2458
+ });
2459
+ }
2460
+ if (!fheKey) {
2461
+ throw new CofhesdkError({
2462
+ code: "MISSING_FHE_KEY" /* MissingFheKey */,
2463
+ message: `FHE key not found`,
2464
+ context: {
2465
+ chainId,
2466
+ securityZone
2467
+ }
2468
+ });
2469
+ }
2470
+ if (!crs) {
2471
+ throw new CofhesdkError({
2472
+ code: "MISSING_CRS" /* MissingCrs */,
2473
+ message: `CRS not found for chainId <${this.chainId}>`,
2474
+ context: {
2475
+ chainId
2476
+ }
2477
+ });
2478
+ }
2479
+ return { fheKey, fheKeyFetchedFromCoFHE, crs, crsFetchedFromCoFHE };
2480
+ }
2481
+ /**
2482
+ * zkBuilderAndCrsGenerator is a platform-specific dependency injected into core/createCofhesdkClientBase by web/createCofhesdkClient and node/createCofhesdkClient
2483
+ * web/ uses zama "tfhe"
2484
+ * node/ uses zama "node-tfhe"
2485
+ * Users should not set this manually.
2486
+ *
2487
+ * Generates the zkBuilder and zkCrs from the fheKey and crs
2488
+ */
2489
+ generateZkBuilderAndCrs(fheKey, crs) {
2490
+ const zkBuilderAndCrsGenerator2 = this.zkBuilderAndCrsGenerator;
2491
+ if (!zkBuilderAndCrsGenerator2) {
2492
+ throw new CofhesdkError({
2493
+ code: "MISSING_ZK_BUILDER_AND_CRS_GENERATOR" /* MissingZkBuilderAndCrsGenerator */,
2494
+ message: `zkBuilderAndCrsGenerator is undefined`,
2495
+ hint: "Ensure client has been created with a zkBuilderAndCrsGenerator.",
2496
+ context: {
2497
+ zkBuilderAndCrsGenerator: this.zkBuilderAndCrsGenerator
2498
+ }
2499
+ });
2500
+ }
2501
+ return zkBuilderAndCrsGenerator2(fheKey, crs);
2502
+ }
2503
+ /**
2504
+ * @dev Encrypt against the cofheMocks instead of CoFHE
2505
+ *
2506
+ * In the cofheMocks, the MockZkVerifier contract is deployed on hardhat to a fixed address, this contract handles mocking the zk verifying.
2507
+ * cofheMocksInsertPackedHashes - stores the ctHashes and their plaintext values for on-chain mocking of FHE operations.
2508
+ * cofheMocksZkCreateProofSignatures - creates signatures to be included in the encrypted inputs. The signers address is known and verified in the mock contracts.
2509
+ */
2510
+ async mocksEncrypt(account) {
2511
+ this.fireStepStart("initTfhe" /* InitTfhe */);
2512
+ await sleep(100);
2513
+ this.fireStepEnd("initTfhe" /* InitTfhe */, { tfheInitializationExecuted: false });
2514
+ this.fireStepStart("fetchKeys" /* FetchKeys */);
2515
+ await sleep(100);
2516
+ this.fireStepEnd("fetchKeys" /* FetchKeys */, { fheKeyFetchedFromCoFHE: false, crsFetchedFromCoFHE: false });
2517
+ this.fireStepStart("pack" /* Pack */);
2518
+ await cofheMocksCheckEncryptableBits(this.inputItems);
2519
+ await sleep(100);
2520
+ this.fireStepEnd("pack" /* Pack */);
2521
+ this.fireStepStart("prove" /* Prove */);
2522
+ await sleep(500);
2523
+ this.fireStepEnd("prove" /* Prove */);
2524
+ this.fireStepStart("verify" /* Verify */);
2525
+ await sleep(500);
2526
+ const signedResults = await cofheMocksZkVerifySign(
2527
+ this.inputItems,
2528
+ account,
2529
+ this.securityZone,
2530
+ this.getPublicClientOrThrow(),
2531
+ this.getWalletClientOrThrow(),
2532
+ this.zkvWalletClient
2533
+ );
2534
+ const encryptedInputs = signedResults.map(({ ct_hash, signature }, index) => ({
2535
+ ctHash: BigInt(ct_hash),
2536
+ securityZone: this.securityZone,
2537
+ utype: this.inputItems[index].utype,
2538
+ signature
2539
+ }));
2540
+ this.fireStepEnd("verify" /* Verify */);
2541
+ return encryptedInputs;
2542
+ }
2543
+ /**
2544
+ * In the production context, perform a true encryption with the CoFHE coprocessor.
2545
+ */
2546
+ async productionEncrypt(account, chainId) {
2547
+ this.fireStepStart("initTfhe" /* InitTfhe */);
2548
+ const tfheInitializationExecuted = await this.initTfheOrThrow();
2549
+ this.fireStepEnd("initTfhe" /* InitTfhe */, { tfheInitializationExecuted });
2550
+ this.fireStepStart("fetchKeys" /* FetchKeys */);
2551
+ const { fheKey, fheKeyFetchedFromCoFHE, crs, crsFetchedFromCoFHE } = await this.fetchFheKeyAndCrs();
2552
+ let { zkBuilder, zkCrs } = this.generateZkBuilderAndCrs(fheKey, crs);
2553
+ this.fireStepEnd("fetchKeys" /* FetchKeys */, { fheKeyFetchedFromCoFHE, crsFetchedFromCoFHE });
2554
+ this.fireStepStart("pack" /* Pack */);
2555
+ zkBuilder = zkPack(this.inputItems, zkBuilder);
2556
+ this.fireStepEnd("pack" /* Pack */);
2557
+ this.fireStepStart("prove" /* Prove */);
2558
+ const proof = await zkProve(zkBuilder, zkCrs, account, this.securityZone, chainId);
2559
+ this.fireStepEnd("prove" /* Prove */);
2560
+ this.fireStepStart("verify" /* Verify */);
2561
+ const zkVerifierUrl = await this.getZkVerifierUrl();
2562
+ const verifyResults = await zkVerify(zkVerifierUrl, proof, account, this.securityZone, chainId);
2563
+ const encryptedInputs = verifyResults.map(
2564
+ ({ ct_hash, signature }, index) => ({
2565
+ ctHash: BigInt(ct_hash),
2566
+ securityZone: this.securityZone,
2567
+ utype: this.inputItems[index].utype,
2568
+ signature
2569
+ })
2570
+ );
2571
+ this.fireStepEnd("verify" /* Verify */);
2572
+ return encryptedInputs;
2573
+ }
2574
+ /**
2575
+ * Final step of the encryption process. MUST BE CALLED LAST IN THE CHAIN.
2576
+ *
2577
+ * This will:
2578
+ * - Pack the encryptable items into a zk proof
2579
+ * - Prove the zk proof
2580
+ * - Verify the zk proof with CoFHE
2581
+ * - Package and return the encrypted inputs
2582
+ *
2583
+ * Example:
2584
+ * ```typescript
2585
+ * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
2586
+ * .setAccount('0x123...890') // optional
2587
+ * .setChainId(11155111) // optional
2588
+ * .encrypt(); // execute
2589
+ * ```
2590
+ *
2591
+ * @returns The encrypted inputs.
2592
+ */
2593
+ async encrypt() {
2594
+ return resultWrapper(async () => {
2595
+ await this.requireConnectedOrThrow();
2596
+ const account = await this.getAccountOrThrow();
2597
+ const chainId = await this.getChainIdOrThrow();
2598
+ if (chainId === chains.hardhat.id) {
2599
+ return await this.mocksEncrypt(account);
2600
+ }
2601
+ return await this.productionEncrypt(account, chainId);
2602
+ });
2603
+ }
2604
+ };
2605
+
2606
+ // core/types.ts
2607
+ var FheUintUTypes = [
2608
+ 2 /* Uint8 */,
2609
+ 3 /* Uint16 */,
2610
+ 4 /* Uint32 */,
2611
+ 5 /* Uint64 */,
2612
+ 6 /* Uint128 */
2613
+ // [U256-DISABLED]
2614
+ // FheTypes.Uint256,
2615
+ ];
2616
+
2617
+ // core/config.ts
2618
+ var CofhesdkConfigSchema = zod.z.object({
2619
+ /** List of supported chain configurations */
2620
+ supportedChains: zod.z.array(zod.z.custom()),
2621
+ /** Strategy for fetching FHE keys */
2622
+ fheKeysPrefetching: zod.z.enum(["CONNECTED_CHAIN", "SUPPORTED_CHAINS", "OFF"]).optional().default("OFF"),
2623
+ /** How permits are generated */
2624
+ permitGeneration: zod.z.enum(["ON_CONNECT", "ON_DECRYPT_HANDLES", "MANUAL"]).optional().default("ON_CONNECT"),
2625
+ /** Default permit expiration in seconds, default is 30 days */
2626
+ defaultPermitExpiration: zod.z.number().optional().default(60 * 60 * 24 * 30),
2627
+ /** Storage method for fhe keys (defaults to indexedDB on web, filesystem on node) */
2628
+ fheKeyStorage: zod.z.object({
2629
+ getItem: zod.z.function().args(zod.z.string()).returns(zod.z.promise(zod.z.any())),
2630
+ setItem: zod.z.function().args(zod.z.string(), zod.z.any()).returns(zod.z.promise(zod.z.void())),
2631
+ removeItem: zod.z.function().args(zod.z.string()).returns(zod.z.promise(zod.z.void()))
2632
+ }).or(zod.z.null()).default(null),
2633
+ /** Mocks configs */
2634
+ mocks: zod.z.object({
2635
+ sealOutputDelay: zod.z.number().optional().default(0)
2636
+ }).optional().default({ sealOutputDelay: 0 }),
2637
+ /** Internal configuration */
2638
+ _internal: zod.z.object({
2639
+ zkvWalletClient: zod.z.any().optional()
2640
+ }).optional()
2641
+ });
2642
+ function createCofhesdkConfigBase(config) {
2643
+ const result = CofhesdkConfigSchema.safeParse(config);
2644
+ if (!result.success) {
2645
+ throw new Error(`Invalid cofhesdk configuration: ${result.error.message}`);
2646
+ }
2647
+ return result.data;
2648
+ }
2649
+ function getSupportedChainOrThrow(config, chainId) {
2650
+ const supportedChain = config.supportedChains.find((chain) => chain.id === chainId);
2651
+ if (!supportedChain) {
2652
+ throw new CofhesdkError({
2653
+ code: "UNSUPPORTED_CHAIN" /* UnsupportedChain */,
2654
+ message: `Config does not support chain <${chainId}>`,
2655
+ hint: "Ensure config passed to client has been created with this chain in the config.supportedChains array.",
2656
+ context: {
2657
+ chainId,
2658
+ supportedChainIds: config.supportedChains.map((c) => c.id)
2659
+ }
2660
+ });
2661
+ }
2662
+ return supportedChain;
2663
+ }
2664
+ function getCoFheUrlOrThrow(config, chainId) {
2665
+ const supportedChain = getSupportedChainOrThrow(config, chainId);
2666
+ const url = supportedChain.coFheUrl;
2667
+ if (!url) {
2668
+ throw new CofhesdkError({
2669
+ code: "MISSING_CONFIG" /* MissingConfig */,
2670
+ message: `CoFHE URL is not configured for chain <${chainId}>`,
2671
+ hint: "Ensure this chain config includes a coFheUrl property.",
2672
+ context: { chainId }
2673
+ });
2674
+ }
2675
+ return url;
2676
+ }
2677
+ function getZkVerifierUrlOrThrow(config, chainId) {
2678
+ const supportedChain = getSupportedChainOrThrow(config, chainId);
2679
+ const url = supportedChain.verifierUrl;
2680
+ if (!url) {
2681
+ throw new CofhesdkError({
2682
+ code: "ZK_VERIFIER_URL_UNINITIALIZED" /* ZkVerifierUrlUninitialized */,
2683
+ message: `ZK verifier URL is not configured for chain <${chainId}>`,
2684
+ hint: "Ensure this chain config includes a verifierUrl property.",
2685
+ context: { chainId }
2686
+ });
2687
+ }
2688
+ return url;
2689
+ }
2690
+ function getThresholdNetworkUrlOrThrow(config, chainId) {
2691
+ const supportedChain = getSupportedChainOrThrow(config, chainId);
2692
+ const url = supportedChain.thresholdNetworkUrl;
2693
+ if (!url) {
2694
+ throw new CofhesdkError({
2695
+ code: "THRESHOLD_NETWORK_URL_UNINITIALIZED" /* ThresholdNetworkUrlUninitialized */,
2696
+ message: `Threshold network URL is not configured for chain <${chainId}>`,
2697
+ hint: "Ensure this chain config includes a thresholdNetworkUrl property.",
2698
+ context: { chainId }
2699
+ });
2700
+ }
2701
+ return url;
2702
+ }
2703
+
2704
+ // core/fetchKeys.ts
2705
+ var PUBLIC_KEY_LENGTH_MIN = 15e3;
2706
+ var checkKeyValidity = (key, serializer) => {
2707
+ if (key == null || key.length === 0)
2708
+ return [false, `Key is null or empty <${key}>`];
2709
+ try {
2710
+ serializer(key);
2711
+ return [true, `Key is valid`];
2712
+ } catch (err) {
2713
+ return [false, `Serialization failed <${err}> key length <${key.length}>`];
2714
+ }
2715
+ };
2716
+ var fetchFhePublicKey = async (coFheUrl, chainId, securityZone, tfhePublicKeyDeserializer2, keysStorage) => {
2717
+ const storedKey = keysStorage?.getFheKey(chainId, securityZone);
2718
+ const [storedKeyValid] = checkKeyValidity(storedKey, tfhePublicKeyDeserializer2);
2719
+ if (storedKeyValid)
2720
+ return [storedKey, false];
2721
+ let pk_data = void 0;
2722
+ try {
2723
+ const pk_res = await fetch(`${coFheUrl}/GetNetworkPublicKey`, {
2724
+ method: "POST",
2725
+ headers: {
2726
+ "Content-Type": "application/json"
2727
+ },
2728
+ body: JSON.stringify({ securityZone })
2729
+ });
2730
+ const json = await pk_res.json();
2731
+ pk_data = json.publicKey;
2732
+ } catch (err) {
2733
+ throw new Error(`Error fetching FHE publicKey; fetching from CoFHE failed with error ${err}`);
2734
+ }
2735
+ if (pk_data == null || typeof pk_data !== "string") {
2736
+ throw new Error(`Error fetching FHE publicKey; fetched result invalid: missing or not a string`);
2737
+ }
2738
+ if (pk_data === "0x") {
2739
+ throw new Error("Error fetching FHE publicKey; provided chain is not FHE enabled / not found");
2740
+ }
2741
+ if (pk_data.length < PUBLIC_KEY_LENGTH_MIN) {
2742
+ throw new Error(
2743
+ `Error fetching FHE publicKey; got shorter than expected key length: ${pk_data.length}. Expected length >= ${PUBLIC_KEY_LENGTH_MIN}`
2744
+ );
2745
+ }
2746
+ try {
2747
+ tfhePublicKeyDeserializer2(pk_data);
2748
+ } catch (err) {
2749
+ throw new Error(`Error serializing FHE publicKey; ${err}`);
2750
+ }
2751
+ keysStorage?.setFheKey(chainId, securityZone, pk_data);
2752
+ return [pk_data, true];
2753
+ };
2754
+ var fetchCrs = async (coFheUrl, chainId, securityZone, compactPkeCrsDeserializer2, keysStorage) => {
2755
+ const storedKey = keysStorage?.getCrs(chainId);
2756
+ const [storedKeyValid] = checkKeyValidity(storedKey, compactPkeCrsDeserializer2);
2757
+ if (storedKeyValid)
2758
+ return [storedKey, false];
2759
+ let crs_data = void 0;
2760
+ try {
2761
+ const crs_res = await fetch(`${coFheUrl}/GetCrs`, {
2762
+ method: "POST",
2763
+ headers: {
2764
+ "Content-Type": "application/json"
2765
+ },
2766
+ body: JSON.stringify({ securityZone })
2767
+ });
2768
+ const json = await crs_res.json();
2769
+ crs_data = json.crs;
2770
+ } catch (err) {
2771
+ throw new Error(`Error fetching CRS; fetching failed with error ${err}`);
2772
+ }
2773
+ if (crs_data == null || typeof crs_data !== "string") {
2774
+ throw new Error(`Error fetching CRS; invalid: missing or not a string`);
2775
+ }
2776
+ try {
2777
+ compactPkeCrsDeserializer2(crs_data);
2778
+ } catch (err) {
2779
+ console.error(`Error serializing CRS ${err}`);
2780
+ throw new Error(`Error serializing CRS; ${err}`);
2781
+ }
2782
+ keysStorage?.setCrs(chainId, crs_data);
2783
+ return [crs_data, true];
2784
+ };
2785
+ var fetchKeys = async (config, chainId, securityZone = 0, tfhePublicKeyDeserializer2, compactPkeCrsDeserializer2, keysStorage) => {
2786
+ const coFheUrl = getCoFheUrlOrThrow(config, chainId);
2787
+ return await Promise.all([
2788
+ fetchFhePublicKey(coFheUrl, chainId, securityZone, tfhePublicKeyDeserializer2, keysStorage),
2789
+ fetchCrs(coFheUrl, chainId, securityZone, compactPkeCrsDeserializer2, keysStorage)
2790
+ ]);
2791
+ };
2792
+ var fetchMultichainKeys = async (config, securityZone = 0, tfhePublicKeyDeserializer2, compactPkeCrsDeserializer2, keysStorage) => {
2793
+ await Promise.all(
2794
+ config.supportedChains.filter((chain) => chain.id !== hardhat.id).map(
2795
+ (chain) => fetchKeys(config, chain.id, securityZone, tfhePublicKeyDeserializer2, compactPkeCrsDeserializer2, keysStorage)
2796
+ )
2797
+ );
2798
+ };
2799
+
2800
+ // core/client.ts
2801
+ function createCofhesdkClientBase(opts) {
2802
+ const keysStorage = createKeysStore(opts.config.fheKeyStorage);
2803
+ let _publicClient = void 0;
2804
+ let _walletClient = void 0;
2805
+ const connectStore = vanilla.createStore(() => ({
2806
+ connected: false,
2807
+ connecting: false,
2808
+ connectError: void 0,
2809
+ chainId: void 0,
2810
+ account: void 0
2811
+ }));
2812
+ const updateConnectState = (partial) => {
2813
+ connectStore.setState((state) => ({ ...state, ...partial }));
2814
+ };
2815
+ let _connectPromise = void 0;
2816
+ const _requireConnected = () => {
2817
+ const state = connectStore.getState();
2818
+ const notConnected = !state.connected || !_publicClient || !_walletClient || !state.account || !state.chainId;
2819
+ if (notConnected) {
2820
+ throw new CofhesdkError({
2821
+ code: "NOT_CONNECTED" /* NotConnected */,
2822
+ message: "Client must be connected, account and chainId must be initialized",
2823
+ hint: "Ensure client.connect() has been called and awaited.",
2824
+ context: {
2825
+ connected: state.connected,
2826
+ account: state.account,
2827
+ chainId: state.chainId,
2828
+ publicClient: _publicClient,
2829
+ walletClient: _walletClient
2830
+ }
2831
+ });
2832
+ }
2833
+ };
2834
+ const keyFetchResult = resultWrapper(async () => {
2835
+ if (opts.config.fheKeysPrefetching === "SUPPORTED_CHAINS") {
2836
+ await fetchMultichainKeys(
2837
+ opts.config,
2838
+ 0,
2839
+ opts.tfhePublicKeyDeserializer,
2840
+ opts.compactPkeCrsDeserializer,
2841
+ keysStorage
2842
+ );
2843
+ return true;
2844
+ }
2845
+ return false;
2846
+ });
2847
+ async function connect(publicClient, walletClient) {
2848
+ const state = connectStore.getState();
2849
+ if (state.connected && _publicClient === publicClient && _walletClient === walletClient) {
2850
+ return Promise.resolve(ResultOk(true));
2851
+ }
2852
+ if (_connectPromise && _publicClient === publicClient && _walletClient === walletClient) {
2853
+ return _connectPromise;
2854
+ }
2855
+ updateConnectState({ connecting: true, connectError: null, connected: false });
2856
+ _connectPromise = resultWrapper(
2857
+ // try
2858
+ async () => {
2859
+ _publicClient = publicClient;
2860
+ _walletClient = walletClient;
2861
+ const chainId = await getPublicClientChainID(publicClient);
2862
+ const account = await getWalletClientAccount(walletClient);
2863
+ updateConnectState({ connecting: false, connected: true, chainId, account });
2864
+ return true;
2865
+ },
2866
+ // catch
2867
+ (e) => {
2868
+ updateConnectState({ connecting: false, connected: false, connectError: e });
2869
+ return false;
2870
+ },
2871
+ // finally
2872
+ () => {
2873
+ _connectPromise = void 0;
2874
+ }
2875
+ );
2876
+ return _connectPromise;
2877
+ }
2878
+ function encryptInputs(inputs) {
2879
+ const state = connectStore.getState();
2880
+ return new EncryptInputsBuilder({
2881
+ inputs,
2882
+ account: state.account ?? void 0,
2883
+ chainId: state.chainId ?? void 0,
2884
+ config: opts.config,
2885
+ publicClient: _publicClient ?? void 0,
2886
+ walletClient: _walletClient ?? void 0,
2887
+ zkvWalletClient: opts.config._internal?.zkvWalletClient,
2888
+ tfhePublicKeyDeserializer: opts.tfhePublicKeyDeserializer,
2889
+ compactPkeCrsDeserializer: opts.compactPkeCrsDeserializer,
2890
+ zkBuilderAndCrsGenerator: opts.zkBuilderAndCrsGenerator,
2891
+ initTfhe: opts.initTfhe,
2892
+ keysStorage,
2893
+ requireConnected: _requireConnected
2894
+ });
2895
+ }
2896
+ function decryptHandle(ctHash, utype) {
2897
+ const state = connectStore.getState();
2898
+ return new DecryptHandlesBuilder({
2899
+ ctHash,
2900
+ utype,
2901
+ chainId: state.chainId ?? void 0,
2902
+ account: state.account ?? void 0,
2903
+ config: opts.config,
2904
+ publicClient: _publicClient ?? void 0,
2905
+ walletClient: _walletClient ?? void 0,
2906
+ requireConnected: _requireConnected
2907
+ });
2908
+ }
2909
+ const _getChainIdAndAccount = (chainId, account) => {
2910
+ const state = connectStore.getState();
2911
+ const _chainId = chainId ?? state.chainId;
2912
+ const _account = account ?? state.account;
2913
+ if (_chainId == null || _account == null) {
2914
+ throw new CofhesdkError({
2915
+ code: "NOT_CONNECTED" /* NotConnected */,
2916
+ message: "ChainId or account not available.",
2917
+ hint: "Ensure client.connect() has been called, or provide chainId and account explicitly.",
2918
+ context: {
2919
+ chainId: _chainId,
2920
+ account: _account
2921
+ }
2922
+ });
2923
+ }
2924
+ return { chainId: _chainId, account: _account };
2925
+ };
2926
+ const clientPermits = {
2927
+ // Pass through store access
2928
+ getSnapshot: permits.getSnapshot,
2929
+ subscribe: permits.subscribe,
2930
+ // Creation methods (require connection)
2931
+ createSelf: async (options) => resultWrapper(async () => {
2932
+ _requireConnected();
2933
+ return permits.createSelf(options, _publicClient, _walletClient);
2934
+ }),
2935
+ createSharing: async (options) => resultWrapper(async () => {
2936
+ _requireConnected();
2937
+ return permits.createSharing(options, _publicClient, _walletClient);
2938
+ }),
2939
+ importShared: async (options) => resultWrapper(async () => {
2940
+ _requireConnected();
2941
+ return permits.importShared(options, _publicClient, _walletClient);
2942
+ }),
2943
+ // Retrieval methods (auto-fill chainId/account)
2944
+ getPermit: async (hash, chainId, account) => resultWrapper(async () => {
2945
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2946
+ return permits.getPermit(_chainId, _account, hash);
2947
+ }),
2948
+ getPermits: async (chainId, account) => resultWrapper(async () => {
2949
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2950
+ return permits.getPermits(_chainId, _account);
2951
+ }),
2952
+ getActivePermit: async (chainId, account) => resultWrapper(async () => {
2953
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2954
+ return permits.getActivePermit(_chainId, _account);
2955
+ }),
2956
+ getActivePermitHash: async (chainId, account) => resultWrapper(async () => {
2957
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2958
+ return permits.getActivePermitHash(_chainId, _account);
2959
+ }),
2960
+ // Mutation methods (auto-fill chainId/account)
2961
+ selectActivePermit: async (hash, chainId, account) => resultWrapper(async () => {
2962
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2963
+ return permits.selectActivePermit(_chainId, _account, hash);
2964
+ }),
2965
+ removePermit: async (hash, chainId, account) => resultWrapper(async () => {
2966
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2967
+ return permits.removePermit(_chainId, _account, hash);
2968
+ }),
2969
+ removeActivePermit: async (chainId, account) => resultWrapper(async () => {
2970
+ const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
2971
+ return permits.removeActivePermit(_chainId, _account);
2972
+ }),
2973
+ // Utils (no context needed)
2974
+ getHash: permits.getHash,
2975
+ serialize: permits.serialize,
2976
+ deserialize: permits.deserialize
2977
+ };
2978
+ return {
2979
+ // Zustand reactive accessors (don't export store directly to prevent mutation)
2980
+ getSnapshot: connectStore.getState,
2981
+ subscribe: connectStore.subscribe,
2982
+ // initialization results
2983
+ initializationResults: {
2984
+ keyFetchResult
2985
+ },
2986
+ // flags (read-only: reflect snapshot)
2987
+ get connected() {
2988
+ return connectStore.getState().connected;
2989
+ },
2990
+ get connecting() {
2991
+ return connectStore.getState().connecting;
2992
+ },
2993
+ // config & platform-specific (read-only)
2994
+ config: opts.config,
2995
+ connect,
2996
+ encryptInputs,
2997
+ decryptHandle,
2998
+ permits: clientPermits
2999
+ // Add SDK-specific methods below that require connection
3000
+ // Example:
3001
+ // async encryptData(data: unknown) {
3002
+ // requireConnected();
3003
+ // // Use _publicClient and _walletClient for implementation
3004
+ // },
3005
+ };
3006
+ }
3007
+ var memoryStorage = {};
3008
+ var createNodeStorage = () => {
3009
+ return {
3010
+ getItem: async (name) => {
3011
+ try {
3012
+ const storageDir = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".cofhesdk");
3013
+ await fs.promises.mkdir(storageDir, { recursive: true });
3014
+ const filePath = path.join(storageDir, `${name}.json`);
3015
+ const data = await fs.promises.readFile(filePath, "utf8").catch(() => null);
3016
+ return data ? JSON.parse(data) : null;
3017
+ } catch (e) {
3018
+ console.warn("Node.js filesystem modules not available, falling back to memory storage" + e);
3019
+ return memoryStorage[name] || null;
3020
+ }
3021
+ },
3022
+ setItem: async (name, value) => {
3023
+ try {
3024
+ const storageDir = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".cofhesdk");
3025
+ await fs.promises.mkdir(storageDir, { recursive: true });
3026
+ const filePath = path.join(storageDir, `${name}.json`);
3027
+ await fs.promises.writeFile(filePath, JSON.stringify(value));
3028
+ } catch (e) {
3029
+ console.warn("Node.js filesystem modules not available, falling back to memory storage" + e);
3030
+ memoryStorage[name] = JSON.stringify(value);
3031
+ }
3032
+ },
3033
+ removeItem: async (name) => {
3034
+ try {
3035
+ const storageDir = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".cofhesdk");
3036
+ const filePath = path.join(storageDir, `${name}.json`);
3037
+ await fs.promises.unlink(filePath).catch(() => {
3038
+ });
3039
+ } catch (e) {
3040
+ console.warn("Node.js filesystem modules not available, falling back to memory storage" + e);
3041
+ delete memoryStorage[name];
3042
+ }
3043
+ }
3044
+ };
3045
+ };
3046
+ var tfheInitialized = false;
3047
+ async function initTfhe() {
3048
+ if (tfheInitialized)
3049
+ return false;
3050
+ await nodeTfhe.init_panic_hook();
3051
+ tfheInitialized = true;
3052
+ return true;
3053
+ }
3054
+ var fromHexString2 = (hexString) => {
3055
+ const cleanString = hexString.length % 2 === 1 ? `0${hexString}` : hexString;
3056
+ const arr = cleanString.replace(/^0x/, "").match(/.{1,2}/g);
3057
+ if (!arr)
3058
+ return new Uint8Array();
3059
+ return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
3060
+ };
3061
+ var tfhePublicKeyDeserializer = (buff) => {
3062
+ nodeTfhe.TfheCompactPublicKey.deserialize(fromHexString2(buff));
3063
+ };
3064
+ var compactPkeCrsDeserializer = (buff) => {
3065
+ nodeTfhe.CompactPkeCrs.deserialize(fromHexString2(buff));
3066
+ };
3067
+ var zkBuilderAndCrsGenerator = (fhe, crs) => {
3068
+ const fhePublicKey = nodeTfhe.TfheCompactPublicKey.deserialize(fromHexString2(fhe));
3069
+ const zkBuilder = nodeTfhe.ProvenCompactCiphertextList.builder(fhePublicKey);
3070
+ const zkCrs = nodeTfhe.CompactPkeCrs.deserialize(fromHexString2(crs));
3071
+ return { zkBuilder, zkCrs };
3072
+ };
3073
+ function createCofhesdkConfig(config) {
3074
+ return createCofhesdkConfigBase({
3075
+ ...config,
3076
+ fheKeyStorage: config.fheKeyStorage === null ? null : config.fheKeyStorage ?? createNodeStorage()
3077
+ });
3078
+ }
3079
+ function createCofhesdkClient(config) {
3080
+ return createCofhesdkClientBase({
3081
+ config,
3082
+ zkBuilderAndCrsGenerator,
3083
+ tfhePublicKeyDeserializer,
3084
+ compactPkeCrsDeserializer,
3085
+ initTfhe
3086
+ });
3087
+ }
3088
+
3089
+ exports.createCofhesdkClient = createCofhesdkClient;
3090
+ exports.createCofhesdkConfig = createCofhesdkConfig;