@zama-fhe/relayer-sdk 0.4.0-alpha.0 → 0.4.0-alpha.2

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.
package/lib/node.js CHANGED
@@ -1,37 +1,15 @@
1
1
  import * as TFHEPkg from 'node-tfhe';
2
2
  import { ShortintParameters, ShortintParametersName, ShortintCompactPublicKeyEncryptionParameters, ShortintCompactPublicKeyEncryptionParametersName, TfheConfigBuilder, TfheClientKey, TfheCompactPublicKey, CompactPkeCrs } from 'node-tfhe';
3
3
  import * as TKMSPkg from 'node-tkms';
4
- import { JsonRpcProvider, BrowserProvider, Contract, getAddress as getAddress$2, ethers, isAddress as isAddress$1, keccak256, AbiCoder } from 'ethers';
4
+ import { JsonRpcProvider, BrowserProvider, Contract, getAddress as getAddress$2, isAddress as isAddress$1, keccak256, ethers, AbiCoder } from 'ethers';
5
5
 
6
6
  const SERIALIZED_SIZE_LIMIT_CIPHERTEXT = BigInt(1024 * 1024 * 512);
7
7
  const SERIALIZED_SIZE_LIMIT_PK = BigInt(1024 * 1024 * 512);
8
8
  const SERIALIZED_SIZE_LIMIT_CRS = BigInt(1024 * 1024 * 512);
9
9
 
10
- function setAuth(init, auth) {
11
- if (auth) {
12
- switch (auth.__type) {
13
- case 'BearerToken':
14
- init.headers['Authorization'] =
15
- `Bearer ${auth.token}`;
16
- break;
17
- case 'ApiKeyHeader':
18
- init.headers[auth.header || 'x-api-key'] =
19
- auth.value;
20
- break;
21
- case 'ApiKeyCookie':
22
- if (typeof window !== 'undefined') {
23
- document.cookie = `${auth.cookie || 'x-api-key'}=${auth.value}; path=/; SameSite=Lax; Secure; HttpOnly;`;
24
- init.credentials = 'include';
25
- }
26
- else {
27
- let cookie = `${auth.cookie || 'x-api-key'}=${auth.value};`;
28
- init.headers['Cookie'] = cookie;
29
- }
30
- break;
31
- }
32
- }
33
- return init;
34
- }
10
+ // This file is auto-generated
11
+ const version = '0.4.0-alpha.2';
12
+ const sdkName = '@zama-fhe/relayer-sdk';
35
13
 
36
14
  function getErrorCause(e) {
37
15
  if (e instanceof Error && typeof e.cause === 'object' && e.cause !== null) {
@@ -213,7 +191,39 @@ function throwRelayerUnknownError(operation, error, message) {
213
191
  });
214
192
  }
215
193
 
216
- ////////////////////////////////////////////////////////////////////////////////
194
+ /**
195
+ * Set the authentication method for the request. The default is no authentication.
196
+ * It supports:
197
+ * - Bearer Token
198
+ * - Custom header
199
+ * - Custom cookie
200
+ */
201
+ function setAuth(init, auth) {
202
+ if (auth) {
203
+ switch (auth.__type) {
204
+ case 'BearerToken':
205
+ init.headers['Authorization'] =
206
+ `Bearer ${auth.token}`;
207
+ break;
208
+ case 'ApiKeyHeader':
209
+ init.headers[auth.header || 'x-api-key'] =
210
+ auth.value;
211
+ break;
212
+ case 'ApiKeyCookie':
213
+ if (typeof window !== 'undefined') {
214
+ document.cookie = `${auth.cookie || 'x-api-key'}=${auth.value}; path=/; SameSite=Lax; Secure; HttpOnly;`;
215
+ init.credentials = 'include';
216
+ }
217
+ else {
218
+ let cookie = `${auth.cookie || 'x-api-key'}=${auth.value};`;
219
+ init.headers['Cookie'] = cookie;
220
+ }
221
+ break;
222
+ }
223
+ }
224
+ return init;
225
+ }
226
+
217
227
  function assertIsRelayerV1FetchResponseJson(json) {
218
228
  if (!json || typeof json !== 'object') {
219
229
  throw new Error('Unexpected response JSON.');
@@ -224,11 +234,13 @@ function assertIsRelayerV1FetchResponseJson(json) {
224
234
  throw new Error("Unexpected response JSON format: missing 'response' property.");
225
235
  }
226
236
  }
227
- async function fetchRelayerJsonRpcPost(relayerOperation, url, payload, options) {
237
+ async function fetchRelayerV1Post(relayerOperation, url, payload, options) {
228
238
  const init = setAuth({
229
239
  method: 'POST',
230
240
  headers: {
231
241
  'Content-Type': 'application/json',
242
+ 'ZAMA-SDK-VERSION': `${version}`,
243
+ 'ZAMA-SDK-NAME': `${sdkName}`,
232
244
  },
233
245
  body: JSON.stringify(payload),
234
246
  }, options?.auth);
@@ -259,14 +271,20 @@ async function fetchRelayerJsonRpcPost(relayerOperation, url, payload, options)
259
271
  }
260
272
  return json;
261
273
  }
262
- async function fetchRelayerGet(relayerOperation, url) {
274
+ async function fetchRelayerV1Get(relayerOperation, url) {
275
+ const init = {
276
+ method: 'GET',
277
+ headers: {
278
+ 'ZAMA-SDK-VERSION': `${version}`,
279
+ 'ZAMA-SDK-NAME': `${sdkName}`,
280
+ },
281
+ };
263
282
  let response;
264
283
  let json;
265
284
  try {
266
- response = await fetch(url);
285
+ response = await fetch(url, init);
267
286
  }
268
287
  catch (e) {
269
- console.log(e);
270
288
  throwRelayerUnknownError(relayerOperation, e);
271
289
  }
272
290
  if (!response.ok) {
@@ -294,7 +312,7 @@ const getKeysFromRelayer = async (versionUrl, publicKeyId) => {
294
312
  if (keyurlCache[versionUrl]) {
295
313
  return keyurlCache[versionUrl];
296
314
  }
297
- const data = await fetchRelayerGet('KEY_URL', `${versionUrl}/keyurl`);
315
+ const data = await fetchRelayerV1Get('KEY_URL', `${versionUrl}/keyurl`);
298
316
  try {
299
317
  let pubKeyUrl;
300
318
  // If no publicKeyId is provided, use the first one
@@ -383,7 +401,7 @@ class RelayerErrorBase extends Error {
383
401
  _docsPath;
384
402
  _docsUrl;
385
403
  _version;
386
- static VERSION = '0.3.0-6';
404
+ static VERSION = version;
387
405
  static DEFAULT_DOCS_BASE_URL = 'https//docs.zama.org';
388
406
  static FULL_VERSION = `@zama-fhe/relayer-sdk@${RelayerErrorBase.VERSION}`;
389
407
  constructor(params) {
@@ -792,6 +810,14 @@ function assertRecordStringArrayProperty(o, property, objName) {
792
810
  }
793
811
  }
794
812
  }
813
+ function safeJSONstringify(o, space) {
814
+ try {
815
+ return JSON.stringify(o, (_, v) => (typeof v === 'bigint' ? v.toString() : v), space);
816
+ }
817
+ catch {
818
+ return '';
819
+ }
820
+ }
795
821
 
796
822
  const abiKmsVerifier = [
797
823
  'function getKmsSigners() view returns (address[])',
@@ -891,6 +917,7 @@ const getCoprocessorSignersThreshold = async (provider, inputVerifierContractAdd
891
917
  return Number(threshold); // threshold is always supposed to fit in a number
892
918
  };
893
919
 
920
+ // This file contains common utilities for both user and public decryption requests
894
921
  const NumEncryptedBits = {
895
922
  0: 2, // ebool
896
923
  2: 8, // euint8
@@ -901,17 +928,17 @@ const NumEncryptedBits = {
901
928
  7: 160, // eaddress
902
929
  8: 256, // euint256
903
930
  };
904
- function getHandleType(handle) {
905
- if (handle.length !== 66) {
906
- throw new Error(`Handle ${handle} is not of valid length`);
907
- }
908
- const hexPair = handle.slice(-4, -2).toLowerCase();
909
- const typeDiscriminant = parseInt(hexPair, 16);
910
- if (!(typeDiscriminant in NumEncryptedBits)) {
911
- throw new Error(`Handle ${handle} is not of valid type`);
912
- }
913
- return typeDiscriminant;
914
- }
931
+ // export function getHandleType(handle: `0x${string}`): number {
932
+ // if (handle.length !== 66) {
933
+ // throw new Error(`Handle ${handle} is not of valid length`);
934
+ // }
935
+ // const hexPair = handle.slice(-4, -2).toLowerCase();
936
+ // const typeDiscriminant = parseInt(hexPair, 16);
937
+ // if (!(typeDiscriminant in NumEncryptedBits)) {
938
+ // throw new Error(`Handle ${handle} is not of valid type`);
939
+ // }
940
+ // return typeDiscriminant;
941
+ // }
915
942
  function checkEncryptedBits(handles) {
916
943
  let total = 0;
917
944
  for (const handle of handles) {
@@ -969,7 +996,7 @@ function isBytes(value, bytewidth) {
969
996
  if (!(value instanceof Uint8Array)) {
970
997
  return false;
971
998
  }
972
- return value.length === bytewidth ;
999
+ return bytewidth ? value.length === bytewidth : true;
973
1000
  }
974
1001
  function isBytesHex(value, bytewidth) {
975
1002
  if (!is0x(value)) {
@@ -1202,6 +1229,54 @@ function assertUint8ArrayProperty(o, property, objName) {
1202
1229
  });
1203
1230
  }
1204
1231
  }
1232
+ ////////////////////////////////////////////////////////////////////////////////
1233
+ // Hex
1234
+ ////////////////////////////////////////////////////////////////////////////////
1235
+ const HEX_CHARS = {
1236
+ '0': 0,
1237
+ '1': 1,
1238
+ '2': 2,
1239
+ '3': 3,
1240
+ '4': 4,
1241
+ '5': 5,
1242
+ '6': 6,
1243
+ '7': 7,
1244
+ '8': 8,
1245
+ '9': 9,
1246
+ a: 10,
1247
+ b: 11,
1248
+ c: 12,
1249
+ d: 13,
1250
+ e: 14,
1251
+ f: 15,
1252
+ A: 10,
1253
+ B: 11,
1254
+ C: 12,
1255
+ D: 13,
1256
+ E: 14,
1257
+ F: 15,
1258
+ };
1259
+ Object.freeze(HEX_CHARS);
1260
+ const HEX_BYTES = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
1261
+ Object.freeze(HEX_BYTES);
1262
+ const HEX_CHARS_CODES = new Uint8Array([
1263
+ 48,
1264
+ 49,
1265
+ 50,
1266
+ 51,
1267
+ 52,
1268
+ 53,
1269
+ 54,
1270
+ 55,
1271
+ 56,
1272
+ 57, // '0'-'9'
1273
+ 97,
1274
+ 98,
1275
+ 99,
1276
+ 100,
1277
+ 101,
1278
+ 102, // 'a'-'f'
1279
+ ]);
1205
1280
  /**
1206
1281
  * Convert a Uint8Array to a hex string (without 0x prefix).
1207
1282
  */
@@ -1221,15 +1296,49 @@ function bytesToHexNo0x(bytes) {
1221
1296
  function bytesToHex(bytes) {
1222
1297
  return `0x${bytesToHexNo0x(bytes)}`;
1223
1298
  }
1299
+ function bytesToHexLarge(bytes) {
1300
+ const out = new Uint8Array(2 + bytes.length * 2);
1301
+ out[0] = 48; // '0'
1302
+ out[1] = 120; // 'x'
1303
+ for (let i = 0; i < bytes.length; i++) {
1304
+ const j = 2 + i * 2;
1305
+ out[j] = HEX_CHARS_CODES[bytes[i] >> 4];
1306
+ out[j + 1] = HEX_CHARS_CODES[bytes[i] & 0xf];
1307
+ }
1308
+ return new TextDecoder().decode(out);
1309
+ }
1224
1310
  /**
1225
1311
  * Convert a hex string prefixed by 0x or not to a Uint8Array
1312
+ * Any invalid byte string is converted to 0
1313
+ * "0xzzff" = [0, 255]
1314
+ * "0xzfff" = [0, 255]
1226
1315
  */
1227
1316
  function hexToBytes(hexString) {
1317
+ if (hexString.length % 2 !== 0) {
1318
+ throw new Error('Invalid hex string: odd length');
1319
+ }
1228
1320
  const arr = hexString.replace(/^(0x)/, '').match(/.{1,2}/g);
1229
1321
  if (!arr)
1230
1322
  return new Uint8Array();
1231
1323
  return Uint8Array.from(arr.map((byte) => parseInt(byte, 16)));
1232
1324
  }
1325
+ function hexToBytesFaster(hexString, strict = false) {
1326
+ const offset = hexString[0] === '0' && hexString[1] === 'x' ? 2 : 0;
1327
+ const len = hexString.length - offset;
1328
+ if (len % 2 !== 0) {
1329
+ throw new Error('Invalid hex string: odd length');
1330
+ }
1331
+ const bytes = new Uint8Array(len / 2);
1332
+ for (let i = 0; i < bytes.length; i++) {
1333
+ const hi = HEX_CHARS[hexString[offset + i * 2]];
1334
+ const lo = HEX_CHARS[hexString[offset + i * 2 + 1]];
1335
+ if ((hi === undefined || lo === undefined) && strict) {
1336
+ throw new Error(`Invalid hex character at position ${offset + i * 2}`);
1337
+ }
1338
+ bytes[i] = (hi << 4) | lo;
1339
+ }
1340
+ return bytes;
1341
+ }
1233
1342
  /**
1234
1343
  * Convert a Uint8Array to a bigint
1235
1344
  */
@@ -1243,9 +1352,6 @@ function bytesToBigInt(byteArray) {
1243
1352
  }
1244
1353
  return result;
1245
1354
  }
1246
- function toHexString(bytes, with0x = false) {
1247
- return `${with0x ? '0x' : ''}${bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '')}`;
1248
- }
1249
1355
  async function fetchBytes(url) {
1250
1356
  const response = await fetch(url);
1251
1357
  if (!response.ok) {
@@ -1321,9 +1427,7 @@ function checkDeadlineValidity(startTimestamp, durationDays) {
1321
1427
  throw Error('User decrypt request has expired');
1322
1428
  }
1323
1429
  }
1324
- const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContractAddress, aclContractAddress,
1325
- //relayerUrl: string,
1326
- relayerProvider, provider, instanceOptions) => async (_handles, privateKey, publicKey, signature, contractAddresses, userAddress, startTimestamp, durationDays, options) => {
1430
+ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContractAddress, aclContractAddress, relayerProvider, provider, defaultOptions) => async (_handles, privateKey, publicKey, signature, contractAddresses, userAddress, startTimestamp, durationDays, options) => {
1327
1431
  const extraData = '0x00';
1328
1432
  let pubKey;
1329
1433
  let privKey;
@@ -1337,16 +1441,16 @@ relayerProvider, provider, instanceOptions) => async (_handles, privateKey, publ
1337
1441
  // Casting handles if string
1338
1442
  const signatureSanitized = signature.replace(/^(0x)/, '');
1339
1443
  const publicKeySanitized = publicKey.replace(/^(0x)/, '');
1340
- const handles = _handles.map((h) => ({
1444
+ const handleContractPairs = _handles.map((h) => ({
1341
1445
  handle: typeof h.handle === 'string'
1342
- ? toHexString(hexToBytes(h.handle), true)
1343
- : toHexString(h.handle, true),
1446
+ ? bytesToHex(hexToBytes(h.handle))
1447
+ : bytesToHex(h.handle),
1344
1448
  contractAddress: getAddress$1(h.contractAddress),
1345
1449
  }));
1346
- checkEncryptedBits(handles.map((h) => h.handle));
1450
+ checkEncryptedBits(handleContractPairs.map((h) => h.handle));
1347
1451
  checkDeadlineValidity(BigInt(startTimestamp), BigInt(durationDays));
1348
- const acl = new ethers.Contract(aclContractAddress, aclABI$1, provider);
1349
- const verifications = handles.map(async ({ handle, contractAddress }) => {
1452
+ const acl = new Contract(aclContractAddress, aclABI$1, provider);
1453
+ const verifications = handleContractPairs.map(async ({ handle, contractAddress }) => {
1350
1454
  const userAllowed = await acl.persistAllowed(handle, userAddress);
1351
1455
  const contractAllowed = await acl.persistAllowed(handle, contractAddress);
1352
1456
  if (!userAllowed) {
@@ -1370,7 +1474,7 @@ relayerProvider, provider, instanceOptions) => async (_handles, privateKey, publ
1370
1474
  throw e;
1371
1475
  });
1372
1476
  const payloadForRequest = {
1373
- handleContractPairs: handles,
1477
+ handleContractPairs,
1374
1478
  requestValidity: {
1375
1479
  startTimestamp: startTimestamp.toString(), // Convert to string
1376
1480
  durationDays: durationDays.toString(), // Convert to string
@@ -1382,13 +1486,10 @@ relayerProvider, provider, instanceOptions) => async (_handles, privateKey, publ
1382
1486
  publicKey: publicKeySanitized,
1383
1487
  extraData,
1384
1488
  };
1385
- const json = await relayerProvider.fetchPostUserDecrypt(payloadForRequest, options ?? instanceOptions);
1386
- // const json = await fetchRelayerJsonRpcPost(
1387
- // 'USER_DECRYPT',
1388
- // `${relayerUrl}/v1/user-decrypt`,
1389
- // payloadForRequest,
1390
- // instanceOptions ?? options,
1391
- // );
1489
+ const json = await relayerProvider.fetchPostUserDecrypt(payloadForRequest, {
1490
+ ...defaultOptions,
1491
+ ...options,
1492
+ });
1392
1493
  // assume the KMS Signers have the correct order
1393
1494
  let indexedKmsSigners = kmsSigners.map((signer, index) => {
1394
1495
  return TKMS.new_server_id_addr(index + 1, signer);
@@ -1410,13 +1511,13 @@ relayerProvider, provider, instanceOptions) => async (_handles, privateKey, publ
1410
1511
  signature: signatureSanitized,
1411
1512
  client_address: userAddress,
1412
1513
  enc_key: publicKeySanitized,
1413
- ciphertext_handles: handles.map((h) => h.handle.replace(/^0x/, '')),
1514
+ ciphertext_handles: handleContractPairs.map((h) => h.handle.replace(/^0x/, '')),
1414
1515
  eip712_verifying_contract: verifyingContractAddress,
1415
1516
  };
1416
1517
  const decryption = TKMS.process_user_decryption_resp_from_js(client, payloadForVerification, eip712Domain, json, //json.response,
1417
1518
  pubKey, privKey, true);
1418
1519
  const listBigIntDecryptions = decryption.map((d) => bytesToBigInt(d.bytes));
1419
- const results = buildUserDecryptResults(handles.map((h) => h.handle), listBigIntDecryptions);
1520
+ const results = buildUserDecryptResults(handleContractPairs.map((h) => h.handle), listBigIntDecryptions);
1420
1521
  return results;
1421
1522
  }
1422
1523
  catch (e) {
@@ -1559,9 +1660,8 @@ const createEncryptedInput = ({ aclContractAddress, chainId, tfheCompactPublicKe
1559
1660
 
1560
1661
  const MAX_UINT64 = BigInt('18446744073709551615'); // 2^64 - 1
1561
1662
  BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
1562
- const MAX_UINT32 = 0xffffffff;
1563
1663
  const MAX_UINT8 = 0xff;
1564
- function numberToHex(num) {
1664
+ function numberToHexNo0x(num) {
1565
1665
  let hex = num.toString(16);
1566
1666
  return hex.length % 2 ? '0' + hex : hex;
1567
1667
  }
@@ -1595,25 +1695,19 @@ function isUint8(value) {
1595
1695
  }
1596
1696
  return value <= MAX_UINT8;
1597
1697
  }
1598
- function isUint32(value) {
1599
- if (!isUint(value)) {
1600
- return false;
1601
- }
1602
- return value <= MAX_UINT32;
1603
- }
1604
1698
  function isUint64(value) {
1605
1699
  if (!isUint(value)) {
1606
1700
  return false;
1607
1701
  }
1608
1702
  return value <= MAX_UINT64;
1609
1703
  }
1610
- function uint32ToBytes32(uint32) {
1611
- if (!isUint32(uint32)) {
1612
- throw new InvalidTypeError({ expectedType: 'Uint32' });
1704
+ function numberToBytes32(num) {
1705
+ if (!isUintNumber(num)) {
1706
+ throw new InvalidTypeError({ expectedType: 'Uint' });
1613
1707
  }
1614
1708
  const buffer = new ArrayBuffer(32);
1615
1709
  const view = new DataView(buffer);
1616
- view.setUint32(28, Number(uint32), false);
1710
+ view.setBigUint64(24, BigInt(num), false);
1617
1711
  return new Uint8Array(buffer);
1618
1712
  }
1619
1713
  function assertIsUint8(value) {
@@ -1708,47 +1802,216 @@ function checksummedAddressToBytes20(address) {
1708
1802
  return bytes;
1709
1803
  }
1710
1804
 
1805
+ class FhevmHandleError extends RelayerErrorBase {
1806
+ constructor({ handle, message }) {
1807
+ super({
1808
+ message: message ??
1809
+ (handle
1810
+ ? `FHEVM Handle "${handle}" is invalid.`
1811
+ : `FHEVM Handle is invalid.`),
1812
+ name: 'FhevmHandleError',
1813
+ });
1814
+ }
1815
+ }
1816
+
1817
+ class FheTypeError extends RelayerErrorBase {
1818
+ constructor({ fheTypeId, message, }) {
1819
+ super({
1820
+ message: message ??
1821
+ (fheTypeId
1822
+ ? `FheTypeId "${fheTypeId}" is invalid.`
1823
+ : `FheTypeId is invalid.`),
1824
+ name: 'FheTypeError',
1825
+ });
1826
+ }
1827
+ }
1828
+
1829
+ const FheTypeIdToName = {
1830
+ 0: 'ebool',
1831
+ //1: 'euint4', has been deprecated
1832
+ 2: 'euint8',
1833
+ 3: 'euint16',
1834
+ 4: 'euint32',
1835
+ 5: 'euint64',
1836
+ 6: 'euint128',
1837
+ 7: 'eaddress',
1838
+ 8: 'euint256',
1839
+ };
1840
+ const FheTypeIdToEncryptionBitwidth = {
1841
+ 0: 2,
1842
+ //1:?, euint4 has been deprecated
1843
+ 2: 8,
1844
+ 3: 16,
1845
+ 4: 32,
1846
+ 5: 64,
1847
+ 6: 128,
1848
+ 7: 160,
1849
+ 8: 256,
1850
+ };
1851
+ const EncryptionBitwidthToFheTypeId = {
1852
+ 2: 0,
1853
+ //?:1, euint4 has been deprecated
1854
+ 8: 2,
1855
+ 16: 3,
1856
+ 32: 4,
1857
+ 64: 5,
1858
+ 128: 6,
1859
+ 160: 7,
1860
+ 256: 8,
1861
+ };
1862
+ const FheTypeIdToSolidityPrimitiveTypeName = {
1863
+ 0: 'bool',
1864
+ //1:'uint256', euint4 has been deprecated
1865
+ 2: 'uint256',
1866
+ 3: 'uint256',
1867
+ 4: 'uint256',
1868
+ 5: 'uint256',
1869
+ 6: 'uint256',
1870
+ 7: 'address',
1871
+ 8: 'uint256',
1872
+ };
1873
+ Object.freeze(FheTypeIdToEncryptionBitwidth);
1874
+ Object.freeze(EncryptionBitwidthToFheTypeId);
1875
+ Object.freeze(FheTypeIdToSolidityPrimitiveTypeName);
1876
+ ////////////////////////////////////////////////////////////////////////////////
1877
+ // Type Guards
1878
+ ////////////////////////////////////////////////////////////////////////////////
1879
+ /**
1880
+ * Checks if a value is a valid FheTypeId.
1881
+ * @example isFheTypeId(2) // true (euint8)
1882
+ * @example isFheTypeId(1) // false (euint4 is deprecated)
1883
+ */
1884
+ function isFheTypeId(value) {
1885
+ switch (value) {
1886
+ case 0:
1887
+ // 1: euint4 is deprecated
1888
+ case 2:
1889
+ case 3:
1890
+ case 4:
1891
+ case 5:
1892
+ case 6:
1893
+ case 7:
1894
+ case 8:
1895
+ return true;
1896
+ default:
1897
+ return false;
1898
+ }
1899
+ }
1900
+ /**
1901
+ * Checks if a value is a valid encryption bit width.
1902
+ * @example isEncryptionBits(8) // true
1903
+ * @example isEncryptionBits(4) // false (euint4 is deprecated)
1904
+ */
1905
+ function isEncryptionBits(value) {
1906
+ if (typeof value !== 'number') {
1907
+ return false;
1908
+ }
1909
+ return value in EncryptionBitwidthToFheTypeId;
1910
+ }
1911
+ ////////////////////////////////////////////////////////////////////////////////
1912
+ // FheTypeId extractors
1913
+ ////////////////////////////////////////////////////////////////////////////////
1914
+ /**
1915
+ * Converts an encryption bit width to its corresponding FheTypeId.
1916
+ * @throws {FheTypeError} If bitwidth is not a valid encryption bit width.
1917
+ * @example fheTypeIdFromEncryptionBits(8) // 2 (euint8)
1918
+ */
1919
+ function fheTypeIdFromEncryptionBits(bitwidth) {
1920
+ if (!isEncryptionBits(bitwidth)) {
1921
+ throw new FheTypeError({
1922
+ message: `Invalid encryption bits ${bitwidth}`,
1923
+ });
1924
+ }
1925
+ return EncryptionBitwidthToFheTypeId[bitwidth];
1926
+ }
1927
+ /**
1928
+ * Converts an FheTypeId to its corresponding FheTypeName.
1929
+ * @throws {FheTypeError} If id is not a valid FheTypeId.
1930
+ * @example fheTypeNameFromId(2) // 'euint8'
1931
+ */
1932
+ function fheTypeNameFromId(id) {
1933
+ if (!isFheTypeId(id)) {
1934
+ throw new FheTypeError({
1935
+ message: `Invalid FheType id '${id}'`,
1936
+ });
1937
+ }
1938
+ return FheTypeIdToName[id];
1939
+ }
1940
+ ////////////////////////////////////////////////////////////////////////////////
1941
+ // Solidity primitive type names
1942
+ ////////////////////////////////////////////////////////////////////////////////
1943
+ /**
1944
+ * Returns the Solidity primitive type name for an FheTypeId.
1945
+ * @example solidityPrimitiveTypeNameFromFheTypeId(0) // 'bool'
1946
+ * @example solidityPrimitiveTypeNameFromFheTypeId(7) // 'address'
1947
+ * @example solidityPrimitiveTypeNameFromFheTypeId(2) // 'uint256'
1948
+ */
1949
+ function solidityPrimitiveTypeNameFromFheTypeId(typeId) {
1950
+ if (!isFheTypeId(typeId)) {
1951
+ throw new FheTypeError({
1952
+ message: `Invalid FheType id '${typeId}'`,
1953
+ });
1954
+ }
1955
+ return FheTypeIdToSolidityPrimitiveTypeName[typeId];
1956
+ }
1957
+ ////////////////////////////////////////////////////////////////////////////////
1958
+ // Encryption Bits
1959
+ ////////////////////////////////////////////////////////////////////////////////
1960
+ /**
1961
+ * Returns the encryption bit width for an FheTypeId.
1962
+ * @example encryptionBitsFromFheTypeId(2) // 8 (euint8)
1963
+ * @example encryptionBitsFromFheTypeId(7) // 160 (eaddress)
1964
+ */
1965
+ function encryptionBitsFromFheTypeId(typeId) {
1966
+ if (!isFheTypeId(typeId)) {
1967
+ throw new FheTypeError({
1968
+ message: `Invalid FheType id '${typeId}'`,
1969
+ });
1970
+ }
1971
+ return FheTypeIdToEncryptionBitwidth[typeId];
1972
+ }
1973
+
1711
1974
  ////////////////////////////////////////////////////////////////////////////////
1712
1975
  // FhevmHandle
1713
1976
  ////////////////////////////////////////////////////////////////////////////////
1714
1977
  class FhevmHandle {
1978
+ //////////////////////////////////////////////////////////////////////////////
1979
+ // Instance Properties
1980
+ //////////////////////////////////////////////////////////////////////////////
1715
1981
  _hash21;
1716
1982
  _chainId;
1717
1983
  _fheTypeId;
1718
1984
  _version;
1719
1985
  _computed;
1720
1986
  _index;
1987
+ _handleBytes32Hex;
1988
+ _handleBytes32;
1989
+ //////////////////////////////////////////////////////////////////////////////
1990
+ // Static Constants
1991
+ //////////////////////////////////////////////////////////////////////////////
1721
1992
  static RAW_CT_HASH_DOMAIN_SEPARATOR = 'ZK-w_rct';
1722
1993
  static HANDLE_HASH_DOMAIN_SEPARATOR = 'ZK-w_hdl';
1723
- static FheTypeIdToEncryptionBitwidths = {
1724
- 0: 2,
1725
- 2: 8,
1726
- 3: 16,
1727
- 4: 32,
1728
- 5: 64,
1729
- 6: 128,
1730
- 7: 160,
1731
- 8: 256,
1732
- };
1733
- static FheTypeEncryptionBitwidthsToId = {
1734
- 2: 0,
1735
- 8: 2,
1736
- 16: 3,
1737
- 32: 4,
1738
- 64: 5,
1739
- 128: 6,
1740
- 160: 7,
1741
- 256: 8,
1742
- };
1743
- static {
1744
- Object.freeze(FhevmHandle.FheTypeIdToEncryptionBitwidths);
1745
- Object.freeze(FhevmHandle.FheTypeEncryptionBitwidthsToId);
1746
- }
1747
- constructor(hash21, chainId, fheTypeId, version, computed, index) {
1994
+ static CURRENT_CIPHERTEXT_VERSION = 0;
1995
+ //////////////////////////////////////////////////////////////////////////////
1996
+ // Constructor
1997
+ //////////////////////////////////////////////////////////////////////////////
1998
+ constructor({ hash21, chainId, fheTypeId, version, computed, index, handleBytes32, handleBytes32Hex, }) {
1999
+ if (!isUintNumber(chainId)) {
2000
+ throw new FhevmHandleError({
2001
+ message: 'ChainId must be a positive integer',
2002
+ });
2003
+ }
1748
2004
  if (BigInt(chainId) > MAX_UINT64) {
1749
2005
  // fhevm assumes chainID is only taking up to 8 bytes
1750
- throw new Error('ChainId exceeds maximum allowed value (8 bytes)');
2006
+ throw new FhevmHandleError({
2007
+ message: 'ChainId exceeds maximum allowed value (8 bytes)',
2008
+ });
1751
2009
  }
2010
+ if (!isBytesHex(hash21, 21)) {
2011
+ throw new FhevmHandleError({ message: 'Hash21 should be 21 bytes long' });
2012
+ }
2013
+ this._handleBytes32 = handleBytes32;
2014
+ this._handleBytes32Hex = handleBytes32Hex;
1752
2015
  this._hash21 = hash21;
1753
2016
  this._chainId = chainId;
1754
2017
  this._fheTypeId = fheTypeId;
@@ -1758,6 +2021,9 @@ class FhevmHandle {
1758
2021
  this._index = index;
1759
2022
  }
1760
2023
  }
2024
+ //////////////////////////////////////////////////////////////////////////////
2025
+ // Instance Getters
2026
+ //////////////////////////////////////////////////////////////////////////////
1761
2027
  get hash21() {
1762
2028
  return this._hash21;
1763
2029
  }
@@ -1767,6 +2033,9 @@ class FhevmHandle {
1767
2033
  get fheTypeId() {
1768
2034
  return this._fheTypeId;
1769
2035
  }
2036
+ get fheTypeName() {
2037
+ return fheTypeNameFromId(this._fheTypeId);
2038
+ }
1770
2039
  get version() {
1771
2040
  return this._version;
1772
2041
  }
@@ -1776,6 +2045,106 @@ class FhevmHandle {
1776
2045
  get index() {
1777
2046
  return this._index;
1778
2047
  }
2048
+ get encryptedBitwidth() {
2049
+ return encryptionBitsFromFheTypeId(this._fheTypeId);
2050
+ }
2051
+ get solidityPrimitiveTypeName() {
2052
+ return solidityPrimitiveTypeNameFromFheTypeId(this._fheTypeId);
2053
+ }
2054
+ toJSON() {
2055
+ return {
2056
+ handle: this.toBytes32Hex(),
2057
+ fheTypeName: this.fheTypeName,
2058
+ fheTypeId: this.fheTypeId,
2059
+ chainId: this.chainId,
2060
+ index: this.index,
2061
+ computed: this.computed,
2062
+ encryptedBitwidth: this.encryptedBitwidth,
2063
+ version: this.version,
2064
+ solidityPrimitiveTypeName: this.solidityPrimitiveTypeName,
2065
+ hash21: this.hash21,
2066
+ };
2067
+ }
2068
+ //////////////////////////////////////////////////////////////////////////////
2069
+ // Instance Serialization
2070
+ //////////////////////////////////////////////////////////////////////////////
2071
+ toBytes32() {
2072
+ if (this._handleBytes32 === undefined) {
2073
+ assertRelayer((this._index === undefined && this._computed) ||
2074
+ (this._index !== undefined && this._index < 255 && !this._computed));
2075
+ const chainId32Bytes = numberToBytes32(this._chainId);
2076
+ const chainId8Bytes = chainId32Bytes.subarray(24, 32);
2077
+ const handleHash21 = hexToBytes(this._hash21);
2078
+ assertRelayer(handleHash21.length === 21);
2079
+ const handleBytes32AsBytes = new Uint8Array(32);
2080
+ handleBytes32AsBytes.set(handleHash21, 0);
2081
+ handleBytes32AsBytes[21] = this._index === undefined ? 255 : this._index;
2082
+ handleBytes32AsBytes.set(chainId8Bytes, 22);
2083
+ handleBytes32AsBytes[30] = this._fheTypeId;
2084
+ handleBytes32AsBytes[31] = this._version;
2085
+ this._handleBytes32 = handleBytes32AsBytes;
2086
+ }
2087
+ return this._handleBytes32;
2088
+ }
2089
+ toBytes32Hex() {
2090
+ if (this._handleBytes32Hex === undefined) {
2091
+ this._handleBytes32Hex = bytesToHex(this.toBytes32());
2092
+ }
2093
+ return this._handleBytes32Hex;
2094
+ }
2095
+ //////////////////////////////////////////////////////////////////////////////
2096
+ // Static Factory Methods
2097
+ //////////////////////////////////////////////////////////////////////////////
2098
+ static fromComponents(params) {
2099
+ return new FhevmHandle(params);
2100
+ }
2101
+ static fromBytes32(handle) {
2102
+ if (!isBytes32(handle)) {
2103
+ throw new FhevmHandleError({
2104
+ message: `FHEVM Handle is not a valid bytes32 array.`,
2105
+ });
2106
+ }
2107
+ const bytes = handle;
2108
+ // Extract hash21 (bytes 0-20)
2109
+ const hash21 = bytesToHex(bytes.slice(0, 21));
2110
+ // Extract index (byte 21) - 255 means computed
2111
+ const indexByte = bytes[21];
2112
+ const computed = indexByte === 255;
2113
+ const index = computed ? undefined : indexByte;
2114
+ // Extract chainId (bytes 22-29, 8 bytes as big-endian uint64)
2115
+ let chainId = 0;
2116
+ for (let i = 22; i < 30; i++) {
2117
+ chainId = chainId * 256 + bytes[i];
2118
+ }
2119
+ // Extract fheTypeId (byte 30)
2120
+ const fheTypeIdByte = bytes[30];
2121
+ if (!isFheTypeId(fheTypeIdByte)) {
2122
+ throw new FhevmHandleError({
2123
+ handle,
2124
+ message: `FHEVM Handle "${handle}" is invalid. Unknown FheType: ${fheTypeIdByte}`,
2125
+ });
2126
+ }
2127
+ // Extract version (byte 31)
2128
+ const version = bytes[31];
2129
+ return new FhevmHandle({
2130
+ hash21,
2131
+ chainId,
2132
+ fheTypeId: fheTypeIdByte,
2133
+ version,
2134
+ computed,
2135
+ index,
2136
+ handleBytes32: handle,
2137
+ });
2138
+ }
2139
+ static fromBytes32Hex(handle) {
2140
+ if (!isBytes32Hex(handle)) {
2141
+ throw new FhevmHandleError({ handle });
2142
+ }
2143
+ const bytes = hexToBytes(handle);
2144
+ const h = FhevmHandle.fromBytes32(bytes);
2145
+ h._handleBytes32Hex = handle;
2146
+ return h;
2147
+ }
1779
2148
  static fromZKProof(params) {
1780
2149
  assertIsChecksummedAddress(params.aclAddress);
1781
2150
  assertIsUint64(params.chainId);
@@ -1785,7 +2154,7 @@ class FhevmHandle {
1785
2154
  fheTypeIds = params.fheTypeIds;
1786
2155
  }
1787
2156
  else if (params.fheTypeEncryptionBitwidths !== undefined) {
1788
- fheTypeIds = params.fheTypeEncryptionBitwidths.map((w) => FhevmHandle.FheTypeEncryptionBitwidthsToId[w]);
2157
+ fheTypeIds = params.fheTypeEncryptionBitwidths.map((w) => fheTypeIdFromEncryptionBits(w));
1789
2158
  }
1790
2159
  else {
1791
2160
  throw new InternalError({
@@ -1816,22 +2185,69 @@ class FhevmHandle {
1816
2185
  const handles = [];
1817
2186
  for (let i = 0; i < fheTypeIds.length; ++i) {
1818
2187
  const hash21 = FhevmHandle._computeInputHash21(hexToBytes(blobHashBytes32Hex), params.aclAddress, params.chainId, i);
1819
- handles.push(new FhevmHandle(hash21, params.chainId, fheTypeIds[i], params.ciphertextVersion, false, i));
2188
+ handles.push(new FhevmHandle({
2189
+ hash21,
2190
+ chainId: params.chainId,
2191
+ fheTypeId: fheTypeIds[i],
2192
+ version: params.ciphertextVersion,
2193
+ computed: false,
2194
+ index: i,
2195
+ }));
1820
2196
  }
1821
2197
  return handles;
1822
2198
  }
2199
+ //////////////////////////////////////////////////////////////////////////////
2200
+ // Static Parsing
2201
+ //////////////////////////////////////////////////////////////////////////////
2202
+ static parse(handle) {
2203
+ if (isBytes(handle)) {
2204
+ return FhevmHandle.fromBytes32(handle);
2205
+ }
2206
+ return FhevmHandle.fromBytes32Hex(handle);
2207
+ }
2208
+ static canParse(handle) {
2209
+ try {
2210
+ FhevmHandle.parse(handle);
2211
+ return true;
2212
+ }
2213
+ catch {
2214
+ return false;
2215
+ }
2216
+ }
2217
+ //////////////////////////////////////////////////////////////////////////////
2218
+ // Static Assertions
2219
+ //////////////////////////////////////////////////////////////////////////////
2220
+ static assertIsHandleHex(handle) {
2221
+ if (typeof handle !== 'string') {
2222
+ throw new FhevmHandleError({
2223
+ message: 'Invalid bytes32 hexadecimal string',
2224
+ });
2225
+ }
2226
+ if (!FhevmHandle.canParse(handle)) {
2227
+ throw new FhevmHandleError({ handle });
2228
+ }
2229
+ }
2230
+ //////////////////////////////////////////////////////////////////////////////
2231
+ // Static Helpers
2232
+ //////////////////////////////////////////////////////////////////////////////
2233
+ static currentCiphertextVersion() {
2234
+ return FhevmHandle.CURRENT_CIPHERTEXT_VERSION;
2235
+ }
2236
+ //////////////////////////////////////////////////////////////////////////////
2237
+ // Private Helpers
2238
+ //////////////////////////////////////////////////////////////////////////////
1823
2239
  /**
1824
2240
  * blobHashBytes32 = keccak256(ciphertextWithZKProof)
1825
2241
  */
1826
2242
  static _computeInputHash21(blobHashBytes32, aclAddress, chainId, index) {
1827
2243
  /*
1828
2244
  https://github.com/zama-ai/fhevm/blob/8ffbd5906ab3d57af178e049930e3fc065c9d4b3/coprocessor/fhevm-engine/zkproof-worker/src/verifier.rs#L431C7-L431C8
1829
-
2245
+
1830
2246
  handle_hash = Bytes("ZK-w_hdl") + blobHash 32 Bytes + index 1 Byte + aclAddress 20 Bytes + chainId 32 bytes
1831
2247
  ===========================================================================================================
1832
2248
 
1833
2249
  const HANDLE_HASH_DOMAIN_SEPARATOR: [u8; 8] = *b"ZK-w_hdl";
1834
-
2250
+
1835
2251
  let mut handle_hash = Keccak256::new();
1836
2252
  handle_hash.update(HANDLE_HASH_DOMAIN_SEPARATOR);
1837
2253
  handle_hash.update(blob_hash);
@@ -1852,27 +2268,12 @@ class FhevmHandle {
1852
2268
  assertIsUint64(chainId);
1853
2269
  const encryptionIndexByte1 = new Uint8Array([index]);
1854
2270
  const aclContractAddressBytes20 = checksummedAddressToBytes20(aclAddress);
1855
- const chainIdBytes32 = uint32ToBytes32(chainId);
2271
+ const chainIdBytes32 = numberToBytes32(chainId);
1856
2272
  const encoder = new TextEncoder();
1857
2273
  const domainSepBytes = encoder.encode(FhevmHandle.HANDLE_HASH_DOMAIN_SEPARATOR);
1858
- return keccak256(concatBytes(domainSepBytes, blobHashBytes32, encryptionIndexByte1, aclContractAddressBytes20, chainIdBytes32));
1859
- }
1860
- toBytes32() {
1861
- assertRelayer((this._index === undefined && this._computed) ||
1862
- (this._index !== undefined && this._index < 255 && !this._computed));
1863
- const chainId32Bytes = uint32ToBytes32(this._chainId);
1864
- const chainId8Bytes = chainId32Bytes.subarray(24, 32);
1865
- const handleHash = hexToBytes(this._hash21);
1866
- const handleBytes32AsBytes = new Uint8Array(32);
1867
- handleBytes32AsBytes.set(handleHash, 0);
1868
- handleBytes32AsBytes[21] = this._index === undefined ? 255 : this._index;
1869
- handleBytes32AsBytes.set(chainId8Bytes, 22);
1870
- handleBytes32AsBytes[30] = this._fheTypeId;
1871
- handleBytes32AsBytes[31] = this._version;
1872
- return handleBytes32AsBytes;
1873
- }
1874
- toBytes32Hex() {
1875
- return bytesToHex(this.toBytes32());
2274
+ const hashBytes32Hex = keccak256(concatBytes(domainSepBytes, blobHashBytes32, encryptionIndexByte1, aclContractAddressBytes20, chainIdBytes32));
2275
+ // Truncate to 21 bytes (0x + 42 hex chars)
2276
+ return hashBytes32Hex.slice(0, 2 + 2 * 21);
1876
2277
  }
1877
2278
  }
1878
2279
 
@@ -1881,6 +2282,89 @@ const getAddress = (value) => getAddress$2(value);
1881
2282
  const currentCiphertextVersion = () => {
1882
2283
  return 0;
1883
2284
  };
2285
+ async function requestCiphertextWithZKProofVerification({ bits, ciphertext, contractAddress, userAddress, aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerProvider, coprocessorSigners, thresholdCoprocessorSigners, extraData, options, }) {
2286
+ const payload = {
2287
+ contractAddress,
2288
+ userAddress,
2289
+ ciphertextWithInputVerification: bytesToHexNo0x(ciphertext),
2290
+ contractChainId: ('0x' + chainId.toString(16)),
2291
+ extraData,
2292
+ };
2293
+ const json = await relayerProvider.fetchPostInputProof(payload, options);
2294
+ if (!isFhevmRelayerInputProofResponse(json)) {
2295
+ throwRelayerInternalError('INPUT_PROOF', json);
2296
+ }
2297
+ const fhevmHandles = FhevmHandle.fromZKProof({
2298
+ ciphertextWithZKProof: ciphertext,
2299
+ chainId,
2300
+ aclAddress: aclContractAddress,
2301
+ ciphertextVersion: currentCiphertextVersion(),
2302
+ fheTypeEncryptionBitwidths: bits,
2303
+ });
2304
+ const handles = fhevmHandles.map((h) => h.toBytes32());
2305
+ const result = json;
2306
+ // Note that the hex strings returned by the relayer do have have the 0x prefix
2307
+ if (result.handles && result.handles.length > 0) {
2308
+ const responseHandles = result.handles.map(hexToBytes);
2309
+ if (handles.length != responseHandles.length) {
2310
+ throw new Error(`Incorrect Handles list sizes: (expected) ${handles.length} != ${responseHandles.length} (received)`);
2311
+ }
2312
+ for (let index = 0; index < handles.length; index += 1) {
2313
+ let handle = handles[index];
2314
+ let responseHandle = responseHandles[index];
2315
+ let expected = bytesToHexNo0x(handle);
2316
+ let current = bytesToHexNo0x(responseHandle);
2317
+ if (expected !== current) {
2318
+ throw new Error(`Incorrect Handle ${index}: (expected) ${expected} != ${current} (received)`);
2319
+ }
2320
+ }
2321
+ }
2322
+ const signatures = result.signatures;
2323
+ // verify signatures for inputs:
2324
+ const domain = {
2325
+ name: 'InputVerification',
2326
+ version: '1',
2327
+ chainId: gatewayChainId,
2328
+ verifyingContract: verifyingContractAddressInputVerification,
2329
+ };
2330
+ const types = {
2331
+ CiphertextVerification: [
2332
+ { name: 'ctHandles', type: 'bytes32[]' },
2333
+ { name: 'userAddress', type: 'address' },
2334
+ { name: 'contractAddress', type: 'address' },
2335
+ { name: 'contractChainId', type: 'uint256' },
2336
+ { name: 'extraData', type: 'bytes' },
2337
+ ],
2338
+ };
2339
+ const recoveredAddresses = signatures.map((signature) => {
2340
+ const sig = signature.startsWith('0x') ? signature : `0x${signature}`;
2341
+ const recoveredAddress = ethers.verifyTypedData(domain, types, {
2342
+ ctHandles: handles,
2343
+ userAddress,
2344
+ contractAddress,
2345
+ contractChainId: chainId,
2346
+ extraData,
2347
+ }, sig);
2348
+ return recoveredAddress;
2349
+ });
2350
+ const thresholdReached = isThresholdReached$1(coprocessorSigners, recoveredAddresses, thresholdCoprocessorSigners);
2351
+ if (!thresholdReached) {
2352
+ throw Error('Coprocessor signers threshold is not reached');
2353
+ }
2354
+ // inputProof is len(list_handles) + numCoprocessorSigners + list_handles + signatureCoprocessorSigners (1+1+NUM_HANDLES*32+65*numSigners)
2355
+ let inputProof = numberToHexNo0x(handles.length);
2356
+ const numSigners = signatures.length;
2357
+ inputProof += numberToHexNo0x(numSigners);
2358
+ const listHandlesStr = handles.map((i) => bytesToHexNo0x(i));
2359
+ listHandlesStr.map((handle) => (inputProof += handle));
2360
+ signatures.map((signature) => (inputProof += signature.slice(2))); // removes the '0x' prefix from the `signature` string
2361
+ // Append the extra data to the input proof
2362
+ inputProof += extraData.slice(2);
2363
+ return {
2364
+ handles,
2365
+ inputProof: hexToBytes(inputProof),
2366
+ };
2367
+ }
1884
2368
  function isThresholdReached$1(coprocessorSigners, recoveredAddresses, threshold) {
1885
2369
  const addressMap = new Map();
1886
2370
  recoveredAddresses.forEach((address, index) => {
@@ -1912,9 +2396,7 @@ function isFhevmRelayerInputProofResponse(json) {
1912
2396
  return (response.signatures.every((s) => typeof s === 'string') &&
1913
2397
  response.handles.every((h) => typeof h === 'string'));
1914
2398
  }
1915
- const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId,
1916
- //relayerUrl: string,
1917
- relayerProvider, tfheCompactPublicKey, publicParams, coprocessorSigners, thresholdCoprocessorSigners, instanceOptions) => (contractAddress, userAddress) => {
2399
+ const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerProvider, tfheCompactPublicKey, publicParams, coprocessorSigners, thresholdCoprocessorSigners, defaultOptions) => (contractAddress, userAddress) => {
1918
2400
  if (!isAddress$1(contractAddress)) {
1919
2401
  throw new Error('Contract address is not a valid address.');
1920
2402
  }
@@ -1966,25 +2448,31 @@ relayerProvider, tfheCompactPublicKey, publicParams, coprocessorSigners, thresho
1966
2448
  getBits() {
1967
2449
  return input.getBits();
1968
2450
  },
2451
+ generateZKProof() {
2452
+ return {
2453
+ chainId,
2454
+ aclContractAddress: aclContractAddress,
2455
+ userAddress: userAddress,
2456
+ contractAddress: contractAddress,
2457
+ ciphertextWithZkProof: input.encrypt(),
2458
+ bits: input.getBits(),
2459
+ };
2460
+ },
1969
2461
  encrypt: async (options) => {
1970
2462
  const extraData = '0x00';
1971
2463
  const bits = input.getBits();
1972
2464
  const ciphertext = input.encrypt();
1973
- //console.log(`ciphertext=${toHexString(ciphertext)}`);
1974
2465
  const payload = {
1975
2466
  contractAddress: getAddress(contractAddress),
1976
2467
  userAddress: getAddress(userAddress),
1977
- ciphertextWithInputVerification: toHexString(ciphertext),
2468
+ ciphertextWithInputVerification: bytesToHexNo0x(ciphertext),
1978
2469
  contractChainId: ('0x' + chainId.toString(16)),
1979
2470
  extraData,
1980
2471
  };
1981
- const json = await relayerProvider.fetchPostInputProof(payload, options ?? instanceOptions);
1982
- // const json = await fetchRelayerJsonRpcPost(
1983
- // 'INPUT_PROOF',
1984
- // `${relayerUrl}/v1/input-proof`,
1985
- // payload,
1986
- // options ?? instanceOptions,
1987
- // );
2472
+ const json = await relayerProvider.fetchPostInputProof(payload, {
2473
+ ...defaultOptions,
2474
+ ...options,
2475
+ });
1988
2476
  if (!isFhevmRelayerInputProofResponse(json)) {
1989
2477
  throwRelayerInternalError('INPUT_PROOF', json);
1990
2478
  }
@@ -1996,7 +2484,6 @@ relayerProvider, tfheCompactPublicKey, publicParams, coprocessorSigners, thresho
1996
2484
  fheTypeEncryptionBitwidths: bits,
1997
2485
  });
1998
2486
  const handles = fhevmHandles.map((h) => h.toBytes32());
1999
- //const result = json.response;
2000
2487
  const result = json;
2001
2488
  // Note that the hex strings returned by the relayer do have have the 0x prefix
2002
2489
  if (result.handles && result.handles.length > 0) {
@@ -2007,8 +2494,8 @@ relayerProvider, tfheCompactPublicKey, publicParams, coprocessorSigners, thresho
2007
2494
  for (let index = 0; index < handles.length; index += 1) {
2008
2495
  let handle = handles[index];
2009
2496
  let responseHandle = responseHandles[index];
2010
- let expected = toHexString(handle);
2011
- let current = toHexString(responseHandle);
2497
+ let expected = bytesToHexNo0x(handle);
2498
+ let current = bytesToHexNo0x(responseHandle);
2012
2499
  if (expected !== current) {
2013
2500
  throw new Error(`Incorrect Handle ${index}: (expected) ${expected} != ${current} (received)`);
2014
2501
  }
@@ -2047,10 +2534,10 @@ relayerProvider, tfheCompactPublicKey, publicParams, coprocessorSigners, thresho
2047
2534
  throw Error('Coprocessor signers threshold is not reached');
2048
2535
  }
2049
2536
  // inputProof is len(list_handles) + numCoprocessorSigners + list_handles + signatureCoprocessorSigners (1+1+NUM_HANDLES*32+65*numSigners)
2050
- let inputProof = numberToHex(handles.length);
2537
+ let inputProof = numberToHexNo0x(handles.length);
2051
2538
  const numSigners = signatures.length;
2052
- inputProof += numberToHex(numSigners);
2053
- const listHandlesStr = handles.map((i) => toHexString(i));
2539
+ inputProof += numberToHexNo0x(numSigners);
2540
+ const listHandlesStr = handles.map((i) => bytesToHexNo0x(i));
2054
2541
  listHandlesStr.map((handle) => (inputProof += handle));
2055
2542
  signatures.map((signature) => (inputProof += signature.slice(2))); // removes the '0x' prefix from the `signature` string
2056
2543
  // Append the extra data to the input proof
@@ -2063,15 +2550,30 @@ relayerProvider, tfheCompactPublicKey, publicParams, coprocessorSigners, thresho
2063
2550
  };
2064
2551
  };
2065
2552
 
2066
- const aclABI = [
2067
- 'function isAllowedForDecryption(bytes32 handle) view returns (bool)',
2068
- ];
2069
- function isThresholdReached(kmsSigners, recoveredAddresses, threshold) {
2070
- const addressMap = new Map();
2071
- recoveredAddresses.forEach((address, index) => {
2072
- if (addressMap.has(address)) {
2073
- const duplicateValue = address;
2074
- throw new Error(`Duplicate KMS signer address found: ${duplicateValue} appears multiple times in recovered addresses`);
2553
+ function ensureError(e) {
2554
+ if (e instanceof Error) {
2555
+ return e;
2556
+ }
2557
+ const message = e.message ?? 'Non-Error value caught in exception handler';
2558
+ const name = e.name ?? 'ErrorWrapper';
2559
+ const cause = e.cause ?? e;
2560
+ const err = new Error(message, { cause });
2561
+ err.name = name;
2562
+ return err;
2563
+ }
2564
+ function assertNever(value, message) {
2565
+ throw new InternalError({ message });
2566
+ }
2567
+
2568
+ const aclABI = [
2569
+ 'function isAllowedForDecryption(bytes32 handle) view returns (bool)',
2570
+ ];
2571
+ function isThresholdReached(kmsSigners, recoveredAddresses, threshold) {
2572
+ const addressMap = new Map();
2573
+ recoveredAddresses.forEach((address, index) => {
2574
+ if (addressMap.has(address)) {
2575
+ const duplicateValue = address;
2576
+ throw new Error(`Duplicate KMS signer address found: ${duplicateValue} appears multiple times in recovered addresses`);
2075
2577
  }
2076
2578
  addressMap.set(address, index);
2077
2579
  });
@@ -2088,7 +2590,7 @@ function abiEncodeClearValues(clearValues) {
2088
2590
  const abiValues = [];
2089
2591
  for (let i = 0; i < handlesBytes32Hex.length; ++i) {
2090
2592
  const handle = handlesBytes32Hex[i];
2091
- const handleType = getHandleType(handle);
2593
+ const handleType = FhevmHandle.parse(handle).fheTypeId;
2092
2594
  let clearTextValue = clearValues[handle];
2093
2595
  if (typeof clearTextValue === 'boolean') {
2094
2596
  clearTextValue = clearTextValue ? '0x01' : '0x00';
@@ -2125,7 +2627,7 @@ function abiEncodeClearValues(clearValues) {
2125
2627
  break;
2126
2628
  }
2127
2629
  default: {
2128
- throw new Error(`Unsupported Fhevm primitive type id: ${handleType}`);
2630
+ assertNever(handleType, `Unsupported Fhevm primitive type id: ${handleType}`);
2129
2631
  }
2130
2632
  }
2131
2633
  }
@@ -2150,50 +2652,38 @@ function buildDecryptionProof(kmsSignatures, extraData) {
2150
2652
  ]);
2151
2653
  return decryptionProof;
2152
2654
  }
2153
- const CiphertextType = {
2154
- 0: 'bool',
2155
- 2: 'uint256',
2156
- 3: 'uint256',
2157
- 4: 'uint256',
2158
- 5: 'uint256',
2159
- 6: 'uint256',
2160
- 7: 'address',
2161
- 8: 'uint256',
2162
- };
2163
2655
  function deserializeClearValues(handles, decryptedResult) {
2164
- let typesList = [];
2656
+ let fheTypeIdList = [];
2165
2657
  for (const handle of handles) {
2166
- const hexPair = handle.slice(-4, -2).toLowerCase();
2167
- const typeDiscriminant = parseInt(hexPair, 16);
2168
- typesList.push(typeDiscriminant);
2658
+ const typeDiscriminant = FhevmHandle.parse(handle).fheTypeId;
2659
+ fheTypeIdList.push(typeDiscriminant);
2169
2660
  }
2170
2661
  const restoredEncoded = '0x' +
2171
2662
  '00'.repeat(32) + // dummy requestID (ignored)
2172
2663
  decryptedResult.slice(2) +
2173
2664
  '00'.repeat(32); // dummy empty bytes[] length (ignored)
2174
- const abiTypes = typesList.map((t) => {
2175
- const abiType = CiphertextType[t]; // all types are valid because this was supposedly checked already inside the `checkEncryptedBits` function
2665
+ const abiTypes = fheTypeIdList.map((t) => {
2666
+ const abiType = solidityPrimitiveTypeNameFromFheTypeId(t); // all types are valid because this was supposedly checked already inside the `checkEncryptedBits` function
2176
2667
  return abiType;
2177
2668
  });
2178
2669
  const coder = new AbiCoder();
2179
2670
  const decoded = coder.decode(['uint256', ...abiTypes, 'bytes[]'], restoredEncoded);
2180
2671
  // strip dummy first/last element
2181
- const rawValues = decoded.slice(1, 1 + typesList.length);
2672
+ const rawValues = decoded.slice(1, 1 + fheTypeIdList.length);
2182
2673
  const results = {};
2183
2674
  handles.forEach((handle, idx) => (results[handle] = rawValues[idx]));
2184
2675
  return results;
2185
2676
  }
2186
- const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, verifyingContractAddress, aclContractAddress,
2187
- //relayerUrl: string,
2188
- relayerProvider, provider, instanceOptions) => async (_handles, options) => {
2677
+ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, verifyingContractAddress, aclContractAddress, relayerProvider, provider, defaultOptions) => async (_handles, options) => {
2189
2678
  const extraData = '0x00';
2190
2679
  const acl = new ethers.Contract(aclContractAddress, aclABI, provider);
2680
+ // This will be replaced by new sanitize classes
2191
2681
  let handles;
2192
2682
  try {
2193
2683
  handles = await Promise.all(_handles.map(async (_handle) => {
2194
2684
  const handle = typeof _handle === 'string'
2195
- ? toHexString(hexToBytes(_handle), true)
2196
- : toHexString(_handle, true);
2685
+ ? bytesToHex(hexToBytes(_handle))
2686
+ : bytesToHex(_handle);
2197
2687
  const isAllowedForDecryption = await acl.isAllowedForDecryption(handle);
2198
2688
  if (!isAllowedForDecryption) {
2199
2689
  throw new Error(`Handle ${handle} is not allowed for public decryption!`);
@@ -2210,13 +2700,10 @@ relayerProvider, provider, instanceOptions) => async (_handles, options) => {
2210
2700
  ciphertextHandles: handles,
2211
2701
  extraData,
2212
2702
  };
2213
- const json = await relayerProvider.fetchPostPublicDecrypt(payloadForRequest, options ?? instanceOptions);
2214
- // const json = await fetchRelayerJsonRpcPost(
2215
- // 'PUBLIC_DECRYPT',
2216
- // `${relayerUrl}/v1/public-decrypt`,
2217
- // payloadForRequest,
2218
- // options ?? instanceOptions,
2219
- // );
2703
+ const json = await relayerProvider.fetchPostPublicDecrypt(payloadForRequest, {
2704
+ ...defaultOptions,
2705
+ ...options,
2706
+ });
2220
2707
  // verify signatures on decryption:
2221
2708
  const domain = {
2222
2709
  name: 'Decryption',
@@ -2354,8 +2841,8 @@ const createEIP712 = (verifyingContract, contractsChainId) => (publicKey, contra
2354
2841
  const generateKeypair = () => {
2355
2842
  const keypair = TKMS.ml_kem_pke_keygen();
2356
2843
  return {
2357
- publicKey: toHexString(TKMS.ml_kem_pke_pk_to_u8vec(TKMS.ml_kem_pke_get_pk(keypair))),
2358
- privateKey: toHexString(TKMS.ml_kem_pke_sk_to_u8vec(keypair)),
2844
+ publicKey: bytesToHexNo0x(TKMS.ml_kem_pke_pk_to_u8vec(TKMS.ml_kem_pke_get_pk(keypair))),
2845
+ privateKey: bytesToHexNo0x(TKMS.ml_kem_pke_sk_to_u8vec(keypair)),
2359
2846
  };
2360
2847
  };
2361
2848
 
@@ -2412,7 +2899,7 @@ class RelayerV1Provider extends AbstractRelayerProvider {
2412
2899
  return 1;
2413
2900
  }
2414
2901
  async fetchGetKeyUrl() {
2415
- const response = await fetchRelayerGet('KEY_URL', this.keyUrl);
2902
+ const response = await fetchRelayerV1Get('KEY_URL', this.keyUrl);
2416
2903
  return response;
2417
2904
  }
2418
2905
  async fetchPostInputProof(payload, options) {
@@ -2430,12 +2917,12 @@ class RelayerV1Provider extends AbstractRelayerProvider {
2430
2917
  }
2431
2918
  }
2432
2919
  */
2433
- const json = await fetchRelayerJsonRpcPost('INPUT_PROOF', this.inputProof, payload, options);
2920
+ const json = await fetchRelayerV1Post('INPUT_PROOF', this.inputProof, payload, options);
2434
2921
  assertIsRelayerInputProofResult(json.response, 'fetchPostInputProof()');
2435
2922
  return json.response;
2436
2923
  }
2437
2924
  async fetchPostPublicDecrypt(payload, options) {
2438
- const json = await fetchRelayerJsonRpcPost('PUBLIC_DECRYPT', this.publicDecrypt, payload, options);
2925
+ const json = await fetchRelayerV1Post('PUBLIC_DECRYPT', this.publicDecrypt, payload, options);
2439
2926
  const response = json.response[0];
2440
2927
  const result = {
2441
2928
  signatures: response.signatures,
@@ -2446,24 +2933,12 @@ class RelayerV1Provider extends AbstractRelayerProvider {
2446
2933
  return result;
2447
2934
  }
2448
2935
  async fetchPostUserDecrypt(payload, options) {
2449
- const json = await fetchRelayerJsonRpcPost('USER_DECRYPT', this.userDecrypt, payload, options);
2936
+ const json = await fetchRelayerV1Post('USER_DECRYPT', this.userDecrypt, payload, options);
2450
2937
  assertIsRelayerUserDecryptResult(json.response, 'RelayerUserDecryptResult()');
2451
2938
  return json.response;
2452
2939
  }
2453
2940
  }
2454
2941
 
2455
- function ensureError(e) {
2456
- if (e instanceof Error) {
2457
- return e;
2458
- }
2459
- const message = e.message ?? 'Non-Error value caught in exception handler';
2460
- const name = e.name ?? 'ErrorWrapper';
2461
- const cause = e.cause ?? e;
2462
- const err = new Error(message, { cause });
2463
- err.name = name;
2464
- return err;
2465
- }
2466
-
2467
2942
  class RelayerV2ProviderError extends RelayerErrorBase {
2468
2943
  _operation;
2469
2944
  constructor(params) {
@@ -2940,22 +3415,6 @@ class RelayerV2RequestInternalError extends RelayerV2RequestErrorBase {
2940
3415
  }
2941
3416
  }
2942
3417
 
2943
- function assertIsRelayerV2ResultQueued(value, name) {
2944
- assertRecordStringProperty(value, 'jobId', name);
2945
- }
2946
-
2947
- /*
2948
- type RelayerV2ResponseQueued = {
2949
- status: "queued";
2950
- result: RelayerV2ResultQueued;
2951
- }
2952
- */
2953
- function assertIsRelayerV2ResponseQueued(value, name) {
2954
- assertRecordStringProperty(value, 'status', name, 'queued');
2955
- assertNonNullableRecordProperty(value, 'result', name);
2956
- assertIsRelayerV2ResultQueued(value.result, `${name}.result`);
2957
- }
2958
-
2959
3418
  class RelayerV2ResponseApiError extends RelayerV2ResponseErrorBase {
2960
3419
  constructor(params) {
2961
3420
  super({
@@ -3017,7 +3476,58 @@ class RelayerV2MaxRetryError extends RelayerV2FetchErrorBase {
3017
3476
  }
3018
3477
  }
3019
3478
 
3479
+ function assertIsRelayerV2PostResultQueued(value, name) {
3480
+ assertRecordStringProperty(value, 'jobId', name);
3481
+ }
3482
+
3483
+ /*
3484
+ {
3485
+ status: 'queued';
3486
+ requestId: string;
3487
+ result: {
3488
+ jobId: string;
3489
+ };
3490
+ }
3491
+ */
3492
+ function assertIsRelayerV2PostResponseQueued(value, name) {
3493
+ assertRecordStringProperty(value, 'status', name, 'queued');
3494
+ assertRecordStringProperty(value, 'requestId', name);
3495
+ assertNonNullableRecordProperty(value, 'result', name);
3496
+ assertIsRelayerV2PostResultQueued(value.result, `${name}.result`);
3497
+ }
3498
+ /*
3499
+ {
3500
+ status: 'queued';
3501
+ requestId: string;
3502
+ }
3503
+ */
3504
+ function assertIsRelayerV2GetResponseQueued(value, name) {
3505
+ assertRecordStringProperty(value, 'status', name, 'queued');
3506
+ assertRecordStringProperty(value, 'requestId', name);
3507
+ }
3508
+
3509
+ class RelayerV2TimeoutError extends RelayerV2RequestErrorBase {
3510
+ constructor(params) {
3511
+ super({
3512
+ ...params,
3513
+ name: 'RelayerV2TimeoutError',
3514
+ message: `Request timed out after ${params.timeoutMs}ms`,
3515
+ });
3516
+ }
3517
+ }
3518
+
3519
+ class RelayerV2AbortError extends RelayerV2RequestErrorBase {
3520
+ constructor(params) {
3521
+ super({
3522
+ ...params,
3523
+ name: 'RelayerV2AbortError',
3524
+ message: `Request aborted`,
3525
+ });
3526
+ }
3527
+ }
3528
+
3020
3529
  class RelayerV2AsyncRequest {
3530
+ _fetchMethod;
3021
3531
  _jobId;
3022
3532
  _jobIdTimestamp;
3023
3533
  _state;
@@ -3032,17 +3542,18 @@ class RelayerV2AsyncRequest {
3032
3542
  _retryAfterTimeoutID;
3033
3543
  _url;
3034
3544
  _payload;
3035
- _fhevmInstanceOptions;
3545
+ _fhevmAuth;
3036
3546
  _retryAfterTimeoutPromiseFuncReject;
3037
3547
  _onProgress;
3038
- _requestMaxDurationInSecs;
3548
+ _requestMaxDurationInMs;
3039
3549
  _requestStartTimestamp;
3040
3550
  _requestGlobalTimeoutID;
3041
3551
  _throwErrorIfNoRetryAfter;
3042
- static DEFAULT_RETRY_AFTER_SECS = 2;
3043
- static DEFAULT_GLOBAL_REQUEST_TIMEOUT_SECS = 60 * 60;
3044
- static MAX_GET_RETRY = 100;
3045
- static MAX_POST_RETRY = 100;
3552
+ static DEFAULT_RETRY_AFTER_MS = 2500;
3553
+ static MINIMUM_RETRY_AFTER_MS = 1000;
3554
+ static DEFAULT_GLOBAL_REQUEST_TIMEOUT_MS = 60 * 60 * 1000; // 1 hour
3555
+ static MAX_GET_RETRY = 60 * 30; // number of default retries in 1 hour (30 retries/min)
3556
+ static MAX_POST_RETRY = RelayerV2AsyncRequest.MAX_GET_RETRY;
3046
3557
  constructor(params) {
3047
3558
  if (params.relayerOperation !== 'INPUT_PROOF' &&
3048
3559
  params.relayerOperation !== 'PUBLIC_DECRYPT' &&
@@ -3059,14 +3570,14 @@ class RelayerV2AsyncRequest {
3059
3570
  this._internalAbortController = new AbortController();
3060
3571
  this._internalAbortSignal = this._internalAbortController.signal;
3061
3572
  this._internalAbortSignal.addEventListener('abort', this._handleInternalSignalAbort);
3062
- this._externalAbortSignal = params.signal;
3573
+ this._externalAbortSignal = params.options?.signal;
3063
3574
  if (this._externalAbortSignal) {
3064
3575
  this._externalAbortSignal.addEventListener('abort', this._handleExternalSignalAbort);
3065
3576
  }
3066
3577
  this._url = params.url;
3067
3578
  this._payload = params.payload;
3068
- this._fhevmInstanceOptions = params.instanceOptions;
3069
- this._onProgress = params.onProgress;
3579
+ this._fhevmAuth = params.options?.auth;
3580
+ this._onProgress = params.options?.onProgress;
3070
3581
  this._state = {
3071
3582
  aborted: false,
3072
3583
  canceled: false,
@@ -3075,6 +3586,7 @@ class RelayerV2AsyncRequest {
3075
3586
  running: false,
3076
3587
  succeeded: false,
3077
3588
  terminated: false,
3589
+ timeout: false,
3078
3590
  };
3079
3591
  this._retryCount = 0;
3080
3592
  this._retryAfterTimeoutID = undefined;
@@ -3082,9 +3594,9 @@ class RelayerV2AsyncRequest {
3082
3594
  this._terminateReason = undefined;
3083
3595
  this._publicAPINoReentrancy = false;
3084
3596
  this._throwErrorIfNoRetryAfter = params.throwErrorIfNoRetryAfter ?? false;
3085
- this._requestMaxDurationInSecs =
3086
- params.timeoutInSeconds ??
3087
- RelayerV2AsyncRequest.DEFAULT_GLOBAL_REQUEST_TIMEOUT_SECS;
3597
+ this._requestMaxDurationInMs =
3598
+ params.options?.timeout ??
3599
+ RelayerV2AsyncRequest.DEFAULT_GLOBAL_REQUEST_TIMEOUT_MS;
3088
3600
  }
3089
3601
  //////////////////////////////////////////////////////////////////////////////
3090
3602
  // Public API: run
@@ -3126,6 +3638,12 @@ class RelayerV2AsyncRequest {
3126
3638
  state: { ...this._state },
3127
3639
  });
3128
3640
  }
3641
+ if (this._state.timeout) {
3642
+ throw new RelayerV2StateError({
3643
+ message: `Relayer.run() failed. Request already timeout.`,
3644
+ state: { ...this._state },
3645
+ });
3646
+ }
3129
3647
  if (this._externalAbortSignal?.aborted === true) {
3130
3648
  throw new RelayerV2StateError({
3131
3649
  message: `Relayer.run() failed. External AbortSignal already aborted (reason:${this._externalAbortSignal?.reason}).`,
@@ -3146,7 +3664,7 @@ class RelayerV2AsyncRequest {
3146
3664
  }
3147
3665
  this._state.running = true;
3148
3666
  this._requestStartTimestamp = Date.now();
3149
- this._setGlobalRequestTimeout(this._requestMaxDurationInSecs * 1000);
3667
+ this._setGlobalRequestTimeout(this._requestMaxDurationInMs);
3150
3668
  try {
3151
3669
  const json = await this._runPostLoop();
3152
3670
  this._state.succeeded = true;
@@ -3217,6 +3735,12 @@ class RelayerV2AsyncRequest {
3217
3735
  get failed() {
3218
3736
  return this._state.failed;
3219
3737
  }
3738
+ get aborted() {
3739
+ return this._state.aborted;
3740
+ }
3741
+ get timeout() {
3742
+ return this._state.timeout;
3743
+ }
3220
3744
  get succeeded() {
3221
3745
  return this._state.succeeded;
3222
3746
  }
@@ -3237,6 +3761,8 @@ class RelayerV2AsyncRequest {
3237
3761
  //////////////////////////////////////////////////////////////////////////////
3238
3762
  // POST : 202 | 400 | 429 | 500 | 503
3239
3763
  async _runPostLoop() {
3764
+ this._assert(this._fetchMethod === undefined, 'this._fetchMethod === undefined');
3765
+ this._fetchMethod = 'POST';
3240
3766
  // No infinite loop!
3241
3767
  let i = 0;
3242
3768
  while (i < RelayerV2AsyncRequest.MAX_POST_RETRY) {
@@ -3261,19 +3787,18 @@ class RelayerV2AsyncRequest {
3261
3787
  // - SyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2) at JSON.parse (<anonymous>)
3262
3788
  const bodyJson = await this._getResponseJson(response);
3263
3789
  try {
3264
- assertIsRelayerV2ResponseQueued(bodyJson, 'body');
3790
+ assertIsRelayerV2PostResponseQueued(bodyJson, 'body');
3265
3791
  }
3266
3792
  catch (cause) {
3267
- this._throwInvalidResponseError({
3793
+ this._throwResponseInvalidBodyError({
3268
3794
  fetchMethod: 'POST',
3269
3795
  status: responseStatus,
3270
3796
  cause: cause,
3271
3797
  elapsed,
3798
+ bodyJson: safeJSONstringify(bodyJson),
3272
3799
  });
3273
3800
  }
3274
- let retry_after_sec = this._getRetryAfterHeaderValueInSecs(response);
3275
- if (retry_after_sec < 1)
3276
- retry_after_sec = 1;
3801
+ const retryAfterMs = this._getRetryAfterHeaderValueInMs(response);
3277
3802
  // Debug: will throw an assert failed error if jobId has already been set
3278
3803
  this._setJobIdOnce(bodyJson.result.jobId);
3279
3804
  // Async onProgress callback
@@ -3286,11 +3811,10 @@ class RelayerV2AsyncRequest {
3286
3811
  jobId: this.jobId,
3287
3812
  operation: this._relayerOperation,
3288
3813
  retryCount: this._retryCount,
3289
- retryAfter: retry_after_sec,
3814
+ retryAfterMs,
3290
3815
  elapsed,
3291
3816
  });
3292
- // Wait if needed (minimum 1s)
3293
- await this._setRetryAfterTimeout(retry_after_sec * 1000);
3817
+ await this._setRetryAfterTimeout(retryAfterMs);
3294
3818
  const json = await this._runGetLoop();
3295
3819
  return json;
3296
3820
  }
@@ -3303,11 +3827,12 @@ class RelayerV2AsyncRequest {
3303
3827
  assertIsRelayerV2ResponseFailedWithError400(bodyJson, 'body');
3304
3828
  }
3305
3829
  catch (cause) {
3306
- this._throwInvalidResponseError({
3830
+ this._throwResponseInvalidBodyError({
3307
3831
  fetchMethod: 'POST',
3308
3832
  status: responseStatus,
3309
3833
  cause: cause,
3310
3834
  elapsed,
3835
+ bodyJson: safeJSONstringify(bodyJson),
3311
3836
  });
3312
3837
  }
3313
3838
  this._throwRelayerV2ResponseApiError({
@@ -3327,29 +3852,28 @@ class RelayerV2AsyncRequest {
3327
3852
  assertIsRelayerV2ResponseFailedWithError429(bodyJson, 'body');
3328
3853
  }
3329
3854
  catch (cause) {
3330
- this._throwInvalidResponseError({
3855
+ this._throwResponseInvalidBodyError({
3331
3856
  fetchMethod: 'POST',
3332
3857
  status: responseStatus,
3333
3858
  cause: cause,
3334
3859
  elapsed,
3860
+ bodyJson: safeJSONstringify(bodyJson),
3335
3861
  });
3336
3862
  }
3337
- let retry_after_sec = this._getRetryAfterHeaderValueInSecs(response);
3338
- if (retry_after_sec < 1)
3339
- retry_after_sec = 1;
3863
+ const retryAfterMs = this._getRetryAfterHeaderValueInMs(response);
3340
3864
  // Async onProgress callback
3341
3865
  this._postAsyncOnProgressCallback({
3342
3866
  type: 'ratelimited',
3343
3867
  url: this._url,
3344
3868
  method: 'POST',
3345
3869
  status: responseStatus,
3346
- retryAfter: retry_after_sec,
3870
+ retryAfterMs,
3347
3871
  retryCount: this._retryCount,
3348
3872
  elapsed,
3349
- message: bodyJson.error.message,
3873
+ relayerApiError: bodyJson.error,
3350
3874
  });
3351
3875
  // Wait if needed (minimum 1s)
3352
- await this._setRetryAfterTimeout(retry_after_sec * 1000);
3876
+ await this._setRetryAfterTimeout(retryAfterMs);
3353
3877
  continue;
3354
3878
  }
3355
3879
  // RelayerV2ResponseFailed
@@ -3362,11 +3886,12 @@ class RelayerV2AsyncRequest {
3362
3886
  assertIsRelayerV2ResponseFailedWithError500(bodyJson, 'body');
3363
3887
  }
3364
3888
  catch (cause) {
3365
- this._throwInvalidResponseError({
3889
+ this._throwResponseInvalidBodyError({
3366
3890
  fetchMethod: 'POST',
3367
3891
  status: responseStatus,
3368
3892
  cause: cause,
3369
3893
  elapsed,
3894
+ bodyJson: safeJSONstringify(bodyJson),
3370
3895
  });
3371
3896
  }
3372
3897
  this._throwRelayerV2ResponseApiError({
@@ -3386,11 +3911,12 @@ class RelayerV2AsyncRequest {
3386
3911
  assertIsRelayerV2ResponseFailedWithError503(bodyJson, 'body');
3387
3912
  }
3388
3913
  catch (cause) {
3389
- this._throwInvalidResponseError({
3914
+ this._throwResponseInvalidBodyError({
3390
3915
  fetchMethod: 'POST',
3391
3916
  status: responseStatus,
3392
3917
  cause: cause,
3393
3918
  elapsed,
3919
+ bodyJson: safeJSONstringify(bodyJson),
3394
3920
  });
3395
3921
  }
3396
3922
  this._throwRelayerV2ResponseApiError({
@@ -3426,8 +3952,10 @@ class RelayerV2AsyncRequest {
3426
3952
  // GET: 200 | 202 | 404 | 500 | 503 | 504
3427
3953
  // GET is not rate-limited, therefore there is not 429 error
3428
3954
  async _runGetLoop() {
3955
+ this._assert(this._fetchMethod === 'POST', "this._fetchMethod === 'POST'");
3429
3956
  this._assert(this._jobId !== undefined, 'this._jobId !== undefined');
3430
3957
  this._assert(this._jobIdTimestamp !== undefined, 'this._jobIdTimestamp !== undefined');
3958
+ this._fetchMethod = 'GET';
3431
3959
  let i = 0;
3432
3960
  while (i < RelayerV2AsyncRequest.MAX_GET_RETRY) {
3433
3961
  ++i;
@@ -3514,6 +4042,7 @@ class RelayerV2AsyncRequest {
3514
4042
  status: responseStatus,
3515
4043
  elapsed,
3516
4044
  cause: cause,
4045
+ bodyJson: safeJSONstringify(bodyJson),
3517
4046
  });
3518
4047
  }
3519
4048
  // RelayerV2ResultPublicDecrypt
@@ -3525,7 +4054,7 @@ class RelayerV2AsyncRequest {
3525
4054
  case 202: {
3526
4055
  const bodyJson = await this._getResponseJson(response);
3527
4056
  try {
3528
- assertIsRelayerV2ResponseQueued(bodyJson, 'body');
4057
+ assertIsRelayerV2GetResponseQueued(bodyJson, 'body');
3529
4058
  }
3530
4059
  catch (cause) {
3531
4060
  this._throwResponseInvalidBodyError({
@@ -3533,11 +4062,10 @@ class RelayerV2AsyncRequest {
3533
4062
  status: responseStatus,
3534
4063
  elapsed,
3535
4064
  cause: cause,
4065
+ bodyJson: safeJSONstringify(bodyJson),
3536
4066
  });
3537
4067
  }
3538
- let retry_after_sec = this._getRetryAfterHeaderValueInSecs(response);
3539
- if (retry_after_sec < 1)
3540
- retry_after_sec = 1;
4068
+ const retryAfterMs = this._getRetryAfterHeaderValueInMs(response);
3541
4069
  // Async onProgress callback
3542
4070
  this._postAsyncOnProgressCallback({
3543
4071
  type: 'queued',
@@ -3547,12 +4075,12 @@ class RelayerV2AsyncRequest {
3547
4075
  requestId: bodyJson.requestId,
3548
4076
  operation: this._relayerOperation,
3549
4077
  jobId: this.jobId,
3550
- retryAfter: retry_after_sec,
4078
+ retryAfterMs,
3551
4079
  retryCount: this._retryCount,
3552
4080
  elapsed,
3553
4081
  });
3554
4082
  // Wait if needed (minimum 1s)
3555
- await this._setRetryAfterTimeout(retry_after_sec * 1000);
4083
+ await this._setRetryAfterTimeout(retryAfterMs);
3556
4084
  continue;
3557
4085
  }
3558
4086
  case 400: {
@@ -3568,6 +4096,7 @@ class RelayerV2AsyncRequest {
3568
4096
  status: responseStatus,
3569
4097
  elapsed,
3570
4098
  cause: cause,
4099
+ bodyJson: safeJSONstringify(bodyJson),
3571
4100
  });
3572
4101
  }
3573
4102
  this._throwRelayerV2ResponseApiError({
@@ -3590,6 +4119,7 @@ class RelayerV2AsyncRequest {
3590
4119
  status: responseStatus,
3591
4120
  elapsed,
3592
4121
  cause: cause,
4122
+ bodyJson: safeJSONstringify(bodyJson),
3593
4123
  });
3594
4124
  }
3595
4125
  this._throwRelayerV2ResponseApiError({
@@ -3614,6 +4144,7 @@ class RelayerV2AsyncRequest {
3614
4144
  status: responseStatus,
3615
4145
  elapsed,
3616
4146
  cause: cause,
4147
+ bodyJson: safeJSONstringify(bodyJson),
3617
4148
  });
3618
4149
  }
3619
4150
  this._throwRelayerV2ResponseApiError({
@@ -3638,6 +4169,7 @@ class RelayerV2AsyncRequest {
3638
4169
  status: responseStatus,
3639
4170
  elapsed,
3640
4171
  cause: cause,
4172
+ bodyJson: safeJSONstringify(bodyJson),
3641
4173
  });
3642
4174
  }
3643
4175
  this._throwRelayerV2ResponseApiError({
@@ -3662,6 +4194,7 @@ class RelayerV2AsyncRequest {
3662
4194
  status: responseStatus,
3663
4195
  elapsed,
3664
4196
  cause: cause,
4197
+ bodyJson: safeJSONstringify(bodyJson),
3665
4198
  });
3666
4199
  }
3667
4200
  this._throwRelayerV2ResponseApiError({
@@ -3699,17 +4232,20 @@ class RelayerV2AsyncRequest {
3699
4232
  return bodyJson;
3700
4233
  }
3701
4234
  //////////////////////////////////////////////////////////////////////////////
3702
- _getRetryAfterHeaderValueInSecs(response) {
4235
+ _getRetryAfterHeaderValueInMs(response) {
3703
4236
  if (!response.headers.has('Retry-After')) {
3704
4237
  if (this._throwErrorIfNoRetryAfter) {
3705
4238
  throw new Error(`Missing 'Retry-After' header key`);
3706
4239
  }
3707
- return RelayerV2AsyncRequest.DEFAULT_RETRY_AFTER_SECS;
4240
+ return RelayerV2AsyncRequest.DEFAULT_RETRY_AFTER_MS;
3708
4241
  }
3709
4242
  try {
3710
4243
  const n = Number.parseInt(response.headers.get('Retry-After'));
3711
4244
  if (isUint(n)) {
3712
- return n;
4245
+ const ms = n * 1000;
4246
+ return ms < RelayerV2AsyncRequest.MINIMUM_RETRY_AFTER_MS
4247
+ ? RelayerV2AsyncRequest.MINIMUM_RETRY_AFTER_MS
4248
+ : ms;
3713
4249
  }
3714
4250
  }
3715
4251
  catch {
@@ -3718,7 +4254,7 @@ class RelayerV2AsyncRequest {
3718
4254
  if (this._throwErrorIfNoRetryAfter) {
3719
4255
  throw new Error(`Invalid 'Retry-After' header key`);
3720
4256
  }
3721
- return RelayerV2AsyncRequest.DEFAULT_RETRY_AFTER_SECS;
4257
+ return RelayerV2AsyncRequest.DEFAULT_RETRY_AFTER_MS;
3722
4258
  }
3723
4259
  //////////////////////////////////////////////////////////////////////////////
3724
4260
  // JobId
@@ -3757,17 +4293,19 @@ class RelayerV2AsyncRequest {
3757
4293
  this._assert(this._jobId === undefined, 'this._jobId === undefined');
3758
4294
  this._assert(!this._state.terminated, '!this._state.terminated');
3759
4295
  this._assert(!this._state.fetching, '!this._state.fetching');
3760
- this._trace('_fetchPost', 'enter');
4296
+ this._trace('_fetchPost', this._url);
3761
4297
  const init = setAuth({
3762
4298
  method: 'POST',
3763
4299
  headers: {
3764
4300
  'Content-Type': 'application/json',
4301
+ 'ZAMA-SDK-VERSION': `${version}`,
4302
+ 'ZAMA-SDK-NAME': `${sdkName}`,
3765
4303
  },
3766
4304
  body: JSON.stringify(this._payload),
3767
4305
  ...(this._internalAbortSignal
3768
4306
  ? { signal: this._internalAbortSignal }
3769
4307
  : {}),
3770
- }, this._fhevmInstanceOptions?.auth);
4308
+ }, this._fhevmAuth);
3771
4309
  this._state.fetching = true;
3772
4310
  let response;
3773
4311
  try {
@@ -3811,9 +4349,16 @@ class RelayerV2AsyncRequest {
3811
4349
  this._assert(!this._state.terminated, '!this._state.terminated');
3812
4350
  this._assert(!this._state.fetching, '!this._state.fetching');
3813
4351
  this._trace('_fetchGet', `jobId=${this.jobId}`);
3814
- const init = this._internalAbortSignal
3815
- ? { signal: this._internalAbortSignal }
3816
- : undefined;
4352
+ const init = {
4353
+ method: 'GET',
4354
+ headers: {
4355
+ 'ZAMA-SDK-VERSION': `${version}`,
4356
+ 'ZAMA-SDK-NAME': `${sdkName}`,
4357
+ },
4358
+ ...(this._internalAbortSignal
4359
+ ? { signal: this._internalAbortSignal }
4360
+ : {}),
4361
+ };
3817
4362
  this._state.fetching = true;
3818
4363
  let response;
3819
4364
  try {
@@ -3887,7 +4432,18 @@ class RelayerV2AsyncRequest {
3887
4432
  if (signal.reason !== 'cancel') {
3888
4433
  this._assert(!this._state.canceled, '!this._state.canceled');
3889
4434
  }
3890
- this._terminate('abort');
4435
+ this._postAsyncOnProgressCallback({
4436
+ type: 'abort',
4437
+ url: this._url,
4438
+ ...(this._jobId ? { jobId: this._jobId } : {}),
4439
+ operation: this._relayerOperation,
4440
+ retryCount: this._retryCount,
4441
+ });
4442
+ this._terminate('abort', new RelayerV2AbortError({
4443
+ operation: this._relayerOperation,
4444
+ jobId: this._jobId,
4445
+ url: this._url,
4446
+ }));
3891
4447
  };
3892
4448
  //////////////////////////////////////////////////////////////////////////////
3893
4449
  // Terminate
@@ -3911,7 +4467,7 @@ class RelayerV2AsyncRequest {
3911
4467
  this._terminateReason = reason;
3912
4468
  this._terminateError = error;
3913
4469
  this._state.terminated = true;
3914
- this._tryClearRetryAfterTimeout();
4470
+ this._tryClearRetryAfterTimeout(error);
3915
4471
  this._tryClearGlobalRequestTimeout();
3916
4472
  const is = this._internalAbortSignal;
3917
4473
  const es = this._externalAbortSignal;
@@ -3933,7 +4489,7 @@ class RelayerV2AsyncRequest {
3933
4489
  // Debug
3934
4490
  this._assert(!this._state.terminated, '!this._state.terminated');
3935
4491
  this._assert(this._retryAfterTimeoutID === undefined, 'this._retryAfterTimeoutID === undefined');
3936
- this._assert(delayMs >= 1000, 'delayMs >= 1000');
4492
+ this._assert(delayMs >= RelayerV2AsyncRequest.MINIMUM_RETRY_AFTER_MS, `delayMs >= ${RelayerV2AsyncRequest.MINIMUM_RETRY_AFTER_MS}`);
3937
4493
  this._trace('_setRetryAfterTimeout', `delayMs=${delayMs}`);
3938
4494
  if (this._retryAfterTimeoutID !== undefined) {
3939
4495
  return Promise.reject(new Error(`retry-after already running.`));
@@ -3953,7 +4509,7 @@ class RelayerV2AsyncRequest {
3953
4509
  return p;
3954
4510
  }
3955
4511
  //////////////////////////////////////////////////////////////////////////////
3956
- _tryClearRetryAfterTimeout() {
4512
+ _tryClearRetryAfterTimeout(error) {
3957
4513
  if (this._retryAfterTimeoutID === undefined) {
3958
4514
  // Debug
3959
4515
  this._assert(this._retryAfterTimeoutPromiseFuncReject === undefined, 'this._retryAfterTimeoutPromiseFuncReject === undefined');
@@ -3964,7 +4520,8 @@ class RelayerV2AsyncRequest {
3964
4520
  this._retryAfterTimeoutID = undefined;
3965
4521
  this._retryAfterTimeoutPromiseFuncReject = undefined;
3966
4522
  clearTimeout(tid);
3967
- reject(new Error('_tryClearRetryAfterTimeout'));
4523
+ // Calling reject will
4524
+ reject(error ?? new Error('_tryClearRetryAfterTimeout'));
3968
4525
  }
3969
4526
  //////////////////////////////////////////////////////////////////////////////
3970
4527
  // Global Request Timeout
@@ -3979,7 +4536,24 @@ class RelayerV2AsyncRequest {
3979
4536
  this._requestGlobalTimeoutID = setTimeout(callback, delayMs);
3980
4537
  }
3981
4538
  _handleGlobalRequestTimeout() {
3982
- this._terminate('timeout');
4539
+ this._state.timeout = true;
4540
+ // Debug state-check guards:
4541
+ this._assert(this instanceof RelayerV2AsyncRequest, `this instanceof RelayerV2AsyncRequest`);
4542
+ this._assert(!this._state.terminated, `!this._state.terminated`);
4543
+ this._assert(!this._state.timeout, '!this._state.timeout');
4544
+ this._postAsyncOnProgressCallback({
4545
+ type: 'timeout',
4546
+ url: this._url,
4547
+ ...(this._jobId ? { jobId: this._jobId } : {}),
4548
+ operation: this._relayerOperation,
4549
+ retryCount: this._retryCount,
4550
+ });
4551
+ this._terminate('timeout', new RelayerV2TimeoutError({
4552
+ operation: this._relayerOperation,
4553
+ jobId: this._jobId,
4554
+ url: this._url,
4555
+ timeoutMs: this._requestMaxDurationInMs,
4556
+ }));
3983
4557
  }
3984
4558
  _tryClearGlobalRequestTimeout() {
3985
4559
  if (this._requestGlobalTimeoutID === undefined) {
@@ -4066,20 +4640,11 @@ class RelayerV2AsyncRequest {
4066
4640
  elapsed,
4067
4641
  });
4068
4642
  }
4069
- _throwInvalidResponseError(params) {
4070
- throw new RelayerV2ResponseInvalidBodyError({
4071
- ...params,
4072
- url: this._url,
4073
- operation: this._relayerOperation,
4074
- state: { ...this._state },
4075
- retryCount: this._retryCount,
4076
- });
4077
- }
4078
4643
  _throwResponseInvalidBodyError(params) {
4079
4644
  throw new RelayerV2ResponseInvalidBodyError({
4080
4645
  ...params,
4081
4646
  url: this._url,
4082
- jobId: this.jobId,
4647
+ jobId: this._jobId,
4083
4648
  operation: this._relayerOperation,
4084
4649
  state: { ...this._state },
4085
4650
  retryCount: this._retryCount,
@@ -4150,7 +4715,7 @@ function assertIsRelayerV2KeyData(value, name) {
4150
4715
  assertRecordStringProperty(value, 'dataId', name);
4151
4716
  assertRecordStringArrayProperty(value, 'urls', name);
4152
4717
  }
4153
- function toRelayerKeyUrlResponse(response) {
4718
+ function toRelayerV1KeyUrlResponse(response) {
4154
4719
  const fheKeyInfoV1 = response.response.fheKeyInfo.map((v2Info) => ({
4155
4720
  fhe_public_key: {
4156
4721
  data_id: v2Info.fhePublicKey.dataId,
@@ -4180,7 +4745,7 @@ class RelayerV2Provider extends AbstractRelayerProvider {
4180
4745
  return 2;
4181
4746
  }
4182
4747
  async fetchGetKeyUrlV2() {
4183
- const response = await fetchRelayerGet('KEY_URL', this.keyUrl);
4748
+ const response = await fetchRelayerV1Get('KEY_URL', this.keyUrl);
4184
4749
  // Relayer error
4185
4750
  try {
4186
4751
  assertIsRelayerV2GetResponseKeyUrl(response, 'fetchGetKeyUrl()');
@@ -4194,39 +4759,36 @@ class RelayerV2Provider extends AbstractRelayerProvider {
4194
4759
  }
4195
4760
  async fetchGetKeyUrl() {
4196
4761
  const response = await this.fetchGetKeyUrlV2();
4197
- return toRelayerKeyUrlResponse(response);
4762
+ return toRelayerV1KeyUrlResponse(response);
4198
4763
  }
4199
- async fetchPostInputProof(payload, instanceOptions, fetchOptions) {
4764
+ async fetchPostInputProof(payload, options) {
4200
4765
  const request = new RelayerV2AsyncRequest({
4201
4766
  relayerOperation: 'INPUT_PROOF',
4202
4767
  url: this.inputProof,
4203
4768
  payload,
4204
- instanceOptions,
4205
- ...fetchOptions,
4769
+ options,
4206
4770
  });
4207
4771
  const result = (await request.run());
4208
4772
  assertIsRelayerInputProofResult(result, 'fetchPostInputProof()');
4209
4773
  return result;
4210
4774
  }
4211
- async fetchPostPublicDecrypt(payload, instanceOptions, fetchOptions) {
4775
+ async fetchPostPublicDecrypt(payload, options) {
4212
4776
  const request = new RelayerV2AsyncRequest({
4213
4777
  relayerOperation: 'PUBLIC_DECRYPT',
4214
4778
  url: this.publicDecrypt,
4215
4779
  payload,
4216
- instanceOptions,
4217
- ...fetchOptions,
4780
+ options,
4218
4781
  });
4219
4782
  const result = await request.run();
4220
4783
  assertIsRelayerPublicDecryptResult(result, 'fetchPostPublicDecrypt()');
4221
4784
  return result;
4222
4785
  }
4223
- async fetchPostUserDecrypt(payload, instanceOptions, fetchOptions) {
4786
+ async fetchPostUserDecrypt(payload, options) {
4224
4787
  const request = new RelayerV2AsyncRequest({
4225
4788
  relayerOperation: 'USER_DECRYPT',
4226
4789
  url: this.userDecrypt,
4227
4790
  payload,
4228
- instanceOptions,
4229
- ...fetchOptions,
4791
+ options,
4230
4792
  });
4231
4793
  const result = (await request.run());
4232
4794
  assertIsRelayerUserDecryptResult(result.result, 'fetchPostUserDecrypt()');
@@ -4234,6 +4796,16 @@ class RelayerV2Provider extends AbstractRelayerProvider {
4234
4796
  }
4235
4797
  }
4236
4798
 
4799
+ class TFHECrsError extends RelayerErrorBase {
4800
+ constructor({ message, cause }) {
4801
+ super({
4802
+ message,
4803
+ name: 'TFHECrsError',
4804
+ ...(cause ? { cause: ensureError(cause) } : {}),
4805
+ });
4806
+ }
4807
+ }
4808
+
4237
4809
  class AbstractRelayerFhevm {
4238
4810
  }
4239
4811
 
@@ -4248,6 +4820,15 @@ class TFHECrs {
4248
4820
  this._bits = params.bits;
4249
4821
  this._srcUrl = params.srcUrl;
4250
4822
  }
4823
+ get id() {
4824
+ return this._id;
4825
+ }
4826
+ get bits() {
4827
+ return this._bits;
4828
+ }
4829
+ get srcUrl() {
4830
+ return this._srcUrl;
4831
+ }
4251
4832
  /*
4252
4833
  {
4253
4834
  id: string,
@@ -4350,20 +4931,58 @@ class TFHECrs {
4350
4931
  return TFHECrs._fromUrl(params);
4351
4932
  }
4352
4933
  else {
4353
- throw new Error('Invalid public key (deserialization failed)');
4934
+ throw new TFHECrsError({
4935
+ message: 'Invalid public key (deserialization failed)',
4936
+ });
4354
4937
  }
4355
4938
  }
4939
+ /*
4940
+ {
4941
+ id: string;
4942
+ data: Uint8Array;
4943
+ bits: number;
4944
+ srcUrl?: string;
4945
+ }
4946
+ */
4356
4947
  static fromBytes(params) {
4357
4948
  try {
4358
4949
  TFHECrs.assertKeyBytesType(params, 'arg');
4359
4950
  return TFHECrs._fromBytes(params);
4360
4951
  }
4361
4952
  catch (e) {
4362
- throw new Error('Invalid public key (deserialization failed)', {
4953
+ throw new TFHECrsError({
4954
+ message: 'Invalid public key (deserialization failed)',
4363
4955
  cause: e,
4364
4956
  });
4365
4957
  }
4366
4958
  }
4959
+ /*
4960
+ {
4961
+ id: string;
4962
+ data: BytesHex;
4963
+ bits: number;
4964
+ srcUrl?: string;
4965
+ }
4966
+ */
4967
+ static fromBytesHex(params) {
4968
+ let data;
4969
+ try {
4970
+ assertRecordStringProperty(params, 'data', 'arg');
4971
+ data = hexToBytesFaster(params.data, true /* strict */);
4972
+ }
4973
+ catch (e) {
4974
+ throw new TFHECrsError({
4975
+ message: 'Invalid public key (deserialization failed)',
4976
+ cause: e,
4977
+ });
4978
+ }
4979
+ return TFHECrs.fromBytes({
4980
+ id: params?.id,
4981
+ bits: params?.bits,
4982
+ srcUrl: params?.srcUrl,
4983
+ data,
4984
+ });
4985
+ }
4367
4986
  static _fromBytes(params) {
4368
4987
  const _params = {
4369
4988
  compactPkeCrs: TFHE.CompactPkeCrs.safe_deserialize(params.data, SERIALIZED_SIZE_LIMIT_CRS),
@@ -4379,7 +4998,50 @@ class TFHECrs {
4379
4998
  return TFHECrs._fromPublicParamsBytes(params);
4380
4999
  }
4381
5000
  catch (e) {
4382
- throw new Error('Invalid public key (deserialization failed)', {
5001
+ throw new TFHECrsError({
5002
+ message: 'Invalid public key (deserialization failed)',
5003
+ cause: e,
5004
+ });
5005
+ }
5006
+ }
5007
+ static fromBitsPublicParamsBytes(bits, params) {
5008
+ if (bits === undefined) {
5009
+ throw new TFHECrsError({ message: 'Missing PublicParams bits format' });
5010
+ }
5011
+ if (bits !== 2048) {
5012
+ throw new TFHECrsError({
5013
+ message: `Unsupported PublicParams bits format '${bits}'`,
5014
+ });
5015
+ }
5016
+ try {
5017
+ assertRecordStringProperty(params, 'publicParamsId', `arg`);
5018
+ assertUint8ArrayProperty(params, 'publicParams', `arg`);
5019
+ return TFHECrs._fromPublicParamsBytes({
5020
+ 2048: params,
5021
+ });
5022
+ }
5023
+ catch (e) {
5024
+ throw new TFHECrsError({
5025
+ message: 'Invalid public key (deserialization failed)',
5026
+ cause: e,
5027
+ });
5028
+ }
5029
+ }
5030
+ static fromPublicParamsBytesHex(params) {
5031
+ try {
5032
+ assertNonNullableRecordProperty(params, '2048', 'arg');
5033
+ assertRecordStringProperty(params['2048'], 'publicParamsId', `arg.2048`);
5034
+ assertRecordStringProperty(params['2048'], 'publicParams', `arg.2048`);
5035
+ return TFHECrs._fromPublicParamsBytes({
5036
+ 2048: {
5037
+ publicParams: hexToBytesFaster(params['2048'].publicParams, true /* strict */),
5038
+ publicParamsId: params['2048'].publicParamsId,
5039
+ },
5040
+ });
5041
+ }
5042
+ catch (e) {
5043
+ throw new TFHECrsError({
5044
+ message: 'Invalid public key (deserialization failed)',
4383
5045
  cause: e,
4384
5046
  });
4385
5047
  }
@@ -4397,7 +5059,8 @@ class TFHECrs {
4397
5059
  return TFHECrs._fromUrl(params);
4398
5060
  }
4399
5061
  catch (e) {
4400
- throw new Error('Impossible to fetch public key: wrong relayer url.', {
5062
+ throw new TFHECrsError({
5063
+ message: 'Impossible to fetch public key: wrong relayer url.',
4401
5064
  cause: e,
4402
5065
  });
4403
5066
  }
@@ -4428,6 +5091,22 @@ class TFHECrs {
4428
5091
  ...(this._srcUrl ? { srcUrl: this._srcUrl } : {}),
4429
5092
  };
4430
5093
  }
5094
+ /*
5095
+ {
5096
+ id: string,
5097
+ bits: number,
5098
+ data: BytesHex,
5099
+ srcUrl?: string
5100
+ }
5101
+ */
5102
+ toBytesHex() {
5103
+ return {
5104
+ data: bytesToHexLarge(this._compactPkeCrs.safe_serialize(SERIALIZED_SIZE_LIMIT_CRS)),
5105
+ id: this._id,
5106
+ bits: this._bits,
5107
+ ...(this._srcUrl ? { srcUrl: this._srcUrl } : {}),
5108
+ };
5109
+ }
4431
5110
  /*
4432
5111
  {
4433
5112
  2048: {
@@ -4436,9 +5115,11 @@ class TFHECrs {
4436
5115
  }
4437
5116
  }
4438
5117
  */
4439
- toPublicParamsWasm() {
5118
+ toPublicParams2048Wasm() {
4440
5119
  if (this._bits !== 2048) {
4441
- throw new Error(`Unsupported PublicParams bits format ${this._bits}`);
5120
+ throw new TFHECrsError({
5121
+ message: `Unsupported PublicParams bits format '2048'`,
5122
+ });
4442
5123
  }
4443
5124
  const pp = {
4444
5125
  2048: {
@@ -4456,9 +5137,11 @@ class TFHECrs {
4456
5137
  }
4457
5138
  }
4458
5139
  */
4459
- toPublicParamsBytes() {
5140
+ toPublicParams2048Bytes() {
4460
5141
  if (this._bits !== 2048) {
4461
- throw new Error(`Unsupported PublicParams bits format ${this._bits}`);
5142
+ throw new TFHECrsError({
5143
+ message: `Unsupported PublicParams bits format '2048'`,
5144
+ });
4462
5145
  }
4463
5146
  const pp = {
4464
5147
  2048: {
@@ -4468,6 +5151,64 @@ class TFHECrs {
4468
5151
  };
4469
5152
  return pp;
4470
5153
  }
5154
+ /*
5155
+ {
5156
+ 2048: {
5157
+ publicParamsId: string,
5158
+ publicParams: BytesHex
5159
+ }
5160
+ }
5161
+ */
5162
+ toPublicParams2048BytesHex() {
5163
+ if (this._bits === undefined) {
5164
+ throw new TFHECrsError({ message: 'Missing PublicParams bits format' });
5165
+ }
5166
+ if (this._bits !== 2048) {
5167
+ throw new TFHECrsError({
5168
+ message: `Unsupported PublicParams bits format '${this._bits}'`,
5169
+ });
5170
+ }
5171
+ const pp = {
5172
+ 2048: {
5173
+ publicParams: this.toBytesHex().data,
5174
+ publicParamsId: this._id,
5175
+ },
5176
+ };
5177
+ return pp;
5178
+ }
5179
+ //////////////////////////////////////////////////////////////////////////////
5180
+ // JSON
5181
+ //////////////////////////////////////////////////////////////////////////////
5182
+ /*
5183
+ {
5184
+ __type: 'TFHECrs',
5185
+ id: string,
5186
+ data: BytesHex,
5187
+ srcUrl?: string
5188
+ }
5189
+ */
5190
+ toJSON() {
5191
+ return {
5192
+ __type: 'TFHECrs',
5193
+ ...this.toBytesHex(),
5194
+ };
5195
+ }
5196
+ static fromJSON(json) {
5197
+ if (json.__type !== 'TFHECrs') {
5198
+ throw new TFHECrsError({ message: 'Invalid TFHECrs JSON.' });
5199
+ }
5200
+ return TFHECrs.fromBytesHex(json);
5201
+ }
5202
+ }
5203
+
5204
+ class TFHEPublicKeyError extends RelayerErrorBase {
5205
+ constructor({ message, cause }) {
5206
+ super({
5207
+ message,
5208
+ name: 'TFHEPublicKeyError',
5209
+ ...(cause ? { cause: ensureError(cause) } : {}),
5210
+ });
5211
+ }
4471
5212
  }
4472
5213
 
4473
5214
  class TFHEPublicKey {
@@ -4479,6 +5220,12 @@ class TFHEPublicKey {
4479
5220
  this._tfheCompactPublicKey = params.tfheCompactPublicKey;
4480
5221
  this._srcUrl = params.srcUrl;
4481
5222
  }
5223
+ get id() {
5224
+ return this._id;
5225
+ }
5226
+ get srcUrl() {
5227
+ return this._srcUrl;
5228
+ }
4482
5229
  /*
4483
5230
  {
4484
5231
  id: string,
@@ -4563,6 +5310,30 @@ class TFHEPublicKey {
4563
5310
  });
4564
5311
  }
4565
5312
  }
5313
+ /*
5314
+ {
5315
+ id: string,
5316
+ data: BytesHex,
5317
+ srcUrl?: string
5318
+ }
5319
+ */
5320
+ static fromBytesHex(params) {
5321
+ let data;
5322
+ try {
5323
+ assertRecordStringProperty(params, 'data', 'arg');
5324
+ data = hexToBytesFaster(params.data, true /* strict */);
5325
+ }
5326
+ catch (e) {
5327
+ throw new Error('Invalid public key (deserialization failed)', {
5328
+ cause: e,
5329
+ });
5330
+ }
5331
+ return TFHEPublicKey.fromBytes({
5332
+ id: params?.id,
5333
+ srcUrl: params?.srcUrl,
5334
+ data,
5335
+ });
5336
+ }
4566
5337
  /*
4567
5338
  {
4568
5339
  id: string,
@@ -4623,6 +5394,20 @@ class TFHEPublicKey {
4623
5394
  ...(this._srcUrl ? { srcUrl: this._srcUrl } : {}),
4624
5395
  };
4625
5396
  }
5397
+ /*
5398
+ {
5399
+ id: string,
5400
+ data: BytesHex,
5401
+ srcUrl?: string
5402
+ }
5403
+ */
5404
+ toBytesHex() {
5405
+ return {
5406
+ data: bytesToHexLarge(this._tfheCompactPublicKey.safe_serialize(SERIALIZED_SIZE_LIMIT_PK)),
5407
+ id: this._id,
5408
+ ...(this._srcUrl ? { srcUrl: this._srcUrl } : {}),
5409
+ };
5410
+ }
4626
5411
  /*
4627
5412
  {
4628
5413
  publicKey: TFHE.TfheCompactPublicKey
@@ -4647,6 +5432,75 @@ class TFHEPublicKey {
4647
5432
  publicKeyId: this._id,
4648
5433
  };
4649
5434
  }
5435
+ /*
5436
+ {
5437
+ publicKey: Uint8Array
5438
+ publicKeyId: string
5439
+ }
5440
+ */
5441
+ toPublicKeyBytesHex() {
5442
+ return {
5443
+ publicKey: this.toBytesHex().data,
5444
+ publicKeyId: this._id,
5445
+ };
5446
+ }
5447
+ static _fromPublicKeyBytes(params) {
5448
+ return TFHEPublicKey._fromBytes({
5449
+ data: params.publicKey,
5450
+ id: params.publicKeyId,
5451
+ srcUrl: params.srcUrl,
5452
+ });
5453
+ }
5454
+ static fromPublicKeyBytesHex(params) {
5455
+ try {
5456
+ assertRecordStringProperty(params, 'publicKey', `arg`);
5457
+ assertRecordStringProperty(params, 'publicKeyId', `arg`);
5458
+ return TFHEPublicKey._fromPublicKeyBytes({
5459
+ publicKey: hexToBytesFaster(params.publicKey, true /* strict */),
5460
+ publicKeyId: params.publicKeyId,
5461
+ });
5462
+ }
5463
+ catch (e) {
5464
+ throw new Error('Invalid public key (deserialization failed)', {
5465
+ cause: e,
5466
+ });
5467
+ }
5468
+ }
5469
+ static fromPublicKeyBytes(params) {
5470
+ try {
5471
+ assertUint8ArrayProperty(params, 'publicKey', `arg`);
5472
+ assertRecordStringProperty(params, 'publicKeyId', `arg`);
5473
+ return TFHEPublicKey._fromPublicKeyBytes(params);
5474
+ }
5475
+ catch (e) {
5476
+ throw new Error('Invalid public key (deserialization failed)', {
5477
+ cause: e,
5478
+ });
5479
+ }
5480
+ }
5481
+ //////////////////////////////////////////////////////////////////////////////
5482
+ // JSON
5483
+ //////////////////////////////////////////////////////////////////////////////
5484
+ /*
5485
+ {
5486
+ __type: 'TFHEPublicKey',
5487
+ id: string,
5488
+ data: BytesHex,
5489
+ srcUrl?: string
5490
+ }
5491
+ */
5492
+ toJSON() {
5493
+ return {
5494
+ __type: 'TFHEPublicKey',
5495
+ ...this.toBytesHex(),
5496
+ };
5497
+ }
5498
+ static fromJSON(json) {
5499
+ if (json.__type !== 'TFHEPublicKey') {
5500
+ throw new TFHEPublicKeyError({ message: 'Invalid TFHEPublicKey JSON.' });
5501
+ }
5502
+ return TFHEPublicKey.fromBytesHex(json);
5503
+ }
4650
5504
  }
4651
5505
 
4652
5506
  //const __KEY_URL_CACHE__: Record<string, RelayerV2PublicKey> = {};
@@ -4722,7 +5576,7 @@ class RelayerV2PublicKey {
4722
5576
  toBytes() {
4723
5577
  return {
4724
5578
  publicKey: this._publicKey.toBytes(),
4725
- publicParams: this._crs2048.toPublicParamsBytes(),
5579
+ publicParams: this._crs2048.toPublicParams2048Bytes(),
4726
5580
  };
4727
5581
  }
4728
5582
  }
@@ -4756,23 +5610,46 @@ class RelayerV2Fhevm extends AbstractRelayerFhevm {
4756
5610
  get relayerProvider() {
4757
5611
  return this._relayerProvider;
4758
5612
  }
5613
+ getPublicKeyInfo() {
5614
+ return {
5615
+ id: this._relayerPublicKey.getTFHEPublicKey().id,
5616
+ srcUrl: this._relayerPublicKey.getTFHEPublicKey().srcUrl,
5617
+ };
5618
+ }
4759
5619
  getPublicKeyBytes() {
4760
5620
  return this._relayerPublicKey.getTFHEPublicKey().toPublicKeyBytes();
4761
5621
  }
4762
5622
  getPublicKeyWasm() {
4763
5623
  return this._relayerPublicKey.getTFHEPublicKey().toPublicKeyWasm();
4764
5624
  }
4765
- getPublicParamsBytes(bits) {
5625
+ getPublicParamsBytesForBits(bits) {
5626
+ if (bits === undefined) {
5627
+ throw new TFHECrsError({ message: `Missing PublicParams bits format` });
5628
+ }
4766
5629
  if (bits !== 2048) {
4767
- throw new Error(`Unsupported PublicParams bits format ${bits}`);
5630
+ throw new TFHECrsError({
5631
+ message: `Unsupported PublicParams bits format '${bits}'`,
5632
+ });
4768
5633
  }
4769
- return this._relayerPublicKey.getTFHECrs().toPublicParamsBytes()['2048'];
5634
+ return this._relayerPublicKey.getTFHECrs().toPublicParams2048Bytes()['2048'];
4770
5635
  }
4771
- getPublicParamsWasm(bits) {
5636
+ getPublicParamsWasmForBits(bits) {
5637
+ if (bits === undefined) {
5638
+ throw new TFHECrsError({ message: `Missing PublicParams bits format` });
5639
+ }
4772
5640
  if (bits !== 2048) {
4773
- throw new Error(`Unsupported PublicParams bits format ${bits}`);
5641
+ throw new TFHECrsError({
5642
+ message: `Unsupported PublicParams bits format '${bits}'`,
5643
+ });
4774
5644
  }
4775
- return this._relayerPublicKey.getTFHECrs().toPublicParamsWasm()['2048'];
5645
+ return this._relayerPublicKey.getTFHECrs().toPublicParams2048Wasm()['2048'];
5646
+ }
5647
+ getPublicParamsInfo() {
5648
+ return {
5649
+ id: this._relayerPublicKey.getTFHECrs().id,
5650
+ bits: this._relayerPublicKey.getTFHECrs().bits,
5651
+ srcUrl: this._relayerPublicKey.getTFHECrs().srcUrl,
5652
+ };
4776
5653
  }
4777
5654
  }
4778
5655
 
@@ -4811,24 +5688,42 @@ class RelayerV1Fhevm extends AbstractRelayerFhevm {
4811
5688
  publicKeyId: this._publicKeyData.publicKeyId,
4812
5689
  };
4813
5690
  }
5691
+ getPublicKeyInfo() {
5692
+ return {
5693
+ id: this._publicKeyData.publicKeyId,
5694
+ };
5695
+ }
5696
+ getPublicParamsInfo() {
5697
+ return {
5698
+ id: this._publicParamsData['2048'].publicParamsId,
5699
+ bits: 2048,
5700
+ };
5701
+ }
4814
5702
  getPublicKeyWasm() {
4815
5703
  return {
4816
5704
  publicKey: this._publicKeyData.publicKey,
4817
5705
  publicKeyId: this._publicKeyData.publicKeyId,
4818
5706
  };
4819
5707
  }
4820
- getPublicParamsBytes(bits) {
5708
+ getPublicParamsBytesForBits(bits) {
5709
+ if (bits === undefined) {
5710
+ throw new Error(`Missing PublicParams bits format`);
5711
+ }
4821
5712
  if (bits !== 2048) {
4822
- throw new Error(`Unsupported PublicParams bits format ${bits}`);
5713
+ throw new Error(`Unsupported PublicParams bits format '${bits}'`);
4823
5714
  }
4824
- return {
5715
+ const res = {
4825
5716
  publicParams: this._publicParamsData['2048'].publicParams.safe_serialize(SERIALIZED_SIZE_LIMIT_CRS),
4826
5717
  publicParamsId: this._publicParamsData['2048'].publicParamsId,
4827
5718
  };
5719
+ return res;
4828
5720
  }
4829
- getPublicParamsWasm(bits) {
5721
+ getPublicParamsWasmForBits(bits) {
5722
+ if (bits === undefined) {
5723
+ throw new Error(`Missing PublicParams bits format`);
5724
+ }
4830
5725
  if (bits !== 2048) {
4831
- throw new Error(`Unsupported PublicParams bits format ${bits}`);
5726
+ throw new Error(`Unsupported PublicParams bits format '${bits}'`);
4832
5727
  }
4833
5728
  return {
4834
5729
  publicParams: this._publicParamsData['2048'].publicParams,
@@ -4849,11 +5744,16 @@ async function createRelayerFhevm(config) {
4849
5744
  publicParams: config.publicParams,
4850
5745
  });
4851
5746
  }
4852
- return RelayerV1Fhevm.fromConfig({
4853
- relayerVersionUrl: resolved.url,
4854
- publicKey: config.publicKey,
4855
- publicParams: config.publicParams,
4856
- });
5747
+ else if (resolved.version === 1) {
5748
+ return RelayerV1Fhevm.fromConfig({
5749
+ relayerVersionUrl: resolved.url,
5750
+ publicKey: config.publicKey,
5751
+ publicParams: config.publicParams,
5752
+ });
5753
+ }
5754
+ else {
5755
+ throw new Error(`Invalid relayerUrl: ${config.relayerUrl}`);
5756
+ }
4857
5757
  }
4858
5758
  function _resolveRelayerUrl(value, defaultVersion) {
4859
5759
  if (!value || typeof value !== 'string') {
@@ -4884,60 +5784,39 @@ function _resolveRelayerUrl(value, defaultVersion) {
4884
5784
  };
4885
5785
  }
4886
5786
 
4887
- /**
4888
- * **FHE Type Mapping for Input Builders**
4889
- * * Maps the **number of encrypted bits** used by a FHEVM primary type
4890
- * to its corresponding **FheTypeId**. This constant is primarily used by
4891
- * `EncryptedInput` and `RelayerEncryptedInput` builders to determine the correct
4892
- * input type and calculate the total required bit-length.
4893
- *
4894
- * **Structure: \{ Encrypted Bit Length: FheTypeId \}**
4895
- *
4896
- * | Bits | FheTypeId | FHE Type Name | Note |
4897
- * | :--- | :-------- | :------------ | :--- |
4898
- * | 2 | 0 | `ebool` | The boolean type. |
4899
- * | (N/A)| 1 | `euint4` | **Deprecated** and omitted from this map. |
4900
- * | 8 | 2 | `euint8` | |
4901
- * | 16 | 3 | `euint16` | |
4902
- * | 32 | 4 | `euint32` | |
4903
- * | 64 | 5 | `euint64` | |
4904
- * | 128 | 6 | `euint128` | |
4905
- * | 160 | 7 | `eaddress` | Used for encrypted Ethereum addresses. |
4906
- * | 256 | 8 | `euint256` | The maximum supported integer size. |
4907
- */
4908
- const ENCRYPTION_TYPES = {
4909
- 2: 0, // ebool (FheTypeId=0) is using 2 encrypted bits
4910
- // euint4 (FheTypeId=1) is deprecated
4911
- 8: 2, // euint8 (FheTypeId=2) is using 8 encrypted bits
4912
- 16: 3, // euint16 (FheTypeId=3) is using 16 encrypted bits
4913
- 32: 4, // euint32 (FheTypeId=4) is using 32 encrypted bits
4914
- 64: 5, // euint64 (FheTypeId=5) is using 64 encrypted bits
4915
- 128: 6, // euint128 (FheTypeId=128) is using 128 encrypted bits
4916
- 160: 7, // eaddress (FheTypeId=7) is using 160 encrypted bits
4917
- 256: 8, // euint256 (FheTypeId=8) is using 256 encrypted bits
5787
+ ////////////////////////////////////////////////////////////////////////////////
5788
+ // MainnetConfig
5789
+ ////////////////////////////////////////////////////////////////////////////////
5790
+ const MainnetConfig = {
5791
+ aclContractAddress: '0xcA2E8f1F656CD25C01F05d0b243Ab1ecd4a8ffb6',
5792
+ kmsContractAddress: '0x77627828a55156b04Ac0DC0eb30467f1a552BB03',
5793
+ inputVerifierContractAddress: '0xCe0FC2e05CFff1B719EFF7169f7D80Af770c8EA2',
5794
+ verifyingContractAddressDecryption: '0x0f6024a97684f7d90ddb0fAAD79cB15F2C888D24',
5795
+ verifyingContractAddressInputVerification: '0xcB1bB072f38bdAF0F328CdEf1Fc6eDa1DF029287',
5796
+ chainId: 1,
5797
+ gatewayChainId: 261131,
5798
+ network: 'https://ethereum-rpc.publicnode.com',
5799
+ relayerUrl: 'https://relayer.mainnet.zama.org',
4918
5800
  };
4919
-
5801
+ Object.freeze(MainnetConfig);
5802
+ ////////////////////////////////////////////////////////////////////////////////
5803
+ // SepoliaConfig
5804
+ ////////////////////////////////////////////////////////////////////////////////
4920
5805
  const SepoliaConfig = {
4921
- // ACL_CONTRACT_ADDRESS (FHEVM Host chain)
4922
5806
  aclContractAddress: '0xf0Ffdc93b7E186bC2f8CB3dAA75D86d1930A433D',
4923
- // KMS_VERIFIER_CONTRACT_ADDRESS (FHEVM Host chain)
4924
5807
  kmsContractAddress: '0xbE0E383937d564D7FF0BC3b46c51f0bF8d5C311A',
4925
- // INPUT_VERIFIER_CONTRACT_ADDRESS (FHEVM Host chain)
4926
5808
  inputVerifierContractAddress: '0xBBC1fFCdc7C316aAAd72E807D9b0272BE8F84DA0',
4927
- // DECRYPTION_ADDRESS (Gateway chain)
4928
5809
  verifyingContractAddressDecryption: '0x5D8BD78e2ea6bbE41f26dFe9fdaEAa349e077478',
4929
- // INPUT_VERIFICATION_ADDRESS (Gateway chain)
4930
5810
  verifyingContractAddressInputVerification: '0x483b9dE06E4E4C7D35CCf5837A1668487406D955',
4931
- // FHEVM Host chain id
4932
5811
  chainId: 11155111,
4933
- // Gateway chain id
4934
5812
  gatewayChainId: 10901,
4935
- // Optional RPC provider to host chain
4936
5813
  network: 'https://ethereum-sepolia-rpc.publicnode.com',
4937
- // Relayer URL
4938
5814
  relayerUrl: 'https://relayer.testnet.zama.org',
4939
5815
  };
4940
5816
  Object.freeze(SepoliaConfig);
5817
+ ////////////////////////////////////////////////////////////////////////////////
5818
+ // createInstance
5819
+ ////////////////////////////////////////////////////////////////////////////////
4941
5820
  const createInstance = async (config) => {
4942
5821
  const { verifyingContractAddressDecryption, verifyingContractAddressInputVerification, publicKey, inputVerifierContractAddress, kmsContractAddress, aclContractAddress, gatewayChainId, auth, } = config;
4943
5822
  if (!isChecksummedAddress(aclContractAddress)) {
@@ -4969,29 +5848,33 @@ const createInstance = async (config) => {
4969
5848
  defaultRelayerVersion: 1,
4970
5849
  });
4971
5850
  const chainId = await getChainId(provider, config);
4972
- // const relayerVersionUrl = `${config.relayerUrl!}/v1`;
4973
- // const publicKeyData = await getTfheCompactPublicKey({
4974
- // relayerVersionUrl: relayerFhevm.relayerVersionUrl,
4975
- // publicKey: config.publicKey,
4976
- // });
4977
- //const aaa = relayerFhevm.getPublicKey();
4978
- // const publicParamsData = await getPublicParams({
4979
- // relayerVersionUrl,
4980
- // publicParams: config.publicParams,
4981
- // });
4982
5851
  const kmsSigners = await getKMSSigners(provider, kmsContractAddress);
4983
5852
  const thresholdKMSSigners = await getKMSSignersThreshold(provider, kmsContractAddress);
4984
5853
  const coprocessorSigners = await getCoprocessorSigners(provider, inputVerifierContractAddress);
4985
5854
  const thresholdCoprocessorSigners = await getCoprocessorSignersThreshold(provider, inputVerifierContractAddress);
4986
5855
  return {
4987
- createEncryptedInput: createRelayerEncryptedInput(aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId,
4988
- //cleanURL(config.relayerUrl),
4989
- //relayerFhevm.relayerVersionUrl,
4990
- relayerFhevm.relayerProvider,
4991
- //publicKeyData.publicKey,
4992
- relayerFhevm.getPublicKeyWasm().publicKey,
4993
- //publicParamsData,
4994
- { 2048: relayerFhevm.getPublicParamsWasm(2048) }, coprocessorSigners, thresholdCoprocessorSigners),
5856
+ createEncryptedInput: createRelayerEncryptedInput(aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerFhevm.relayerProvider, relayerFhevm.getPublicKeyWasm().publicKey, { 2048: relayerFhevm.getPublicParamsWasmForBits(2048) }, coprocessorSigners, thresholdCoprocessorSigners, auth && { auth }),
5857
+ requestZKProofVerification: (zkProof, options) => {
5858
+ if (zkProof.chainId !== chainId ||
5859
+ zkProof.aclContractAddress !== aclContractAddress) {
5860
+ throw new Error('Invalid ZKProof');
5861
+ }
5862
+ return requestCiphertextWithZKProofVerification({
5863
+ ciphertext: zkProof.ciphertextWithZkProof,
5864
+ aclContractAddress: aclContractAddress,
5865
+ contractAddress: zkProof.contractAddress,
5866
+ userAddress: zkProof.userAddress,
5867
+ chainId,
5868
+ gatewayChainId,
5869
+ bits: zkProof.bits,
5870
+ coprocessorSigners,
5871
+ extraData: '0x00',
5872
+ thresholdCoprocessorSigners,
5873
+ relayerProvider: relayerFhevm.relayerProvider,
5874
+ verifyingContractAddressInputVerification: verifyingContractAddressInputVerification,
5875
+ options,
5876
+ });
5877
+ },
4995
5878
  generateKeypair,
4996
5879
  createEIP712: createEIP712(verifyingContractAddressDecryption, chainId),
4997
5880
  publicDecrypt: publicDecryptRequest(kmsSigners, thresholdKMSSigners, gatewayChainId, verifyingContractAddressDecryption, aclContractAddress,
@@ -5001,7 +5884,7 @@ const createInstance = async (config) => {
5001
5884
  //cleanURL(config.relayerUrl),
5002
5885
  relayerFhevm.relayerProvider, provider, auth && { auth }),
5003
5886
  getPublicKey: () => relayerFhevm.getPublicKeyBytes(),
5004
- getPublicParams: (bits) => relayerFhevm.getPublicParamsBytes(bits),
5887
+ getPublicParams: (bits) => relayerFhevm.getPublicParamsBytesForBits(bits),
5005
5888
  // getPublicKey: () =>
5006
5889
  // publicKeyData.publicKey
5007
5890
  // ? {
@@ -5039,10 +5922,10 @@ const createTfheKeypair = () => {
5039
5922
  };
5040
5923
  const createTfhePublicKey = () => {
5041
5924
  const { publicKey } = createTfheKeypair();
5042
- return toHexString(publicKey.serialize());
5925
+ return bytesToHexNo0x(publicKey.serialize());
5043
5926
  };
5044
5927
 
5045
5928
  global.TFHE = TFHEPkg;
5046
5929
  global.TKMS = TKMSPkg;
5047
5930
 
5048
- export { ENCRYPTION_TYPES, SepoliaConfig, createEIP712, createInstance, createTfheKeypair, createTfhePublicKey, generateKeypair, getErrorCauseCode, getErrorCauseStatus };
5931
+ export { MainnetConfig, SepoliaConfig, createEIP712, createInstance, createTfheKeypair, createTfhePublicKey, generateKeypair, getErrorCauseCode, getErrorCauseStatus };