@cofhe/sdk 0.0.0-alpha-20260409113701

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 (132) hide show
  1. package/CHANGELOG.md +146 -0
  2. package/adapters/ethers5.test.ts +174 -0
  3. package/adapters/ethers5.ts +36 -0
  4. package/adapters/ethers6.test.ts +169 -0
  5. package/adapters/ethers6.ts +36 -0
  6. package/adapters/hardhat-node.ts +167 -0
  7. package/adapters/hardhat.hh2.test.ts +159 -0
  8. package/adapters/hardhat.ts +36 -0
  9. package/adapters/index.test.ts +20 -0
  10. package/adapters/index.ts +5 -0
  11. package/adapters/smartWallet.ts +99 -0
  12. package/adapters/test-utils.ts +53 -0
  13. package/adapters/types.ts +6 -0
  14. package/adapters/wagmi.test.ts +156 -0
  15. package/adapters/wagmi.ts +17 -0
  16. package/chains/chains/arbSepolia.ts +14 -0
  17. package/chains/chains/baseSepolia.ts +14 -0
  18. package/chains/chains/hardhat.ts +15 -0
  19. package/chains/chains/localcofhe.ts +14 -0
  20. package/chains/chains/sepolia.ts +14 -0
  21. package/chains/chains.test.ts +50 -0
  22. package/chains/defineChain.ts +18 -0
  23. package/chains/index.ts +35 -0
  24. package/chains/types.ts +32 -0
  25. package/core/baseBuilder.ts +119 -0
  26. package/core/client.test.ts +429 -0
  27. package/core/client.ts +341 -0
  28. package/core/clientTypes.ts +119 -0
  29. package/core/config.test.ts +242 -0
  30. package/core/config.ts +225 -0
  31. package/core/consts.ts +22 -0
  32. package/core/decrypt/MockThresholdNetworkAbi.ts +179 -0
  33. package/core/decrypt/cofheMocksDecryptForTx.ts +84 -0
  34. package/core/decrypt/cofheMocksDecryptForView.ts +48 -0
  35. package/core/decrypt/decryptForTxBuilder.ts +359 -0
  36. package/core/decrypt/decryptForViewBuilder.ts +332 -0
  37. package/core/decrypt/decryptUtils.ts +28 -0
  38. package/core/decrypt/pollCallbacks.test.ts +194 -0
  39. package/core/decrypt/polling.ts +14 -0
  40. package/core/decrypt/tnDecryptUtils.ts +65 -0
  41. package/core/decrypt/tnDecryptV1.ts +171 -0
  42. package/core/decrypt/tnDecryptV2.ts +365 -0
  43. package/core/decrypt/tnSealOutputV1.ts +59 -0
  44. package/core/decrypt/tnSealOutputV2.ts +324 -0
  45. package/core/decrypt/verifyDecryptResult.ts +52 -0
  46. package/core/encrypt/MockZkVerifierAbi.ts +106 -0
  47. package/core/encrypt/cofheMocksZkVerifySign.ts +281 -0
  48. package/core/encrypt/encryptInputsBuilder.test.ts +747 -0
  49. package/core/encrypt/encryptInputsBuilder.ts +583 -0
  50. package/core/encrypt/encryptUtils.ts +67 -0
  51. package/core/encrypt/zkPackProveVerify.ts +335 -0
  52. package/core/error.ts +168 -0
  53. package/core/fetchKeys.test.ts +195 -0
  54. package/core/fetchKeys.ts +144 -0
  55. package/core/index.ts +106 -0
  56. package/core/keyStore.test.ts +226 -0
  57. package/core/keyStore.ts +154 -0
  58. package/core/permits.test.ts +493 -0
  59. package/core/permits.ts +201 -0
  60. package/core/types.ts +419 -0
  61. package/core/utils.ts +130 -0
  62. package/dist/adapters.cjs +88 -0
  63. package/dist/adapters.d.cts +14576 -0
  64. package/dist/adapters.d.ts +14576 -0
  65. package/dist/adapters.js +83 -0
  66. package/dist/chains.cjs +111 -0
  67. package/dist/chains.d.cts +121 -0
  68. package/dist/chains.d.ts +121 -0
  69. package/dist/chains.js +1 -0
  70. package/dist/chunk-36FBWLUS.js +3310 -0
  71. package/dist/chunk-7HLGHV67.js +990 -0
  72. package/dist/chunk-TBLR7NNE.js +102 -0
  73. package/dist/clientTypes-AVSCBet7.d.cts +998 -0
  74. package/dist/clientTypes-flH1ju82.d.ts +998 -0
  75. package/dist/core.cjs +4362 -0
  76. package/dist/core.d.cts +138 -0
  77. package/dist/core.d.ts +138 -0
  78. package/dist/core.js +3 -0
  79. package/dist/node.cjs +4225 -0
  80. package/dist/node.d.cts +22 -0
  81. package/dist/node.d.ts +22 -0
  82. package/dist/node.js +91 -0
  83. package/dist/permit-jRirYqFt.d.cts +376 -0
  84. package/dist/permit-jRirYqFt.d.ts +376 -0
  85. package/dist/permits.cjs +1025 -0
  86. package/dist/permits.d.cts +353 -0
  87. package/dist/permits.d.ts +353 -0
  88. package/dist/permits.js +1 -0
  89. package/dist/types-YiAC4gig.d.cts +33 -0
  90. package/dist/types-YiAC4gig.d.ts +33 -0
  91. package/dist/web.cjs +4434 -0
  92. package/dist/web.d.cts +42 -0
  93. package/dist/web.d.ts +42 -0
  94. package/dist/web.js +256 -0
  95. package/dist/zkProve.worker.cjs +93 -0
  96. package/dist/zkProve.worker.d.cts +2 -0
  97. package/dist/zkProve.worker.d.ts +2 -0
  98. package/dist/zkProve.worker.js +91 -0
  99. package/node/client.test.ts +159 -0
  100. package/node/config.test.ts +68 -0
  101. package/node/encryptInputs.test.ts +155 -0
  102. package/node/index.ts +97 -0
  103. package/node/storage.ts +51 -0
  104. package/package.json +121 -0
  105. package/permits/index.ts +68 -0
  106. package/permits/localstorage.test.ts +113 -0
  107. package/permits/onchain-utils.ts +221 -0
  108. package/permits/permit.test.ts +534 -0
  109. package/permits/permit.ts +386 -0
  110. package/permits/sealing.test.ts +84 -0
  111. package/permits/sealing.ts +131 -0
  112. package/permits/signature.ts +79 -0
  113. package/permits/store.test.ts +88 -0
  114. package/permits/store.ts +156 -0
  115. package/permits/test-utils.ts +28 -0
  116. package/permits/types.ts +204 -0
  117. package/permits/utils.ts +58 -0
  118. package/permits/validation.test.ts +361 -0
  119. package/permits/validation.ts +327 -0
  120. package/web/client.web.test.ts +159 -0
  121. package/web/config.web.test.ts +69 -0
  122. package/web/const.ts +2 -0
  123. package/web/encryptInputs.web.test.ts +172 -0
  124. package/web/index.ts +166 -0
  125. package/web/storage.ts +49 -0
  126. package/web/worker.builder.web.test.ts +148 -0
  127. package/web/worker.config.web.test.ts +329 -0
  128. package/web/worker.output.web.test.ts +84 -0
  129. package/web/workerManager.test.ts +80 -0
  130. package/web/workerManager.ts +214 -0
  131. package/web/workerManager.web.test.ts +114 -0
  132. package/web/zkProve.worker.ts +133 -0
@@ -0,0 +1,324 @@
1
+ import { type Permission, type EthEncryptedData } from '@/permits';
2
+
3
+ import { CofheError, CofheErrorCode } from '../error.js';
4
+ import { type DecryptPollCallbackFunction } from '../types.js';
5
+ import { computeMinuteRampPollIntervalMs } from './polling.js';
6
+
7
+ // Polling configuration
8
+ const POLL_INTERVAL_MS = 1000; // 1 second
9
+ const POLL_MAX_INTERVAL_MS = 10_000; // 10 seconds
10
+ const POLL_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
11
+
12
+ // V2 API response types
13
+ type SealOutputSubmitResponse = {
14
+ request_id: string;
15
+ };
16
+
17
+ type SealOutputStatusResponse = {
18
+ request_id: string;
19
+ status: 'PROCESSING' | 'COMPLETED';
20
+ submitted_at: string;
21
+ completed_at?: string;
22
+ is_succeed?: boolean;
23
+ sealed?: {
24
+ data: number[];
25
+ public_key: number[];
26
+ nonce: number[];
27
+ };
28
+ signature?: string;
29
+ encryption_type?: number;
30
+ error_message?: string | null;
31
+ };
32
+
33
+ /**
34
+ * Converts a number array to Uint8Array
35
+ */
36
+ function numberArrayToUint8Array(arr: number[]): Uint8Array {
37
+ return new Uint8Array(arr);
38
+ }
39
+
40
+ /**
41
+ * Converts the sealed data from the API response to EthEncryptedData
42
+ */
43
+ function convertSealedData(sealed: SealOutputStatusResponse['sealed']): EthEncryptedData {
44
+ if (!sealed) {
45
+ throw new CofheError({
46
+ code: CofheErrorCode.SealOutputReturnedNull,
47
+ message: 'Sealed data is missing from completed response',
48
+ });
49
+ }
50
+
51
+ return {
52
+ data: numberArrayToUint8Array(sealed.data),
53
+ public_key: numberArrayToUint8Array(sealed.public_key),
54
+ nonce: numberArrayToUint8Array(sealed.nonce),
55
+ };
56
+ }
57
+
58
+ /**
59
+ * Submits a sealoutput request to the v2 API and returns the request_id
60
+ */
61
+ async function submitSealOutputRequest(
62
+ thresholdNetworkUrl: string,
63
+ ctHash: bigint | string,
64
+ chainId: number,
65
+ permission: Permission
66
+ ): Promise<string> {
67
+ const body = {
68
+ ct_tempkey: BigInt(ctHash).toString(16).padStart(64, '0'),
69
+ host_chain_id: chainId,
70
+ permit: permission,
71
+ };
72
+
73
+ let response: Response;
74
+ try {
75
+ response = await fetch(`${thresholdNetworkUrl}/v2/sealoutput`, {
76
+ method: 'POST',
77
+ headers: {
78
+ 'Content-Type': 'application/json',
79
+ },
80
+ body: JSON.stringify(body),
81
+ });
82
+ } catch (e) {
83
+ throw new CofheError({
84
+ code: CofheErrorCode.SealOutputFailed,
85
+ message: `sealOutput request failed`,
86
+ hint: 'Ensure the threshold network URL is valid and reachable.',
87
+ cause: e instanceof Error ? e : undefined,
88
+ context: {
89
+ thresholdNetworkUrl,
90
+ body,
91
+ },
92
+ });
93
+ }
94
+
95
+ // Handle non-200 status codes
96
+ if (!response.ok) {
97
+ let errorMessage = `HTTP ${response.status}`;
98
+ try {
99
+ const errorBody = await response.json();
100
+ errorMessage = errorBody.error_message || errorBody.message || errorMessage;
101
+ } catch {
102
+ // Ignore JSON parse errors, use status text
103
+ errorMessage = response.statusText || errorMessage;
104
+ }
105
+
106
+ throw new CofheError({
107
+ code: CofheErrorCode.SealOutputFailed,
108
+ message: `sealOutput request failed: ${errorMessage}`,
109
+ hint: 'Check the threshold network URL and request parameters.',
110
+ context: {
111
+ thresholdNetworkUrl,
112
+ status: response.status,
113
+ statusText: response.statusText,
114
+ body,
115
+ },
116
+ });
117
+ }
118
+
119
+ let submitResponse: SealOutputSubmitResponse;
120
+ try {
121
+ submitResponse = (await response.json()) as SealOutputSubmitResponse;
122
+ } catch (e) {
123
+ throw new CofheError({
124
+ code: CofheErrorCode.SealOutputFailed,
125
+ message: `Failed to parse sealOutput submit response`,
126
+ cause: e instanceof Error ? e : undefined,
127
+ context: {
128
+ thresholdNetworkUrl,
129
+ body,
130
+ },
131
+ });
132
+ }
133
+
134
+ if (!submitResponse.request_id) {
135
+ throw new CofheError({
136
+ code: CofheErrorCode.SealOutputFailed,
137
+ message: `sealOutput submit response missing request_id`,
138
+ context: {
139
+ thresholdNetworkUrl,
140
+ body,
141
+ submitResponse,
142
+ },
143
+ });
144
+ }
145
+
146
+ return submitResponse.request_id;
147
+ }
148
+
149
+ /**
150
+ * Polls for the sealoutput status until completed or timeout
151
+ */
152
+ async function pollSealOutputStatus(
153
+ thresholdNetworkUrl: string,
154
+ requestId: string,
155
+ onPoll?: DecryptPollCallbackFunction
156
+ ): Promise<EthEncryptedData> {
157
+ const startTime = Date.now();
158
+ let attemptIndex = 0;
159
+ let completed = false;
160
+
161
+ while (!completed) {
162
+ const elapsedMs = Date.now() - startTime;
163
+ const intervalMs = computeMinuteRampPollIntervalMs(elapsedMs, {
164
+ minIntervalMs: POLL_INTERVAL_MS,
165
+ maxIntervalMs: POLL_MAX_INTERVAL_MS,
166
+ });
167
+ onPoll?.({
168
+ operation: 'sealoutput',
169
+ requestId,
170
+ attemptIndex,
171
+ elapsedMs,
172
+ intervalMs,
173
+ timeoutMs: POLL_TIMEOUT_MS,
174
+ });
175
+
176
+ // Check timeout
177
+ if (elapsedMs > POLL_TIMEOUT_MS) {
178
+ throw new CofheError({
179
+ code: CofheErrorCode.SealOutputFailed,
180
+ message: `sealOutput polling timed out after ${POLL_TIMEOUT_MS}ms`,
181
+ hint: 'The request may still be processing. Try again later.',
182
+ context: {
183
+ thresholdNetworkUrl,
184
+ requestId,
185
+ timeoutMs: POLL_TIMEOUT_MS,
186
+ },
187
+ });
188
+ }
189
+
190
+ let response: Response;
191
+ try {
192
+ response = await fetch(`${thresholdNetworkUrl}/v2/sealoutput/${requestId}`, {
193
+ method: 'GET',
194
+ headers: {
195
+ 'Content-Type': 'application/json',
196
+ },
197
+ });
198
+ } catch (e) {
199
+ throw new CofheError({
200
+ code: CofheErrorCode.SealOutputFailed,
201
+ message: `sealOutput status poll failed`,
202
+ hint: 'Ensure the threshold network URL is valid and reachable.',
203
+ cause: e instanceof Error ? e : undefined,
204
+ context: {
205
+ thresholdNetworkUrl,
206
+ requestId,
207
+ },
208
+ });
209
+ }
210
+
211
+ // Handle 404 - request not found
212
+ if (response.status === 404) {
213
+ throw new CofheError({
214
+ code: CofheErrorCode.SealOutputFailed,
215
+ message: `sealOutput request not found: ${requestId}`,
216
+ hint: 'The request may have expired or been invalid.',
217
+ context: {
218
+ thresholdNetworkUrl,
219
+ requestId,
220
+ },
221
+ });
222
+ }
223
+
224
+ // Handle other non-200 status codes
225
+ if (!response.ok) {
226
+ let errorMessage = `HTTP ${response.status}`;
227
+ try {
228
+ const errorBody = await response.json();
229
+ errorMessage = errorBody.error_message || errorBody.message || errorMessage;
230
+ } catch {
231
+ errorMessage = response.statusText || errorMessage;
232
+ }
233
+
234
+ throw new CofheError({
235
+ code: CofheErrorCode.SealOutputFailed,
236
+ message: `sealOutput status poll failed: ${errorMessage}`,
237
+ context: {
238
+ thresholdNetworkUrl,
239
+ requestId,
240
+ status: response.status,
241
+ statusText: response.statusText,
242
+ },
243
+ });
244
+ }
245
+
246
+ let statusResponse: SealOutputStatusResponse;
247
+ try {
248
+ statusResponse = (await response.json()) as SealOutputStatusResponse;
249
+ } catch (e) {
250
+ throw new CofheError({
251
+ code: CofheErrorCode.SealOutputFailed,
252
+ message: `Failed to parse sealOutput status response`,
253
+ cause: e instanceof Error ? e : undefined,
254
+ context: {
255
+ thresholdNetworkUrl,
256
+ requestId,
257
+ },
258
+ });
259
+ }
260
+
261
+ // Check if completed
262
+ if (statusResponse.status === 'COMPLETED') {
263
+ // Check if succeeded
264
+ if (statusResponse.is_succeed === false) {
265
+ const errorMessage = statusResponse.error_message || 'Unknown error';
266
+ throw new CofheError({
267
+ code: CofheErrorCode.SealOutputFailed,
268
+ message: `sealOutput request failed: ${errorMessage}`,
269
+ context: {
270
+ thresholdNetworkUrl,
271
+ requestId,
272
+ statusResponse,
273
+ },
274
+ });
275
+ }
276
+
277
+ // Check if sealed data exists
278
+ if (!statusResponse.sealed) {
279
+ throw new CofheError({
280
+ code: CofheErrorCode.SealOutputReturnedNull,
281
+ message: `sealOutput request completed but returned no sealed data`,
282
+ context: {
283
+ thresholdNetworkUrl,
284
+ requestId,
285
+ statusResponse,
286
+ },
287
+ });
288
+ }
289
+
290
+ // Convert and return the sealed data
291
+ return convertSealedData(statusResponse.sealed);
292
+ }
293
+
294
+ // Still processing, wait before next poll
295
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
296
+ attemptIndex += 1;
297
+ }
298
+
299
+ // This should never be reached, but TypeScript requires it
300
+ throw new CofheError({
301
+ code: CofheErrorCode.SealOutputFailed,
302
+ message: 'Polling loop exited unexpectedly',
303
+ context: {
304
+ thresholdNetworkUrl,
305
+ requestId,
306
+ },
307
+ });
308
+ }
309
+
310
+ export async function tnSealOutputV2(params: {
311
+ ctHash: bigint | string;
312
+ chainId: number;
313
+ permission: Permission;
314
+ thresholdNetworkUrl: string;
315
+ onPoll?: DecryptPollCallbackFunction;
316
+ }): Promise<EthEncryptedData> {
317
+ const { thresholdNetworkUrl, ctHash, chainId, permission, onPoll } = params;
318
+
319
+ // Step 1: Submit the request and get request_id
320
+ const requestId = await submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission);
321
+
322
+ // Step 2: Poll for status until completed
323
+ return await pollSealOutputStatus(thresholdNetworkUrl, requestId, onPoll);
324
+ }
@@ -0,0 +1,52 @@
1
+ import {
2
+ encodePacked,
3
+ isAddressEqual,
4
+ keccak256,
5
+ parseAbi,
6
+ recoverAddress,
7
+ zeroAddress,
8
+ type Address,
9
+ type Hex,
10
+ type PublicClient,
11
+ } from 'viem';
12
+ import { TASK_MANAGER_ADDRESS } from '../consts.js';
13
+
14
+ const decryptResultSignerAbi = parseAbi(['function decryptResultSigner() view returns (address)']);
15
+
16
+ /**
17
+ * Verifies a decrypt result signature **locally** (no `ctHash`/plaintext sent over RPC).
18
+ *
19
+ * This matches the TaskManager contract logic:
20
+ * - messageHash = keccak256(abi.encodePacked(ctHash, result))
21
+ * - recovered = ecrecover(messageHash, signature)
22
+ * - recovered must equal the on-chain configured `decryptResultSigner`
23
+ *
24
+ * The only on-chain read performed is `TaskManager.decryptResultSigner()` (via `eth_call`).
25
+ *
26
+ * Works with both production and mock deployments.
27
+ */
28
+ export async function verifyDecryptResult(
29
+ handle: bigint | string,
30
+ cleartext: bigint,
31
+ signature: Hex,
32
+ publicClient: PublicClient
33
+ ): Promise<boolean> {
34
+ const expectedSigner = await publicClient.readContract({
35
+ address: TASK_MANAGER_ADDRESS,
36
+ abi: decryptResultSignerAbi,
37
+ functionName: 'decryptResultSigner',
38
+ args: [],
39
+ });
40
+
41
+ if (isAddressEqual(expectedSigner, zeroAddress)) return true;
42
+
43
+ const ctHash = BigInt(handle);
44
+ const messageHash = keccak256(encodePacked(['uint256', 'uint256'], [ctHash, cleartext]));
45
+
46
+ try {
47
+ const recovered = await recoverAddress({ hash: messageHash, signature });
48
+ return isAddressEqual(recovered, expectedSigner);
49
+ } catch {
50
+ return false;
51
+ }
52
+ }
@@ -0,0 +1,106 @@
1
+ export const MockZkVerifierAbi = [
2
+ {
3
+ type: 'function',
4
+ name: 'exists',
5
+ inputs: [],
6
+ outputs: [{ name: '', type: 'bool', internalType: 'bool' }],
7
+ stateMutability: 'pure',
8
+ },
9
+ {
10
+ type: 'function',
11
+ name: 'insertCtHash',
12
+ inputs: [
13
+ { name: 'ctHash', type: 'uint256', internalType: 'uint256' },
14
+ { name: 'value', type: 'uint256', internalType: 'uint256' },
15
+ ],
16
+ outputs: [],
17
+ stateMutability: 'nonpayable',
18
+ },
19
+ {
20
+ type: 'function',
21
+ name: 'insertPackedCtHashes',
22
+ inputs: [
23
+ { name: 'ctHashes', type: 'uint256[]', internalType: 'uint256[]' },
24
+ { name: 'values', type: 'uint256[]', internalType: 'uint256[]' },
25
+ ],
26
+ outputs: [],
27
+ stateMutability: 'nonpayable',
28
+ },
29
+ {
30
+ type: 'function',
31
+ name: 'zkVerify',
32
+ inputs: [
33
+ { name: 'value', type: 'uint256', internalType: 'uint256' },
34
+ { name: 'utype', type: 'uint8', internalType: 'uint8' },
35
+ { name: 'user', type: 'address', internalType: 'address' },
36
+ { name: 'securityZone', type: 'uint8', internalType: 'uint8' },
37
+ { name: '', type: 'uint256', internalType: 'uint256' },
38
+ ],
39
+ outputs: [
40
+ {
41
+ name: '',
42
+ type: 'tuple',
43
+ internalType: 'struct EncryptedInput',
44
+ components: [
45
+ { name: 'ctHash', type: 'uint256', internalType: 'uint256' },
46
+ { name: 'securityZone', type: 'uint8', internalType: 'uint8' },
47
+ { name: 'utype', type: 'uint8', internalType: 'uint8' },
48
+ { name: 'signature', type: 'bytes', internalType: 'bytes' },
49
+ ],
50
+ },
51
+ ],
52
+ stateMutability: 'nonpayable',
53
+ },
54
+ {
55
+ type: 'function',
56
+ name: 'zkVerifyCalcCtHash',
57
+ inputs: [
58
+ { name: 'value', type: 'uint256', internalType: 'uint256' },
59
+ { name: 'utype', type: 'uint8', internalType: 'uint8' },
60
+ { name: 'user', type: 'address', internalType: 'address' },
61
+ { name: 'securityZone', type: 'uint8', internalType: 'uint8' },
62
+ { name: '', type: 'uint256', internalType: 'uint256' },
63
+ ],
64
+ outputs: [{ name: 'ctHash', type: 'uint256', internalType: 'uint256' }],
65
+ stateMutability: 'view',
66
+ },
67
+ {
68
+ type: 'function',
69
+ name: 'zkVerifyCalcCtHashesPacked',
70
+ inputs: [
71
+ { name: 'values', type: 'uint256[]', internalType: 'uint256[]' },
72
+ { name: 'utypes', type: 'uint8[]', internalType: 'uint8[]' },
73
+ { name: 'user', type: 'address', internalType: 'address' },
74
+ { name: 'securityZone', type: 'uint8', internalType: 'uint8' },
75
+ { name: 'chainId', type: 'uint256', internalType: 'uint256' },
76
+ ],
77
+ outputs: [{ name: 'ctHashes', type: 'uint256[]', internalType: 'uint256[]' }],
78
+ stateMutability: 'view',
79
+ },
80
+ {
81
+ type: 'function',
82
+ name: 'zkVerifyPacked',
83
+ inputs: [
84
+ { name: 'values', type: 'uint256[]', internalType: 'uint256[]' },
85
+ { name: 'utypes', type: 'uint8[]', internalType: 'uint8[]' },
86
+ { name: 'user', type: 'address', internalType: 'address' },
87
+ { name: 'securityZone', type: 'uint8', internalType: 'uint8' },
88
+ { name: 'chainId', type: 'uint256', internalType: 'uint256' },
89
+ ],
90
+ outputs: [
91
+ {
92
+ name: 'inputs',
93
+ type: 'tuple[]',
94
+ internalType: 'struct EncryptedInput[]',
95
+ components: [
96
+ { name: 'ctHash', type: 'uint256', internalType: 'uint256' },
97
+ { name: 'securityZone', type: 'uint8', internalType: 'uint8' },
98
+ { name: 'utype', type: 'uint8', internalType: 'uint8' },
99
+ { name: 'signature', type: 'bytes', internalType: 'bytes' },
100
+ ],
101
+ },
102
+ ],
103
+ stateMutability: 'nonpayable',
104
+ },
105
+ { type: 'error', name: 'InvalidInputs', inputs: [] },
106
+ ] as const;