@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.cjs CHANGED
@@ -28,31 +28,9 @@ const SERIALIZED_SIZE_LIMIT_CIPHERTEXT = BigInt(1024 * 1024 * 512);
28
28
  const SERIALIZED_SIZE_LIMIT_PK = BigInt(1024 * 1024 * 512);
29
29
  const SERIALIZED_SIZE_LIMIT_CRS = BigInt(1024 * 1024 * 512);
30
30
 
31
- function setAuth(init, auth) {
32
- if (auth) {
33
- switch (auth.__type) {
34
- case 'BearerToken':
35
- init.headers['Authorization'] =
36
- `Bearer ${auth.token}`;
37
- break;
38
- case 'ApiKeyHeader':
39
- init.headers[auth.header || 'x-api-key'] =
40
- auth.value;
41
- break;
42
- case 'ApiKeyCookie':
43
- if (typeof window !== 'undefined') {
44
- document.cookie = `${auth.cookie || 'x-api-key'}=${auth.value}; path=/; SameSite=Lax; Secure; HttpOnly;`;
45
- init.credentials = 'include';
46
- }
47
- else {
48
- let cookie = `${auth.cookie || 'x-api-key'}=${auth.value};`;
49
- init.headers['Cookie'] = cookie;
50
- }
51
- break;
52
- }
53
- }
54
- return init;
55
- }
31
+ // This file is auto-generated
32
+ const version = '0.4.0-alpha.2';
33
+ const sdkName = '@zama-fhe/relayer-sdk';
56
34
 
57
35
  function getErrorCause(e) {
58
36
  if (e instanceof Error && typeof e.cause === 'object' && e.cause !== null) {
@@ -234,7 +212,39 @@ function throwRelayerUnknownError(operation, error, message) {
234
212
  });
235
213
  }
236
214
 
237
- ////////////////////////////////////////////////////////////////////////////////
215
+ /**
216
+ * Set the authentication method for the request. The default is no authentication.
217
+ * It supports:
218
+ * - Bearer Token
219
+ * - Custom header
220
+ * - Custom cookie
221
+ */
222
+ function setAuth(init, auth) {
223
+ if (auth) {
224
+ switch (auth.__type) {
225
+ case 'BearerToken':
226
+ init.headers['Authorization'] =
227
+ `Bearer ${auth.token}`;
228
+ break;
229
+ case 'ApiKeyHeader':
230
+ init.headers[auth.header || 'x-api-key'] =
231
+ auth.value;
232
+ break;
233
+ case 'ApiKeyCookie':
234
+ if (typeof window !== 'undefined') {
235
+ document.cookie = `${auth.cookie || 'x-api-key'}=${auth.value}; path=/; SameSite=Lax; Secure; HttpOnly;`;
236
+ init.credentials = 'include';
237
+ }
238
+ else {
239
+ let cookie = `${auth.cookie || 'x-api-key'}=${auth.value};`;
240
+ init.headers['Cookie'] = cookie;
241
+ }
242
+ break;
243
+ }
244
+ }
245
+ return init;
246
+ }
247
+
238
248
  function assertIsRelayerV1FetchResponseJson(json) {
239
249
  if (!json || typeof json !== 'object') {
240
250
  throw new Error('Unexpected response JSON.');
@@ -245,11 +255,13 @@ function assertIsRelayerV1FetchResponseJson(json) {
245
255
  throw new Error("Unexpected response JSON format: missing 'response' property.");
246
256
  }
247
257
  }
248
- async function fetchRelayerJsonRpcPost(relayerOperation, url, payload, options) {
258
+ async function fetchRelayerV1Post(relayerOperation, url, payload, options) {
249
259
  const init = setAuth({
250
260
  method: 'POST',
251
261
  headers: {
252
262
  'Content-Type': 'application/json',
263
+ 'ZAMA-SDK-VERSION': `${version}`,
264
+ 'ZAMA-SDK-NAME': `${sdkName}`,
253
265
  },
254
266
  body: JSON.stringify(payload),
255
267
  }, options?.auth);
@@ -280,14 +292,20 @@ async function fetchRelayerJsonRpcPost(relayerOperation, url, payload, options)
280
292
  }
281
293
  return json;
282
294
  }
283
- async function fetchRelayerGet(relayerOperation, url) {
295
+ async function fetchRelayerV1Get(relayerOperation, url) {
296
+ const init = {
297
+ method: 'GET',
298
+ headers: {
299
+ 'ZAMA-SDK-VERSION': `${version}`,
300
+ 'ZAMA-SDK-NAME': `${sdkName}`,
301
+ },
302
+ };
284
303
  let response;
285
304
  let json;
286
305
  try {
287
- response = await fetch(url);
306
+ response = await fetch(url, init);
288
307
  }
289
308
  catch (e) {
290
- console.log(e);
291
309
  throwRelayerUnknownError(relayerOperation, e);
292
310
  }
293
311
  if (!response.ok) {
@@ -315,7 +333,7 @@ const getKeysFromRelayer = async (versionUrl, publicKeyId) => {
315
333
  if (keyurlCache[versionUrl]) {
316
334
  return keyurlCache[versionUrl];
317
335
  }
318
- const data = await fetchRelayerGet('KEY_URL', `${versionUrl}/keyurl`);
336
+ const data = await fetchRelayerV1Get('KEY_URL', `${versionUrl}/keyurl`);
319
337
  try {
320
338
  let pubKeyUrl;
321
339
  // If no publicKeyId is provided, use the first one
@@ -404,7 +422,7 @@ class RelayerErrorBase extends Error {
404
422
  _docsPath;
405
423
  _docsUrl;
406
424
  _version;
407
- static VERSION = '0.3.0-6';
425
+ static VERSION = version;
408
426
  static DEFAULT_DOCS_BASE_URL = 'https//docs.zama.org';
409
427
  static FULL_VERSION = `@zama-fhe/relayer-sdk@${RelayerErrorBase.VERSION}`;
410
428
  constructor(params) {
@@ -813,6 +831,14 @@ function assertRecordStringArrayProperty(o, property, objName) {
813
831
  }
814
832
  }
815
833
  }
834
+ function safeJSONstringify(o, space) {
835
+ try {
836
+ return JSON.stringify(o, (_, v) => (typeof v === 'bigint' ? v.toString() : v), space);
837
+ }
838
+ catch {
839
+ return '';
840
+ }
841
+ }
816
842
 
817
843
  const abiKmsVerifier = [
818
844
  'function getKmsSigners() view returns (address[])',
@@ -912,6 +938,7 @@ const getCoprocessorSignersThreshold = async (provider, inputVerifierContractAdd
912
938
  return Number(threshold); // threshold is always supposed to fit in a number
913
939
  };
914
940
 
941
+ // This file contains common utilities for both user and public decryption requests
915
942
  const NumEncryptedBits = {
916
943
  0: 2, // ebool
917
944
  2: 8, // euint8
@@ -922,17 +949,17 @@ const NumEncryptedBits = {
922
949
  7: 160, // eaddress
923
950
  8: 256, // euint256
924
951
  };
925
- function getHandleType(handle) {
926
- if (handle.length !== 66) {
927
- throw new Error(`Handle ${handle} is not of valid length`);
928
- }
929
- const hexPair = handle.slice(-4, -2).toLowerCase();
930
- const typeDiscriminant = parseInt(hexPair, 16);
931
- if (!(typeDiscriminant in NumEncryptedBits)) {
932
- throw new Error(`Handle ${handle} is not of valid type`);
933
- }
934
- return typeDiscriminant;
935
- }
952
+ // export function getHandleType(handle: `0x${string}`): number {
953
+ // if (handle.length !== 66) {
954
+ // throw new Error(`Handle ${handle} is not of valid length`);
955
+ // }
956
+ // const hexPair = handle.slice(-4, -2).toLowerCase();
957
+ // const typeDiscriminant = parseInt(hexPair, 16);
958
+ // if (!(typeDiscriminant in NumEncryptedBits)) {
959
+ // throw new Error(`Handle ${handle} is not of valid type`);
960
+ // }
961
+ // return typeDiscriminant;
962
+ // }
936
963
  function checkEncryptedBits(handles) {
937
964
  let total = 0;
938
965
  for (const handle of handles) {
@@ -990,7 +1017,7 @@ function isBytes(value, bytewidth) {
990
1017
  if (!(value instanceof Uint8Array)) {
991
1018
  return false;
992
1019
  }
993
- return value.length === bytewidth ;
1020
+ return bytewidth ? value.length === bytewidth : true;
994
1021
  }
995
1022
  function isBytesHex(value, bytewidth) {
996
1023
  if (!is0x(value)) {
@@ -1223,6 +1250,54 @@ function assertUint8ArrayProperty(o, property, objName) {
1223
1250
  });
1224
1251
  }
1225
1252
  }
1253
+ ////////////////////////////////////////////////////////////////////////////////
1254
+ // Hex
1255
+ ////////////////////////////////////////////////////////////////////////////////
1256
+ const HEX_CHARS = {
1257
+ '0': 0,
1258
+ '1': 1,
1259
+ '2': 2,
1260
+ '3': 3,
1261
+ '4': 4,
1262
+ '5': 5,
1263
+ '6': 6,
1264
+ '7': 7,
1265
+ '8': 8,
1266
+ '9': 9,
1267
+ a: 10,
1268
+ b: 11,
1269
+ c: 12,
1270
+ d: 13,
1271
+ e: 14,
1272
+ f: 15,
1273
+ A: 10,
1274
+ B: 11,
1275
+ C: 12,
1276
+ D: 13,
1277
+ E: 14,
1278
+ F: 15,
1279
+ };
1280
+ Object.freeze(HEX_CHARS);
1281
+ const HEX_BYTES = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
1282
+ Object.freeze(HEX_BYTES);
1283
+ const HEX_CHARS_CODES = new Uint8Array([
1284
+ 48,
1285
+ 49,
1286
+ 50,
1287
+ 51,
1288
+ 52,
1289
+ 53,
1290
+ 54,
1291
+ 55,
1292
+ 56,
1293
+ 57, // '0'-'9'
1294
+ 97,
1295
+ 98,
1296
+ 99,
1297
+ 100,
1298
+ 101,
1299
+ 102, // 'a'-'f'
1300
+ ]);
1226
1301
  /**
1227
1302
  * Convert a Uint8Array to a hex string (without 0x prefix).
1228
1303
  */
@@ -1242,15 +1317,49 @@ function bytesToHexNo0x(bytes) {
1242
1317
  function bytesToHex(bytes) {
1243
1318
  return `0x${bytesToHexNo0x(bytes)}`;
1244
1319
  }
1320
+ function bytesToHexLarge(bytes) {
1321
+ const out = new Uint8Array(2 + bytes.length * 2);
1322
+ out[0] = 48; // '0'
1323
+ out[1] = 120; // 'x'
1324
+ for (let i = 0; i < bytes.length; i++) {
1325
+ const j = 2 + i * 2;
1326
+ out[j] = HEX_CHARS_CODES[bytes[i] >> 4];
1327
+ out[j + 1] = HEX_CHARS_CODES[bytes[i] & 0xf];
1328
+ }
1329
+ return new TextDecoder().decode(out);
1330
+ }
1245
1331
  /**
1246
1332
  * Convert a hex string prefixed by 0x or not to a Uint8Array
1333
+ * Any invalid byte string is converted to 0
1334
+ * "0xzzff" = [0, 255]
1335
+ * "0xzfff" = [0, 255]
1247
1336
  */
1248
1337
  function hexToBytes(hexString) {
1338
+ if (hexString.length % 2 !== 0) {
1339
+ throw new Error('Invalid hex string: odd length');
1340
+ }
1249
1341
  const arr = hexString.replace(/^(0x)/, '').match(/.{1,2}/g);
1250
1342
  if (!arr)
1251
1343
  return new Uint8Array();
1252
1344
  return Uint8Array.from(arr.map((byte) => parseInt(byte, 16)));
1253
1345
  }
1346
+ function hexToBytesFaster(hexString, strict = false) {
1347
+ const offset = hexString[0] === '0' && hexString[1] === 'x' ? 2 : 0;
1348
+ const len = hexString.length - offset;
1349
+ if (len % 2 !== 0) {
1350
+ throw new Error('Invalid hex string: odd length');
1351
+ }
1352
+ const bytes = new Uint8Array(len / 2);
1353
+ for (let i = 0; i < bytes.length; i++) {
1354
+ const hi = HEX_CHARS[hexString[offset + i * 2]];
1355
+ const lo = HEX_CHARS[hexString[offset + i * 2 + 1]];
1356
+ if ((hi === undefined || lo === undefined) && strict) {
1357
+ throw new Error(`Invalid hex character at position ${offset + i * 2}`);
1358
+ }
1359
+ bytes[i] = (hi << 4) | lo;
1360
+ }
1361
+ return bytes;
1362
+ }
1254
1363
  /**
1255
1364
  * Convert a Uint8Array to a bigint
1256
1365
  */
@@ -1264,9 +1373,6 @@ function bytesToBigInt(byteArray) {
1264
1373
  }
1265
1374
  return result;
1266
1375
  }
1267
- function toHexString(bytes, with0x = false) {
1268
- return `${with0x ? '0x' : ''}${bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '')}`;
1269
- }
1270
1376
  async function fetchBytes(url) {
1271
1377
  const response = await fetch(url);
1272
1378
  if (!response.ok) {
@@ -1342,9 +1448,7 @@ function checkDeadlineValidity(startTimestamp, durationDays) {
1342
1448
  throw Error('User decrypt request has expired');
1343
1449
  }
1344
1450
  }
1345
- const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContractAddress, aclContractAddress,
1346
- //relayerUrl: string,
1347
- relayerProvider, provider, instanceOptions) => async (_handles, privateKey, publicKey, signature, contractAddresses, userAddress, startTimestamp, durationDays, options) => {
1451
+ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContractAddress, aclContractAddress, relayerProvider, provider, defaultOptions) => async (_handles, privateKey, publicKey, signature, contractAddresses, userAddress, startTimestamp, durationDays, options) => {
1348
1452
  const extraData = '0x00';
1349
1453
  let pubKey;
1350
1454
  let privKey;
@@ -1358,16 +1462,16 @@ relayerProvider, provider, instanceOptions) => async (_handles, privateKey, publ
1358
1462
  // Casting handles if string
1359
1463
  const signatureSanitized = signature.replace(/^(0x)/, '');
1360
1464
  const publicKeySanitized = publicKey.replace(/^(0x)/, '');
1361
- const handles = _handles.map((h) => ({
1465
+ const handleContractPairs = _handles.map((h) => ({
1362
1466
  handle: typeof h.handle === 'string'
1363
- ? toHexString(hexToBytes(h.handle), true)
1364
- : toHexString(h.handle, true),
1467
+ ? bytesToHex(hexToBytes(h.handle))
1468
+ : bytesToHex(h.handle),
1365
1469
  contractAddress: getAddress$1(h.contractAddress),
1366
1470
  }));
1367
- checkEncryptedBits(handles.map((h) => h.handle));
1471
+ checkEncryptedBits(handleContractPairs.map((h) => h.handle));
1368
1472
  checkDeadlineValidity(BigInt(startTimestamp), BigInt(durationDays));
1369
- const acl = new ethers.ethers.Contract(aclContractAddress, aclABI$1, provider);
1370
- const verifications = handles.map(async ({ handle, contractAddress }) => {
1473
+ const acl = new ethers.Contract(aclContractAddress, aclABI$1, provider);
1474
+ const verifications = handleContractPairs.map(async ({ handle, contractAddress }) => {
1371
1475
  const userAllowed = await acl.persistAllowed(handle, userAddress);
1372
1476
  const contractAllowed = await acl.persistAllowed(handle, contractAddress);
1373
1477
  if (!userAllowed) {
@@ -1391,7 +1495,7 @@ relayerProvider, provider, instanceOptions) => async (_handles, privateKey, publ
1391
1495
  throw e;
1392
1496
  });
1393
1497
  const payloadForRequest = {
1394
- handleContractPairs: handles,
1498
+ handleContractPairs,
1395
1499
  requestValidity: {
1396
1500
  startTimestamp: startTimestamp.toString(), // Convert to string
1397
1501
  durationDays: durationDays.toString(), // Convert to string
@@ -1403,13 +1507,10 @@ relayerProvider, provider, instanceOptions) => async (_handles, privateKey, publ
1403
1507
  publicKey: publicKeySanitized,
1404
1508
  extraData,
1405
1509
  };
1406
- const json = await relayerProvider.fetchPostUserDecrypt(payloadForRequest, options ?? instanceOptions);
1407
- // const json = await fetchRelayerJsonRpcPost(
1408
- // 'USER_DECRYPT',
1409
- // `${relayerUrl}/v1/user-decrypt`,
1410
- // payloadForRequest,
1411
- // instanceOptions ?? options,
1412
- // );
1510
+ const json = await relayerProvider.fetchPostUserDecrypt(payloadForRequest, {
1511
+ ...defaultOptions,
1512
+ ...options,
1513
+ });
1413
1514
  // assume the KMS Signers have the correct order
1414
1515
  let indexedKmsSigners = kmsSigners.map((signer, index) => {
1415
1516
  return TKMS.new_server_id_addr(index + 1, signer);
@@ -1431,13 +1532,13 @@ relayerProvider, provider, instanceOptions) => async (_handles, privateKey, publ
1431
1532
  signature: signatureSanitized,
1432
1533
  client_address: userAddress,
1433
1534
  enc_key: publicKeySanitized,
1434
- ciphertext_handles: handles.map((h) => h.handle.replace(/^0x/, '')),
1535
+ ciphertext_handles: handleContractPairs.map((h) => h.handle.replace(/^0x/, '')),
1435
1536
  eip712_verifying_contract: verifyingContractAddress,
1436
1537
  };
1437
1538
  const decryption = TKMS.process_user_decryption_resp_from_js(client, payloadForVerification, eip712Domain, json, //json.response,
1438
1539
  pubKey, privKey, true);
1439
1540
  const listBigIntDecryptions = decryption.map((d) => bytesToBigInt(d.bytes));
1440
- const results = buildUserDecryptResults(handles.map((h) => h.handle), listBigIntDecryptions);
1541
+ const results = buildUserDecryptResults(handleContractPairs.map((h) => h.handle), listBigIntDecryptions);
1441
1542
  return results;
1442
1543
  }
1443
1544
  catch (e) {
@@ -1580,9 +1681,8 @@ const createEncryptedInput = ({ aclContractAddress, chainId, tfheCompactPublicKe
1580
1681
 
1581
1682
  const MAX_UINT64 = BigInt('18446744073709551615'); // 2^64 - 1
1582
1683
  BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
1583
- const MAX_UINT32 = 0xffffffff;
1584
1684
  const MAX_UINT8 = 0xff;
1585
- function numberToHex(num) {
1685
+ function numberToHexNo0x(num) {
1586
1686
  let hex = num.toString(16);
1587
1687
  return hex.length % 2 ? '0' + hex : hex;
1588
1688
  }
@@ -1616,25 +1716,19 @@ function isUint8(value) {
1616
1716
  }
1617
1717
  return value <= MAX_UINT8;
1618
1718
  }
1619
- function isUint32(value) {
1620
- if (!isUint(value)) {
1621
- return false;
1622
- }
1623
- return value <= MAX_UINT32;
1624
- }
1625
1719
  function isUint64(value) {
1626
1720
  if (!isUint(value)) {
1627
1721
  return false;
1628
1722
  }
1629
1723
  return value <= MAX_UINT64;
1630
1724
  }
1631
- function uint32ToBytes32(uint32) {
1632
- if (!isUint32(uint32)) {
1633
- throw new InvalidTypeError({ expectedType: 'Uint32' });
1725
+ function numberToBytes32(num) {
1726
+ if (!isUintNumber(num)) {
1727
+ throw new InvalidTypeError({ expectedType: 'Uint' });
1634
1728
  }
1635
1729
  const buffer = new ArrayBuffer(32);
1636
1730
  const view = new DataView(buffer);
1637
- view.setUint32(28, Number(uint32), false);
1731
+ view.setBigUint64(24, BigInt(num), false);
1638
1732
  return new Uint8Array(buffer);
1639
1733
  }
1640
1734
  function assertIsUint8(value) {
@@ -1729,47 +1823,216 @@ function checksummedAddressToBytes20(address) {
1729
1823
  return bytes;
1730
1824
  }
1731
1825
 
1826
+ class FhevmHandleError extends RelayerErrorBase {
1827
+ constructor({ handle, message }) {
1828
+ super({
1829
+ message: message ??
1830
+ (handle
1831
+ ? `FHEVM Handle "${handle}" is invalid.`
1832
+ : `FHEVM Handle is invalid.`),
1833
+ name: 'FhevmHandleError',
1834
+ });
1835
+ }
1836
+ }
1837
+
1838
+ class FheTypeError extends RelayerErrorBase {
1839
+ constructor({ fheTypeId, message, }) {
1840
+ super({
1841
+ message: message ??
1842
+ (fheTypeId
1843
+ ? `FheTypeId "${fheTypeId}" is invalid.`
1844
+ : `FheTypeId is invalid.`),
1845
+ name: 'FheTypeError',
1846
+ });
1847
+ }
1848
+ }
1849
+
1850
+ const FheTypeIdToName = {
1851
+ 0: 'ebool',
1852
+ //1: 'euint4', has been deprecated
1853
+ 2: 'euint8',
1854
+ 3: 'euint16',
1855
+ 4: 'euint32',
1856
+ 5: 'euint64',
1857
+ 6: 'euint128',
1858
+ 7: 'eaddress',
1859
+ 8: 'euint256',
1860
+ };
1861
+ const FheTypeIdToEncryptionBitwidth = {
1862
+ 0: 2,
1863
+ //1:?, euint4 has been deprecated
1864
+ 2: 8,
1865
+ 3: 16,
1866
+ 4: 32,
1867
+ 5: 64,
1868
+ 6: 128,
1869
+ 7: 160,
1870
+ 8: 256,
1871
+ };
1872
+ const EncryptionBitwidthToFheTypeId = {
1873
+ 2: 0,
1874
+ //?:1, euint4 has been deprecated
1875
+ 8: 2,
1876
+ 16: 3,
1877
+ 32: 4,
1878
+ 64: 5,
1879
+ 128: 6,
1880
+ 160: 7,
1881
+ 256: 8,
1882
+ };
1883
+ const FheTypeIdToSolidityPrimitiveTypeName = {
1884
+ 0: 'bool',
1885
+ //1:'uint256', euint4 has been deprecated
1886
+ 2: 'uint256',
1887
+ 3: 'uint256',
1888
+ 4: 'uint256',
1889
+ 5: 'uint256',
1890
+ 6: 'uint256',
1891
+ 7: 'address',
1892
+ 8: 'uint256',
1893
+ };
1894
+ Object.freeze(FheTypeIdToEncryptionBitwidth);
1895
+ Object.freeze(EncryptionBitwidthToFheTypeId);
1896
+ Object.freeze(FheTypeIdToSolidityPrimitiveTypeName);
1897
+ ////////////////////////////////////////////////////////////////////////////////
1898
+ // Type Guards
1899
+ ////////////////////////////////////////////////////////////////////////////////
1900
+ /**
1901
+ * Checks if a value is a valid FheTypeId.
1902
+ * @example isFheTypeId(2) // true (euint8)
1903
+ * @example isFheTypeId(1) // false (euint4 is deprecated)
1904
+ */
1905
+ function isFheTypeId(value) {
1906
+ switch (value) {
1907
+ case 0:
1908
+ // 1: euint4 is deprecated
1909
+ case 2:
1910
+ case 3:
1911
+ case 4:
1912
+ case 5:
1913
+ case 6:
1914
+ case 7:
1915
+ case 8:
1916
+ return true;
1917
+ default:
1918
+ return false;
1919
+ }
1920
+ }
1921
+ /**
1922
+ * Checks if a value is a valid encryption bit width.
1923
+ * @example isEncryptionBits(8) // true
1924
+ * @example isEncryptionBits(4) // false (euint4 is deprecated)
1925
+ */
1926
+ function isEncryptionBits(value) {
1927
+ if (typeof value !== 'number') {
1928
+ return false;
1929
+ }
1930
+ return value in EncryptionBitwidthToFheTypeId;
1931
+ }
1932
+ ////////////////////////////////////////////////////////////////////////////////
1933
+ // FheTypeId extractors
1934
+ ////////////////////////////////////////////////////////////////////////////////
1935
+ /**
1936
+ * Converts an encryption bit width to its corresponding FheTypeId.
1937
+ * @throws {FheTypeError} If bitwidth is not a valid encryption bit width.
1938
+ * @example fheTypeIdFromEncryptionBits(8) // 2 (euint8)
1939
+ */
1940
+ function fheTypeIdFromEncryptionBits(bitwidth) {
1941
+ if (!isEncryptionBits(bitwidth)) {
1942
+ throw new FheTypeError({
1943
+ message: `Invalid encryption bits ${bitwidth}`,
1944
+ });
1945
+ }
1946
+ return EncryptionBitwidthToFheTypeId[bitwidth];
1947
+ }
1948
+ /**
1949
+ * Converts an FheTypeId to its corresponding FheTypeName.
1950
+ * @throws {FheTypeError} If id is not a valid FheTypeId.
1951
+ * @example fheTypeNameFromId(2) // 'euint8'
1952
+ */
1953
+ function fheTypeNameFromId(id) {
1954
+ if (!isFheTypeId(id)) {
1955
+ throw new FheTypeError({
1956
+ message: `Invalid FheType id '${id}'`,
1957
+ });
1958
+ }
1959
+ return FheTypeIdToName[id];
1960
+ }
1961
+ ////////////////////////////////////////////////////////////////////////////////
1962
+ // Solidity primitive type names
1963
+ ////////////////////////////////////////////////////////////////////////////////
1964
+ /**
1965
+ * Returns the Solidity primitive type name for an FheTypeId.
1966
+ * @example solidityPrimitiveTypeNameFromFheTypeId(0) // 'bool'
1967
+ * @example solidityPrimitiveTypeNameFromFheTypeId(7) // 'address'
1968
+ * @example solidityPrimitiveTypeNameFromFheTypeId(2) // 'uint256'
1969
+ */
1970
+ function solidityPrimitiveTypeNameFromFheTypeId(typeId) {
1971
+ if (!isFheTypeId(typeId)) {
1972
+ throw new FheTypeError({
1973
+ message: `Invalid FheType id '${typeId}'`,
1974
+ });
1975
+ }
1976
+ return FheTypeIdToSolidityPrimitiveTypeName[typeId];
1977
+ }
1978
+ ////////////////////////////////////////////////////////////////////////////////
1979
+ // Encryption Bits
1980
+ ////////////////////////////////////////////////////////////////////////////////
1981
+ /**
1982
+ * Returns the encryption bit width for an FheTypeId.
1983
+ * @example encryptionBitsFromFheTypeId(2) // 8 (euint8)
1984
+ * @example encryptionBitsFromFheTypeId(7) // 160 (eaddress)
1985
+ */
1986
+ function encryptionBitsFromFheTypeId(typeId) {
1987
+ if (!isFheTypeId(typeId)) {
1988
+ throw new FheTypeError({
1989
+ message: `Invalid FheType id '${typeId}'`,
1990
+ });
1991
+ }
1992
+ return FheTypeIdToEncryptionBitwidth[typeId];
1993
+ }
1994
+
1732
1995
  ////////////////////////////////////////////////////////////////////////////////
1733
1996
  // FhevmHandle
1734
1997
  ////////////////////////////////////////////////////////////////////////////////
1735
1998
  class FhevmHandle {
1999
+ //////////////////////////////////////////////////////////////////////////////
2000
+ // Instance Properties
2001
+ //////////////////////////////////////////////////////////////////////////////
1736
2002
  _hash21;
1737
2003
  _chainId;
1738
2004
  _fheTypeId;
1739
2005
  _version;
1740
2006
  _computed;
1741
2007
  _index;
2008
+ _handleBytes32Hex;
2009
+ _handleBytes32;
2010
+ //////////////////////////////////////////////////////////////////////////////
2011
+ // Static Constants
2012
+ //////////////////////////////////////////////////////////////////////////////
1742
2013
  static RAW_CT_HASH_DOMAIN_SEPARATOR = 'ZK-w_rct';
1743
2014
  static HANDLE_HASH_DOMAIN_SEPARATOR = 'ZK-w_hdl';
1744
- static FheTypeIdToEncryptionBitwidths = {
1745
- 0: 2,
1746
- 2: 8,
1747
- 3: 16,
1748
- 4: 32,
1749
- 5: 64,
1750
- 6: 128,
1751
- 7: 160,
1752
- 8: 256,
1753
- };
1754
- static FheTypeEncryptionBitwidthsToId = {
1755
- 2: 0,
1756
- 8: 2,
1757
- 16: 3,
1758
- 32: 4,
1759
- 64: 5,
1760
- 128: 6,
1761
- 160: 7,
1762
- 256: 8,
1763
- };
1764
- static {
1765
- Object.freeze(FhevmHandle.FheTypeIdToEncryptionBitwidths);
1766
- Object.freeze(FhevmHandle.FheTypeEncryptionBitwidthsToId);
1767
- }
1768
- constructor(hash21, chainId, fheTypeId, version, computed, index) {
2015
+ static CURRENT_CIPHERTEXT_VERSION = 0;
2016
+ //////////////////////////////////////////////////////////////////////////////
2017
+ // Constructor
2018
+ //////////////////////////////////////////////////////////////////////////////
2019
+ constructor({ hash21, chainId, fheTypeId, version, computed, index, handleBytes32, handleBytes32Hex, }) {
2020
+ if (!isUintNumber(chainId)) {
2021
+ throw new FhevmHandleError({
2022
+ message: 'ChainId must be a positive integer',
2023
+ });
2024
+ }
1769
2025
  if (BigInt(chainId) > MAX_UINT64) {
1770
2026
  // fhevm assumes chainID is only taking up to 8 bytes
1771
- throw new Error('ChainId exceeds maximum allowed value (8 bytes)');
2027
+ throw new FhevmHandleError({
2028
+ message: 'ChainId exceeds maximum allowed value (8 bytes)',
2029
+ });
1772
2030
  }
2031
+ if (!isBytesHex(hash21, 21)) {
2032
+ throw new FhevmHandleError({ message: 'Hash21 should be 21 bytes long' });
2033
+ }
2034
+ this._handleBytes32 = handleBytes32;
2035
+ this._handleBytes32Hex = handleBytes32Hex;
1773
2036
  this._hash21 = hash21;
1774
2037
  this._chainId = chainId;
1775
2038
  this._fheTypeId = fheTypeId;
@@ -1779,6 +2042,9 @@ class FhevmHandle {
1779
2042
  this._index = index;
1780
2043
  }
1781
2044
  }
2045
+ //////////////////////////////////////////////////////////////////////////////
2046
+ // Instance Getters
2047
+ //////////////////////////////////////////////////////////////////////////////
1782
2048
  get hash21() {
1783
2049
  return this._hash21;
1784
2050
  }
@@ -1788,6 +2054,9 @@ class FhevmHandle {
1788
2054
  get fheTypeId() {
1789
2055
  return this._fheTypeId;
1790
2056
  }
2057
+ get fheTypeName() {
2058
+ return fheTypeNameFromId(this._fheTypeId);
2059
+ }
1791
2060
  get version() {
1792
2061
  return this._version;
1793
2062
  }
@@ -1797,6 +2066,106 @@ class FhevmHandle {
1797
2066
  get index() {
1798
2067
  return this._index;
1799
2068
  }
2069
+ get encryptedBitwidth() {
2070
+ return encryptionBitsFromFheTypeId(this._fheTypeId);
2071
+ }
2072
+ get solidityPrimitiveTypeName() {
2073
+ return solidityPrimitiveTypeNameFromFheTypeId(this._fheTypeId);
2074
+ }
2075
+ toJSON() {
2076
+ return {
2077
+ handle: this.toBytes32Hex(),
2078
+ fheTypeName: this.fheTypeName,
2079
+ fheTypeId: this.fheTypeId,
2080
+ chainId: this.chainId,
2081
+ index: this.index,
2082
+ computed: this.computed,
2083
+ encryptedBitwidth: this.encryptedBitwidth,
2084
+ version: this.version,
2085
+ solidityPrimitiveTypeName: this.solidityPrimitiveTypeName,
2086
+ hash21: this.hash21,
2087
+ };
2088
+ }
2089
+ //////////////////////////////////////////////////////////////////////////////
2090
+ // Instance Serialization
2091
+ //////////////////////////////////////////////////////////////////////////////
2092
+ toBytes32() {
2093
+ if (this._handleBytes32 === undefined) {
2094
+ assertRelayer((this._index === undefined && this._computed) ||
2095
+ (this._index !== undefined && this._index < 255 && !this._computed));
2096
+ const chainId32Bytes = numberToBytes32(this._chainId);
2097
+ const chainId8Bytes = chainId32Bytes.subarray(24, 32);
2098
+ const handleHash21 = hexToBytes(this._hash21);
2099
+ assertRelayer(handleHash21.length === 21);
2100
+ const handleBytes32AsBytes = new Uint8Array(32);
2101
+ handleBytes32AsBytes.set(handleHash21, 0);
2102
+ handleBytes32AsBytes[21] = this._index === undefined ? 255 : this._index;
2103
+ handleBytes32AsBytes.set(chainId8Bytes, 22);
2104
+ handleBytes32AsBytes[30] = this._fheTypeId;
2105
+ handleBytes32AsBytes[31] = this._version;
2106
+ this._handleBytes32 = handleBytes32AsBytes;
2107
+ }
2108
+ return this._handleBytes32;
2109
+ }
2110
+ toBytes32Hex() {
2111
+ if (this._handleBytes32Hex === undefined) {
2112
+ this._handleBytes32Hex = bytesToHex(this.toBytes32());
2113
+ }
2114
+ return this._handleBytes32Hex;
2115
+ }
2116
+ //////////////////////////////////////////////////////////////////////////////
2117
+ // Static Factory Methods
2118
+ //////////////////////////////////////////////////////////////////////////////
2119
+ static fromComponents(params) {
2120
+ return new FhevmHandle(params);
2121
+ }
2122
+ static fromBytes32(handle) {
2123
+ if (!isBytes32(handle)) {
2124
+ throw new FhevmHandleError({
2125
+ message: `FHEVM Handle is not a valid bytes32 array.`,
2126
+ });
2127
+ }
2128
+ const bytes = handle;
2129
+ // Extract hash21 (bytes 0-20)
2130
+ const hash21 = bytesToHex(bytes.slice(0, 21));
2131
+ // Extract index (byte 21) - 255 means computed
2132
+ const indexByte = bytes[21];
2133
+ const computed = indexByte === 255;
2134
+ const index = computed ? undefined : indexByte;
2135
+ // Extract chainId (bytes 22-29, 8 bytes as big-endian uint64)
2136
+ let chainId = 0;
2137
+ for (let i = 22; i < 30; i++) {
2138
+ chainId = chainId * 256 + bytes[i];
2139
+ }
2140
+ // Extract fheTypeId (byte 30)
2141
+ const fheTypeIdByte = bytes[30];
2142
+ if (!isFheTypeId(fheTypeIdByte)) {
2143
+ throw new FhevmHandleError({
2144
+ handle,
2145
+ message: `FHEVM Handle "${handle}" is invalid. Unknown FheType: ${fheTypeIdByte}`,
2146
+ });
2147
+ }
2148
+ // Extract version (byte 31)
2149
+ const version = bytes[31];
2150
+ return new FhevmHandle({
2151
+ hash21,
2152
+ chainId,
2153
+ fheTypeId: fheTypeIdByte,
2154
+ version,
2155
+ computed,
2156
+ index,
2157
+ handleBytes32: handle,
2158
+ });
2159
+ }
2160
+ static fromBytes32Hex(handle) {
2161
+ if (!isBytes32Hex(handle)) {
2162
+ throw new FhevmHandleError({ handle });
2163
+ }
2164
+ const bytes = hexToBytes(handle);
2165
+ const h = FhevmHandle.fromBytes32(bytes);
2166
+ h._handleBytes32Hex = handle;
2167
+ return h;
2168
+ }
1800
2169
  static fromZKProof(params) {
1801
2170
  assertIsChecksummedAddress(params.aclAddress);
1802
2171
  assertIsUint64(params.chainId);
@@ -1806,7 +2175,7 @@ class FhevmHandle {
1806
2175
  fheTypeIds = params.fheTypeIds;
1807
2176
  }
1808
2177
  else if (params.fheTypeEncryptionBitwidths !== undefined) {
1809
- fheTypeIds = params.fheTypeEncryptionBitwidths.map((w) => FhevmHandle.FheTypeEncryptionBitwidthsToId[w]);
2178
+ fheTypeIds = params.fheTypeEncryptionBitwidths.map((w) => fheTypeIdFromEncryptionBits(w));
1810
2179
  }
1811
2180
  else {
1812
2181
  throw new InternalError({
@@ -1837,22 +2206,69 @@ class FhevmHandle {
1837
2206
  const handles = [];
1838
2207
  for (let i = 0; i < fheTypeIds.length; ++i) {
1839
2208
  const hash21 = FhevmHandle._computeInputHash21(hexToBytes(blobHashBytes32Hex), params.aclAddress, params.chainId, i);
1840
- handles.push(new FhevmHandle(hash21, params.chainId, fheTypeIds[i], params.ciphertextVersion, false, i));
2209
+ handles.push(new FhevmHandle({
2210
+ hash21,
2211
+ chainId: params.chainId,
2212
+ fheTypeId: fheTypeIds[i],
2213
+ version: params.ciphertextVersion,
2214
+ computed: false,
2215
+ index: i,
2216
+ }));
1841
2217
  }
1842
2218
  return handles;
1843
2219
  }
2220
+ //////////////////////////////////////////////////////////////////////////////
2221
+ // Static Parsing
2222
+ //////////////////////////////////////////////////////////////////////////////
2223
+ static parse(handle) {
2224
+ if (isBytes(handle)) {
2225
+ return FhevmHandle.fromBytes32(handle);
2226
+ }
2227
+ return FhevmHandle.fromBytes32Hex(handle);
2228
+ }
2229
+ static canParse(handle) {
2230
+ try {
2231
+ FhevmHandle.parse(handle);
2232
+ return true;
2233
+ }
2234
+ catch {
2235
+ return false;
2236
+ }
2237
+ }
2238
+ //////////////////////////////////////////////////////////////////////////////
2239
+ // Static Assertions
2240
+ //////////////////////////////////////////////////////////////////////////////
2241
+ static assertIsHandleHex(handle) {
2242
+ if (typeof handle !== 'string') {
2243
+ throw new FhevmHandleError({
2244
+ message: 'Invalid bytes32 hexadecimal string',
2245
+ });
2246
+ }
2247
+ if (!FhevmHandle.canParse(handle)) {
2248
+ throw new FhevmHandleError({ handle });
2249
+ }
2250
+ }
2251
+ //////////////////////////////////////////////////////////////////////////////
2252
+ // Static Helpers
2253
+ //////////////////////////////////////////////////////////////////////////////
2254
+ static currentCiphertextVersion() {
2255
+ return FhevmHandle.CURRENT_CIPHERTEXT_VERSION;
2256
+ }
2257
+ //////////////////////////////////////////////////////////////////////////////
2258
+ // Private Helpers
2259
+ //////////////////////////////////////////////////////////////////////////////
1844
2260
  /**
1845
2261
  * blobHashBytes32 = keccak256(ciphertextWithZKProof)
1846
2262
  */
1847
2263
  static _computeInputHash21(blobHashBytes32, aclAddress, chainId, index) {
1848
2264
  /*
1849
2265
  https://github.com/zama-ai/fhevm/blob/8ffbd5906ab3d57af178e049930e3fc065c9d4b3/coprocessor/fhevm-engine/zkproof-worker/src/verifier.rs#L431C7-L431C8
1850
-
2266
+
1851
2267
  handle_hash = Bytes("ZK-w_hdl") + blobHash 32 Bytes + index 1 Byte + aclAddress 20 Bytes + chainId 32 bytes
1852
2268
  ===========================================================================================================
1853
2269
 
1854
2270
  const HANDLE_HASH_DOMAIN_SEPARATOR: [u8; 8] = *b"ZK-w_hdl";
1855
-
2271
+
1856
2272
  let mut handle_hash = Keccak256::new();
1857
2273
  handle_hash.update(HANDLE_HASH_DOMAIN_SEPARATOR);
1858
2274
  handle_hash.update(blob_hash);
@@ -1873,27 +2289,12 @@ class FhevmHandle {
1873
2289
  assertIsUint64(chainId);
1874
2290
  const encryptionIndexByte1 = new Uint8Array([index]);
1875
2291
  const aclContractAddressBytes20 = checksummedAddressToBytes20(aclAddress);
1876
- const chainIdBytes32 = uint32ToBytes32(chainId);
2292
+ const chainIdBytes32 = numberToBytes32(chainId);
1877
2293
  const encoder = new TextEncoder();
1878
2294
  const domainSepBytes = encoder.encode(FhevmHandle.HANDLE_HASH_DOMAIN_SEPARATOR);
1879
- return ethers.keccak256(concatBytes(domainSepBytes, blobHashBytes32, encryptionIndexByte1, aclContractAddressBytes20, chainIdBytes32));
1880
- }
1881
- toBytes32() {
1882
- assertRelayer((this._index === undefined && this._computed) ||
1883
- (this._index !== undefined && this._index < 255 && !this._computed));
1884
- const chainId32Bytes = uint32ToBytes32(this._chainId);
1885
- const chainId8Bytes = chainId32Bytes.subarray(24, 32);
1886
- const handleHash = hexToBytes(this._hash21);
1887
- const handleBytes32AsBytes = new Uint8Array(32);
1888
- handleBytes32AsBytes.set(handleHash, 0);
1889
- handleBytes32AsBytes[21] = this._index === undefined ? 255 : this._index;
1890
- handleBytes32AsBytes.set(chainId8Bytes, 22);
1891
- handleBytes32AsBytes[30] = this._fheTypeId;
1892
- handleBytes32AsBytes[31] = this._version;
1893
- return handleBytes32AsBytes;
1894
- }
1895
- toBytes32Hex() {
1896
- return bytesToHex(this.toBytes32());
2295
+ const hashBytes32Hex = ethers.keccak256(concatBytes(domainSepBytes, blobHashBytes32, encryptionIndexByte1, aclContractAddressBytes20, chainIdBytes32));
2296
+ // Truncate to 21 bytes (0x + 42 hex chars)
2297
+ return hashBytes32Hex.slice(0, 2 + 2 * 21);
1897
2298
  }
1898
2299
  }
1899
2300
 
@@ -1902,6 +2303,89 @@ const getAddress = (value) => ethers.getAddress(value);
1902
2303
  const currentCiphertextVersion = () => {
1903
2304
  return 0;
1904
2305
  };
2306
+ async function requestCiphertextWithZKProofVerification({ bits, ciphertext, contractAddress, userAddress, aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerProvider, coprocessorSigners, thresholdCoprocessorSigners, extraData, options, }) {
2307
+ const payload = {
2308
+ contractAddress,
2309
+ userAddress,
2310
+ ciphertextWithInputVerification: bytesToHexNo0x(ciphertext),
2311
+ contractChainId: ('0x' + chainId.toString(16)),
2312
+ extraData,
2313
+ };
2314
+ const json = await relayerProvider.fetchPostInputProof(payload, options);
2315
+ if (!isFhevmRelayerInputProofResponse(json)) {
2316
+ throwRelayerInternalError('INPUT_PROOF', json);
2317
+ }
2318
+ const fhevmHandles = FhevmHandle.fromZKProof({
2319
+ ciphertextWithZKProof: ciphertext,
2320
+ chainId,
2321
+ aclAddress: aclContractAddress,
2322
+ ciphertextVersion: currentCiphertextVersion(),
2323
+ fheTypeEncryptionBitwidths: bits,
2324
+ });
2325
+ const handles = fhevmHandles.map((h) => h.toBytes32());
2326
+ const result = json;
2327
+ // Note that the hex strings returned by the relayer do have have the 0x prefix
2328
+ if (result.handles && result.handles.length > 0) {
2329
+ const responseHandles = result.handles.map(hexToBytes);
2330
+ if (handles.length != responseHandles.length) {
2331
+ throw new Error(`Incorrect Handles list sizes: (expected) ${handles.length} != ${responseHandles.length} (received)`);
2332
+ }
2333
+ for (let index = 0; index < handles.length; index += 1) {
2334
+ let handle = handles[index];
2335
+ let responseHandle = responseHandles[index];
2336
+ let expected = bytesToHexNo0x(handle);
2337
+ let current = bytesToHexNo0x(responseHandle);
2338
+ if (expected !== current) {
2339
+ throw new Error(`Incorrect Handle ${index}: (expected) ${expected} != ${current} (received)`);
2340
+ }
2341
+ }
2342
+ }
2343
+ const signatures = result.signatures;
2344
+ // verify signatures for inputs:
2345
+ const domain = {
2346
+ name: 'InputVerification',
2347
+ version: '1',
2348
+ chainId: gatewayChainId,
2349
+ verifyingContract: verifyingContractAddressInputVerification,
2350
+ };
2351
+ const types = {
2352
+ CiphertextVerification: [
2353
+ { name: 'ctHandles', type: 'bytes32[]' },
2354
+ { name: 'userAddress', type: 'address' },
2355
+ { name: 'contractAddress', type: 'address' },
2356
+ { name: 'contractChainId', type: 'uint256' },
2357
+ { name: 'extraData', type: 'bytes' },
2358
+ ],
2359
+ };
2360
+ const recoveredAddresses = signatures.map((signature) => {
2361
+ const sig = signature.startsWith('0x') ? signature : `0x${signature}`;
2362
+ const recoveredAddress = ethers.ethers.verifyTypedData(domain, types, {
2363
+ ctHandles: handles,
2364
+ userAddress,
2365
+ contractAddress,
2366
+ contractChainId: chainId,
2367
+ extraData,
2368
+ }, sig);
2369
+ return recoveredAddress;
2370
+ });
2371
+ const thresholdReached = isThresholdReached$1(coprocessorSigners, recoveredAddresses, thresholdCoprocessorSigners);
2372
+ if (!thresholdReached) {
2373
+ throw Error('Coprocessor signers threshold is not reached');
2374
+ }
2375
+ // inputProof is len(list_handles) + numCoprocessorSigners + list_handles + signatureCoprocessorSigners (1+1+NUM_HANDLES*32+65*numSigners)
2376
+ let inputProof = numberToHexNo0x(handles.length);
2377
+ const numSigners = signatures.length;
2378
+ inputProof += numberToHexNo0x(numSigners);
2379
+ const listHandlesStr = handles.map((i) => bytesToHexNo0x(i));
2380
+ listHandlesStr.map((handle) => (inputProof += handle));
2381
+ signatures.map((signature) => (inputProof += signature.slice(2))); // removes the '0x' prefix from the `signature` string
2382
+ // Append the extra data to the input proof
2383
+ inputProof += extraData.slice(2);
2384
+ return {
2385
+ handles,
2386
+ inputProof: hexToBytes(inputProof),
2387
+ };
2388
+ }
1905
2389
  function isThresholdReached$1(coprocessorSigners, recoveredAddresses, threshold) {
1906
2390
  const addressMap = new Map();
1907
2391
  recoveredAddresses.forEach((address, index) => {
@@ -1933,9 +2417,7 @@ function isFhevmRelayerInputProofResponse(json) {
1933
2417
  return (response.signatures.every((s) => typeof s === 'string') &&
1934
2418
  response.handles.every((h) => typeof h === 'string'));
1935
2419
  }
1936
- const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId,
1937
- //relayerUrl: string,
1938
- relayerProvider, tfheCompactPublicKey, publicParams, coprocessorSigners, thresholdCoprocessorSigners, instanceOptions) => (contractAddress, userAddress) => {
2420
+ const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerProvider, tfheCompactPublicKey, publicParams, coprocessorSigners, thresholdCoprocessorSigners, defaultOptions) => (contractAddress, userAddress) => {
1939
2421
  if (!ethers.isAddress(contractAddress)) {
1940
2422
  throw new Error('Contract address is not a valid address.');
1941
2423
  }
@@ -1987,25 +2469,31 @@ relayerProvider, tfheCompactPublicKey, publicParams, coprocessorSigners, thresho
1987
2469
  getBits() {
1988
2470
  return input.getBits();
1989
2471
  },
2472
+ generateZKProof() {
2473
+ return {
2474
+ chainId,
2475
+ aclContractAddress: aclContractAddress,
2476
+ userAddress: userAddress,
2477
+ contractAddress: contractAddress,
2478
+ ciphertextWithZkProof: input.encrypt(),
2479
+ bits: input.getBits(),
2480
+ };
2481
+ },
1990
2482
  encrypt: async (options) => {
1991
2483
  const extraData = '0x00';
1992
2484
  const bits = input.getBits();
1993
2485
  const ciphertext = input.encrypt();
1994
- //console.log(`ciphertext=${toHexString(ciphertext)}`);
1995
2486
  const payload = {
1996
2487
  contractAddress: getAddress(contractAddress),
1997
2488
  userAddress: getAddress(userAddress),
1998
- ciphertextWithInputVerification: toHexString(ciphertext),
2489
+ ciphertextWithInputVerification: bytesToHexNo0x(ciphertext),
1999
2490
  contractChainId: ('0x' + chainId.toString(16)),
2000
2491
  extraData,
2001
2492
  };
2002
- const json = await relayerProvider.fetchPostInputProof(payload, options ?? instanceOptions);
2003
- // const json = await fetchRelayerJsonRpcPost(
2004
- // 'INPUT_PROOF',
2005
- // `${relayerUrl}/v1/input-proof`,
2006
- // payload,
2007
- // options ?? instanceOptions,
2008
- // );
2493
+ const json = await relayerProvider.fetchPostInputProof(payload, {
2494
+ ...defaultOptions,
2495
+ ...options,
2496
+ });
2009
2497
  if (!isFhevmRelayerInputProofResponse(json)) {
2010
2498
  throwRelayerInternalError('INPUT_PROOF', json);
2011
2499
  }
@@ -2017,7 +2505,6 @@ relayerProvider, tfheCompactPublicKey, publicParams, coprocessorSigners, thresho
2017
2505
  fheTypeEncryptionBitwidths: bits,
2018
2506
  });
2019
2507
  const handles = fhevmHandles.map((h) => h.toBytes32());
2020
- //const result = json.response;
2021
2508
  const result = json;
2022
2509
  // Note that the hex strings returned by the relayer do have have the 0x prefix
2023
2510
  if (result.handles && result.handles.length > 0) {
@@ -2028,8 +2515,8 @@ relayerProvider, tfheCompactPublicKey, publicParams, coprocessorSigners, thresho
2028
2515
  for (let index = 0; index < handles.length; index += 1) {
2029
2516
  let handle = handles[index];
2030
2517
  let responseHandle = responseHandles[index];
2031
- let expected = toHexString(handle);
2032
- let current = toHexString(responseHandle);
2518
+ let expected = bytesToHexNo0x(handle);
2519
+ let current = bytesToHexNo0x(responseHandle);
2033
2520
  if (expected !== current) {
2034
2521
  throw new Error(`Incorrect Handle ${index}: (expected) ${expected} != ${current} (received)`);
2035
2522
  }
@@ -2068,10 +2555,10 @@ relayerProvider, tfheCompactPublicKey, publicParams, coprocessorSigners, thresho
2068
2555
  throw Error('Coprocessor signers threshold is not reached');
2069
2556
  }
2070
2557
  // inputProof is len(list_handles) + numCoprocessorSigners + list_handles + signatureCoprocessorSigners (1+1+NUM_HANDLES*32+65*numSigners)
2071
- let inputProof = numberToHex(handles.length);
2558
+ let inputProof = numberToHexNo0x(handles.length);
2072
2559
  const numSigners = signatures.length;
2073
- inputProof += numberToHex(numSigners);
2074
- const listHandlesStr = handles.map((i) => toHexString(i));
2560
+ inputProof += numberToHexNo0x(numSigners);
2561
+ const listHandlesStr = handles.map((i) => bytesToHexNo0x(i));
2075
2562
  listHandlesStr.map((handle) => (inputProof += handle));
2076
2563
  signatures.map((signature) => (inputProof += signature.slice(2))); // removes the '0x' prefix from the `signature` string
2077
2564
  // Append the extra data to the input proof
@@ -2084,15 +2571,30 @@ relayerProvider, tfheCompactPublicKey, publicParams, coprocessorSigners, thresho
2084
2571
  };
2085
2572
  };
2086
2573
 
2087
- const aclABI = [
2088
- 'function isAllowedForDecryption(bytes32 handle) view returns (bool)',
2089
- ];
2090
- function isThresholdReached(kmsSigners, recoveredAddresses, threshold) {
2091
- const addressMap = new Map();
2092
- recoveredAddresses.forEach((address, index) => {
2093
- if (addressMap.has(address)) {
2094
- const duplicateValue = address;
2095
- throw new Error(`Duplicate KMS signer address found: ${duplicateValue} appears multiple times in recovered addresses`);
2574
+ function ensureError(e) {
2575
+ if (e instanceof Error) {
2576
+ return e;
2577
+ }
2578
+ const message = e.message ?? 'Non-Error value caught in exception handler';
2579
+ const name = e.name ?? 'ErrorWrapper';
2580
+ const cause = e.cause ?? e;
2581
+ const err = new Error(message, { cause });
2582
+ err.name = name;
2583
+ return err;
2584
+ }
2585
+ function assertNever(value, message) {
2586
+ throw new InternalError({ message });
2587
+ }
2588
+
2589
+ const aclABI = [
2590
+ 'function isAllowedForDecryption(bytes32 handle) view returns (bool)',
2591
+ ];
2592
+ function isThresholdReached(kmsSigners, recoveredAddresses, threshold) {
2593
+ const addressMap = new Map();
2594
+ recoveredAddresses.forEach((address, index) => {
2595
+ if (addressMap.has(address)) {
2596
+ const duplicateValue = address;
2597
+ throw new Error(`Duplicate KMS signer address found: ${duplicateValue} appears multiple times in recovered addresses`);
2096
2598
  }
2097
2599
  addressMap.set(address, index);
2098
2600
  });
@@ -2109,7 +2611,7 @@ function abiEncodeClearValues(clearValues) {
2109
2611
  const abiValues = [];
2110
2612
  for (let i = 0; i < handlesBytes32Hex.length; ++i) {
2111
2613
  const handle = handlesBytes32Hex[i];
2112
- const handleType = getHandleType(handle);
2614
+ const handleType = FhevmHandle.parse(handle).fheTypeId;
2113
2615
  let clearTextValue = clearValues[handle];
2114
2616
  if (typeof clearTextValue === 'boolean') {
2115
2617
  clearTextValue = clearTextValue ? '0x01' : '0x00';
@@ -2146,7 +2648,7 @@ function abiEncodeClearValues(clearValues) {
2146
2648
  break;
2147
2649
  }
2148
2650
  default: {
2149
- throw new Error(`Unsupported Fhevm primitive type id: ${handleType}`);
2651
+ assertNever(handleType, `Unsupported Fhevm primitive type id: ${handleType}`);
2150
2652
  }
2151
2653
  }
2152
2654
  }
@@ -2171,50 +2673,38 @@ function buildDecryptionProof(kmsSignatures, extraData) {
2171
2673
  ]);
2172
2674
  return decryptionProof;
2173
2675
  }
2174
- const CiphertextType = {
2175
- 0: 'bool',
2176
- 2: 'uint256',
2177
- 3: 'uint256',
2178
- 4: 'uint256',
2179
- 5: 'uint256',
2180
- 6: 'uint256',
2181
- 7: 'address',
2182
- 8: 'uint256',
2183
- };
2184
2676
  function deserializeClearValues(handles, decryptedResult) {
2185
- let typesList = [];
2677
+ let fheTypeIdList = [];
2186
2678
  for (const handle of handles) {
2187
- const hexPair = handle.slice(-4, -2).toLowerCase();
2188
- const typeDiscriminant = parseInt(hexPair, 16);
2189
- typesList.push(typeDiscriminant);
2679
+ const typeDiscriminant = FhevmHandle.parse(handle).fheTypeId;
2680
+ fheTypeIdList.push(typeDiscriminant);
2190
2681
  }
2191
2682
  const restoredEncoded = '0x' +
2192
2683
  '00'.repeat(32) + // dummy requestID (ignored)
2193
2684
  decryptedResult.slice(2) +
2194
2685
  '00'.repeat(32); // dummy empty bytes[] length (ignored)
2195
- const abiTypes = typesList.map((t) => {
2196
- const abiType = CiphertextType[t]; // all types are valid because this was supposedly checked already inside the `checkEncryptedBits` function
2686
+ const abiTypes = fheTypeIdList.map((t) => {
2687
+ const abiType = solidityPrimitiveTypeNameFromFheTypeId(t); // all types are valid because this was supposedly checked already inside the `checkEncryptedBits` function
2197
2688
  return abiType;
2198
2689
  });
2199
2690
  const coder = new ethers.AbiCoder();
2200
2691
  const decoded = coder.decode(['uint256', ...abiTypes, 'bytes[]'], restoredEncoded);
2201
2692
  // strip dummy first/last element
2202
- const rawValues = decoded.slice(1, 1 + typesList.length);
2693
+ const rawValues = decoded.slice(1, 1 + fheTypeIdList.length);
2203
2694
  const results = {};
2204
2695
  handles.forEach((handle, idx) => (results[handle] = rawValues[idx]));
2205
2696
  return results;
2206
2697
  }
2207
- const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, verifyingContractAddress, aclContractAddress,
2208
- //relayerUrl: string,
2209
- relayerProvider, provider, instanceOptions) => async (_handles, options) => {
2698
+ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, verifyingContractAddress, aclContractAddress, relayerProvider, provider, defaultOptions) => async (_handles, options) => {
2210
2699
  const extraData = '0x00';
2211
2700
  const acl = new ethers.ethers.Contract(aclContractAddress, aclABI, provider);
2701
+ // This will be replaced by new sanitize classes
2212
2702
  let handles;
2213
2703
  try {
2214
2704
  handles = await Promise.all(_handles.map(async (_handle) => {
2215
2705
  const handle = typeof _handle === 'string'
2216
- ? toHexString(hexToBytes(_handle), true)
2217
- : toHexString(_handle, true);
2706
+ ? bytesToHex(hexToBytes(_handle))
2707
+ : bytesToHex(_handle);
2218
2708
  const isAllowedForDecryption = await acl.isAllowedForDecryption(handle);
2219
2709
  if (!isAllowedForDecryption) {
2220
2710
  throw new Error(`Handle ${handle} is not allowed for public decryption!`);
@@ -2231,13 +2721,10 @@ relayerProvider, provider, instanceOptions) => async (_handles, options) => {
2231
2721
  ciphertextHandles: handles,
2232
2722
  extraData,
2233
2723
  };
2234
- const json = await relayerProvider.fetchPostPublicDecrypt(payloadForRequest, options ?? instanceOptions);
2235
- // const json = await fetchRelayerJsonRpcPost(
2236
- // 'PUBLIC_DECRYPT',
2237
- // `${relayerUrl}/v1/public-decrypt`,
2238
- // payloadForRequest,
2239
- // options ?? instanceOptions,
2240
- // );
2724
+ const json = await relayerProvider.fetchPostPublicDecrypt(payloadForRequest, {
2725
+ ...defaultOptions,
2726
+ ...options,
2727
+ });
2241
2728
  // verify signatures on decryption:
2242
2729
  const domain = {
2243
2730
  name: 'Decryption',
@@ -2375,8 +2862,8 @@ const createEIP712 = (verifyingContract, contractsChainId) => (publicKey, contra
2375
2862
  const generateKeypair = () => {
2376
2863
  const keypair = TKMS.ml_kem_pke_keygen();
2377
2864
  return {
2378
- publicKey: toHexString(TKMS.ml_kem_pke_pk_to_u8vec(TKMS.ml_kem_pke_get_pk(keypair))),
2379
- privateKey: toHexString(TKMS.ml_kem_pke_sk_to_u8vec(keypair)),
2865
+ publicKey: bytesToHexNo0x(TKMS.ml_kem_pke_pk_to_u8vec(TKMS.ml_kem_pke_get_pk(keypair))),
2866
+ privateKey: bytesToHexNo0x(TKMS.ml_kem_pke_sk_to_u8vec(keypair)),
2380
2867
  };
2381
2868
  };
2382
2869
 
@@ -2433,7 +2920,7 @@ class RelayerV1Provider extends AbstractRelayerProvider {
2433
2920
  return 1;
2434
2921
  }
2435
2922
  async fetchGetKeyUrl() {
2436
- const response = await fetchRelayerGet('KEY_URL', this.keyUrl);
2923
+ const response = await fetchRelayerV1Get('KEY_URL', this.keyUrl);
2437
2924
  return response;
2438
2925
  }
2439
2926
  async fetchPostInputProof(payload, options) {
@@ -2451,12 +2938,12 @@ class RelayerV1Provider extends AbstractRelayerProvider {
2451
2938
  }
2452
2939
  }
2453
2940
  */
2454
- const json = await fetchRelayerJsonRpcPost('INPUT_PROOF', this.inputProof, payload, options);
2941
+ const json = await fetchRelayerV1Post('INPUT_PROOF', this.inputProof, payload, options);
2455
2942
  assertIsRelayerInputProofResult(json.response, 'fetchPostInputProof()');
2456
2943
  return json.response;
2457
2944
  }
2458
2945
  async fetchPostPublicDecrypt(payload, options) {
2459
- const json = await fetchRelayerJsonRpcPost('PUBLIC_DECRYPT', this.publicDecrypt, payload, options);
2946
+ const json = await fetchRelayerV1Post('PUBLIC_DECRYPT', this.publicDecrypt, payload, options);
2460
2947
  const response = json.response[0];
2461
2948
  const result = {
2462
2949
  signatures: response.signatures,
@@ -2467,24 +2954,12 @@ class RelayerV1Provider extends AbstractRelayerProvider {
2467
2954
  return result;
2468
2955
  }
2469
2956
  async fetchPostUserDecrypt(payload, options) {
2470
- const json = await fetchRelayerJsonRpcPost('USER_DECRYPT', this.userDecrypt, payload, options);
2957
+ const json = await fetchRelayerV1Post('USER_DECRYPT', this.userDecrypt, payload, options);
2471
2958
  assertIsRelayerUserDecryptResult(json.response, 'RelayerUserDecryptResult()');
2472
2959
  return json.response;
2473
2960
  }
2474
2961
  }
2475
2962
 
2476
- function ensureError(e) {
2477
- if (e instanceof Error) {
2478
- return e;
2479
- }
2480
- const message = e.message ?? 'Non-Error value caught in exception handler';
2481
- const name = e.name ?? 'ErrorWrapper';
2482
- const cause = e.cause ?? e;
2483
- const err = new Error(message, { cause });
2484
- err.name = name;
2485
- return err;
2486
- }
2487
-
2488
2963
  class RelayerV2ProviderError extends RelayerErrorBase {
2489
2964
  _operation;
2490
2965
  constructor(params) {
@@ -2961,22 +3436,6 @@ class RelayerV2RequestInternalError extends RelayerV2RequestErrorBase {
2961
3436
  }
2962
3437
  }
2963
3438
 
2964
- function assertIsRelayerV2ResultQueued(value, name) {
2965
- assertRecordStringProperty(value, 'jobId', name);
2966
- }
2967
-
2968
- /*
2969
- type RelayerV2ResponseQueued = {
2970
- status: "queued";
2971
- result: RelayerV2ResultQueued;
2972
- }
2973
- */
2974
- function assertIsRelayerV2ResponseQueued(value, name) {
2975
- assertRecordStringProperty(value, 'status', name, 'queued');
2976
- assertNonNullableRecordProperty(value, 'result', name);
2977
- assertIsRelayerV2ResultQueued(value.result, `${name}.result`);
2978
- }
2979
-
2980
3439
  class RelayerV2ResponseApiError extends RelayerV2ResponseErrorBase {
2981
3440
  constructor(params) {
2982
3441
  super({
@@ -3038,7 +3497,58 @@ class RelayerV2MaxRetryError extends RelayerV2FetchErrorBase {
3038
3497
  }
3039
3498
  }
3040
3499
 
3500
+ function assertIsRelayerV2PostResultQueued(value, name) {
3501
+ assertRecordStringProperty(value, 'jobId', name);
3502
+ }
3503
+
3504
+ /*
3505
+ {
3506
+ status: 'queued';
3507
+ requestId: string;
3508
+ result: {
3509
+ jobId: string;
3510
+ };
3511
+ }
3512
+ */
3513
+ function assertIsRelayerV2PostResponseQueued(value, name) {
3514
+ assertRecordStringProperty(value, 'status', name, 'queued');
3515
+ assertRecordStringProperty(value, 'requestId', name);
3516
+ assertNonNullableRecordProperty(value, 'result', name);
3517
+ assertIsRelayerV2PostResultQueued(value.result, `${name}.result`);
3518
+ }
3519
+ /*
3520
+ {
3521
+ status: 'queued';
3522
+ requestId: string;
3523
+ }
3524
+ */
3525
+ function assertIsRelayerV2GetResponseQueued(value, name) {
3526
+ assertRecordStringProperty(value, 'status', name, 'queued');
3527
+ assertRecordStringProperty(value, 'requestId', name);
3528
+ }
3529
+
3530
+ class RelayerV2TimeoutError extends RelayerV2RequestErrorBase {
3531
+ constructor(params) {
3532
+ super({
3533
+ ...params,
3534
+ name: 'RelayerV2TimeoutError',
3535
+ message: `Request timed out after ${params.timeoutMs}ms`,
3536
+ });
3537
+ }
3538
+ }
3539
+
3540
+ class RelayerV2AbortError extends RelayerV2RequestErrorBase {
3541
+ constructor(params) {
3542
+ super({
3543
+ ...params,
3544
+ name: 'RelayerV2AbortError',
3545
+ message: `Request aborted`,
3546
+ });
3547
+ }
3548
+ }
3549
+
3041
3550
  class RelayerV2AsyncRequest {
3551
+ _fetchMethod;
3042
3552
  _jobId;
3043
3553
  _jobIdTimestamp;
3044
3554
  _state;
@@ -3053,17 +3563,18 @@ class RelayerV2AsyncRequest {
3053
3563
  _retryAfterTimeoutID;
3054
3564
  _url;
3055
3565
  _payload;
3056
- _fhevmInstanceOptions;
3566
+ _fhevmAuth;
3057
3567
  _retryAfterTimeoutPromiseFuncReject;
3058
3568
  _onProgress;
3059
- _requestMaxDurationInSecs;
3569
+ _requestMaxDurationInMs;
3060
3570
  _requestStartTimestamp;
3061
3571
  _requestGlobalTimeoutID;
3062
3572
  _throwErrorIfNoRetryAfter;
3063
- static DEFAULT_RETRY_AFTER_SECS = 2;
3064
- static DEFAULT_GLOBAL_REQUEST_TIMEOUT_SECS = 60 * 60;
3065
- static MAX_GET_RETRY = 100;
3066
- static MAX_POST_RETRY = 100;
3573
+ static DEFAULT_RETRY_AFTER_MS = 2500;
3574
+ static MINIMUM_RETRY_AFTER_MS = 1000;
3575
+ static DEFAULT_GLOBAL_REQUEST_TIMEOUT_MS = 60 * 60 * 1000; // 1 hour
3576
+ static MAX_GET_RETRY = 60 * 30; // number of default retries in 1 hour (30 retries/min)
3577
+ static MAX_POST_RETRY = RelayerV2AsyncRequest.MAX_GET_RETRY;
3067
3578
  constructor(params) {
3068
3579
  if (params.relayerOperation !== 'INPUT_PROOF' &&
3069
3580
  params.relayerOperation !== 'PUBLIC_DECRYPT' &&
@@ -3080,14 +3591,14 @@ class RelayerV2AsyncRequest {
3080
3591
  this._internalAbortController = new AbortController();
3081
3592
  this._internalAbortSignal = this._internalAbortController.signal;
3082
3593
  this._internalAbortSignal.addEventListener('abort', this._handleInternalSignalAbort);
3083
- this._externalAbortSignal = params.signal;
3594
+ this._externalAbortSignal = params.options?.signal;
3084
3595
  if (this._externalAbortSignal) {
3085
3596
  this._externalAbortSignal.addEventListener('abort', this._handleExternalSignalAbort);
3086
3597
  }
3087
3598
  this._url = params.url;
3088
3599
  this._payload = params.payload;
3089
- this._fhevmInstanceOptions = params.instanceOptions;
3090
- this._onProgress = params.onProgress;
3600
+ this._fhevmAuth = params.options?.auth;
3601
+ this._onProgress = params.options?.onProgress;
3091
3602
  this._state = {
3092
3603
  aborted: false,
3093
3604
  canceled: false,
@@ -3096,6 +3607,7 @@ class RelayerV2AsyncRequest {
3096
3607
  running: false,
3097
3608
  succeeded: false,
3098
3609
  terminated: false,
3610
+ timeout: false,
3099
3611
  };
3100
3612
  this._retryCount = 0;
3101
3613
  this._retryAfterTimeoutID = undefined;
@@ -3103,9 +3615,9 @@ class RelayerV2AsyncRequest {
3103
3615
  this._terminateReason = undefined;
3104
3616
  this._publicAPINoReentrancy = false;
3105
3617
  this._throwErrorIfNoRetryAfter = params.throwErrorIfNoRetryAfter ?? false;
3106
- this._requestMaxDurationInSecs =
3107
- params.timeoutInSeconds ??
3108
- RelayerV2AsyncRequest.DEFAULT_GLOBAL_REQUEST_TIMEOUT_SECS;
3618
+ this._requestMaxDurationInMs =
3619
+ params.options?.timeout ??
3620
+ RelayerV2AsyncRequest.DEFAULT_GLOBAL_REQUEST_TIMEOUT_MS;
3109
3621
  }
3110
3622
  //////////////////////////////////////////////////////////////////////////////
3111
3623
  // Public API: run
@@ -3147,6 +3659,12 @@ class RelayerV2AsyncRequest {
3147
3659
  state: { ...this._state },
3148
3660
  });
3149
3661
  }
3662
+ if (this._state.timeout) {
3663
+ throw new RelayerV2StateError({
3664
+ message: `Relayer.run() failed. Request already timeout.`,
3665
+ state: { ...this._state },
3666
+ });
3667
+ }
3150
3668
  if (this._externalAbortSignal?.aborted === true) {
3151
3669
  throw new RelayerV2StateError({
3152
3670
  message: `Relayer.run() failed. External AbortSignal already aborted (reason:${this._externalAbortSignal?.reason}).`,
@@ -3167,7 +3685,7 @@ class RelayerV2AsyncRequest {
3167
3685
  }
3168
3686
  this._state.running = true;
3169
3687
  this._requestStartTimestamp = Date.now();
3170
- this._setGlobalRequestTimeout(this._requestMaxDurationInSecs * 1000);
3688
+ this._setGlobalRequestTimeout(this._requestMaxDurationInMs);
3171
3689
  try {
3172
3690
  const json = await this._runPostLoop();
3173
3691
  this._state.succeeded = true;
@@ -3238,6 +3756,12 @@ class RelayerV2AsyncRequest {
3238
3756
  get failed() {
3239
3757
  return this._state.failed;
3240
3758
  }
3759
+ get aborted() {
3760
+ return this._state.aborted;
3761
+ }
3762
+ get timeout() {
3763
+ return this._state.timeout;
3764
+ }
3241
3765
  get succeeded() {
3242
3766
  return this._state.succeeded;
3243
3767
  }
@@ -3258,6 +3782,8 @@ class RelayerV2AsyncRequest {
3258
3782
  //////////////////////////////////////////////////////////////////////////////
3259
3783
  // POST : 202 | 400 | 429 | 500 | 503
3260
3784
  async _runPostLoop() {
3785
+ this._assert(this._fetchMethod === undefined, 'this._fetchMethod === undefined');
3786
+ this._fetchMethod = 'POST';
3261
3787
  // No infinite loop!
3262
3788
  let i = 0;
3263
3789
  while (i < RelayerV2AsyncRequest.MAX_POST_RETRY) {
@@ -3282,19 +3808,18 @@ class RelayerV2AsyncRequest {
3282
3808
  // - SyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2) at JSON.parse (<anonymous>)
3283
3809
  const bodyJson = await this._getResponseJson(response);
3284
3810
  try {
3285
- assertIsRelayerV2ResponseQueued(bodyJson, 'body');
3811
+ assertIsRelayerV2PostResponseQueued(bodyJson, 'body');
3286
3812
  }
3287
3813
  catch (cause) {
3288
- this._throwInvalidResponseError({
3814
+ this._throwResponseInvalidBodyError({
3289
3815
  fetchMethod: 'POST',
3290
3816
  status: responseStatus,
3291
3817
  cause: cause,
3292
3818
  elapsed,
3819
+ bodyJson: safeJSONstringify(bodyJson),
3293
3820
  });
3294
3821
  }
3295
- let retry_after_sec = this._getRetryAfterHeaderValueInSecs(response);
3296
- if (retry_after_sec < 1)
3297
- retry_after_sec = 1;
3822
+ const retryAfterMs = this._getRetryAfterHeaderValueInMs(response);
3298
3823
  // Debug: will throw an assert failed error if jobId has already been set
3299
3824
  this._setJobIdOnce(bodyJson.result.jobId);
3300
3825
  // Async onProgress callback
@@ -3307,11 +3832,10 @@ class RelayerV2AsyncRequest {
3307
3832
  jobId: this.jobId,
3308
3833
  operation: this._relayerOperation,
3309
3834
  retryCount: this._retryCount,
3310
- retryAfter: retry_after_sec,
3835
+ retryAfterMs,
3311
3836
  elapsed,
3312
3837
  });
3313
- // Wait if needed (minimum 1s)
3314
- await this._setRetryAfterTimeout(retry_after_sec * 1000);
3838
+ await this._setRetryAfterTimeout(retryAfterMs);
3315
3839
  const json = await this._runGetLoop();
3316
3840
  return json;
3317
3841
  }
@@ -3324,11 +3848,12 @@ class RelayerV2AsyncRequest {
3324
3848
  assertIsRelayerV2ResponseFailedWithError400(bodyJson, 'body');
3325
3849
  }
3326
3850
  catch (cause) {
3327
- this._throwInvalidResponseError({
3851
+ this._throwResponseInvalidBodyError({
3328
3852
  fetchMethod: 'POST',
3329
3853
  status: responseStatus,
3330
3854
  cause: cause,
3331
3855
  elapsed,
3856
+ bodyJson: safeJSONstringify(bodyJson),
3332
3857
  });
3333
3858
  }
3334
3859
  this._throwRelayerV2ResponseApiError({
@@ -3348,29 +3873,28 @@ class RelayerV2AsyncRequest {
3348
3873
  assertIsRelayerV2ResponseFailedWithError429(bodyJson, 'body');
3349
3874
  }
3350
3875
  catch (cause) {
3351
- this._throwInvalidResponseError({
3876
+ this._throwResponseInvalidBodyError({
3352
3877
  fetchMethod: 'POST',
3353
3878
  status: responseStatus,
3354
3879
  cause: cause,
3355
3880
  elapsed,
3881
+ bodyJson: safeJSONstringify(bodyJson),
3356
3882
  });
3357
3883
  }
3358
- let retry_after_sec = this._getRetryAfterHeaderValueInSecs(response);
3359
- if (retry_after_sec < 1)
3360
- retry_after_sec = 1;
3884
+ const retryAfterMs = this._getRetryAfterHeaderValueInMs(response);
3361
3885
  // Async onProgress callback
3362
3886
  this._postAsyncOnProgressCallback({
3363
3887
  type: 'ratelimited',
3364
3888
  url: this._url,
3365
3889
  method: 'POST',
3366
3890
  status: responseStatus,
3367
- retryAfter: retry_after_sec,
3891
+ retryAfterMs,
3368
3892
  retryCount: this._retryCount,
3369
3893
  elapsed,
3370
- message: bodyJson.error.message,
3894
+ relayerApiError: bodyJson.error,
3371
3895
  });
3372
3896
  // Wait if needed (minimum 1s)
3373
- await this._setRetryAfterTimeout(retry_after_sec * 1000);
3897
+ await this._setRetryAfterTimeout(retryAfterMs);
3374
3898
  continue;
3375
3899
  }
3376
3900
  // RelayerV2ResponseFailed
@@ -3383,11 +3907,12 @@ class RelayerV2AsyncRequest {
3383
3907
  assertIsRelayerV2ResponseFailedWithError500(bodyJson, 'body');
3384
3908
  }
3385
3909
  catch (cause) {
3386
- this._throwInvalidResponseError({
3910
+ this._throwResponseInvalidBodyError({
3387
3911
  fetchMethod: 'POST',
3388
3912
  status: responseStatus,
3389
3913
  cause: cause,
3390
3914
  elapsed,
3915
+ bodyJson: safeJSONstringify(bodyJson),
3391
3916
  });
3392
3917
  }
3393
3918
  this._throwRelayerV2ResponseApiError({
@@ -3407,11 +3932,12 @@ class RelayerV2AsyncRequest {
3407
3932
  assertIsRelayerV2ResponseFailedWithError503(bodyJson, 'body');
3408
3933
  }
3409
3934
  catch (cause) {
3410
- this._throwInvalidResponseError({
3935
+ this._throwResponseInvalidBodyError({
3411
3936
  fetchMethod: 'POST',
3412
3937
  status: responseStatus,
3413
3938
  cause: cause,
3414
3939
  elapsed,
3940
+ bodyJson: safeJSONstringify(bodyJson),
3415
3941
  });
3416
3942
  }
3417
3943
  this._throwRelayerV2ResponseApiError({
@@ -3447,8 +3973,10 @@ class RelayerV2AsyncRequest {
3447
3973
  // GET: 200 | 202 | 404 | 500 | 503 | 504
3448
3974
  // GET is not rate-limited, therefore there is not 429 error
3449
3975
  async _runGetLoop() {
3976
+ this._assert(this._fetchMethod === 'POST', "this._fetchMethod === 'POST'");
3450
3977
  this._assert(this._jobId !== undefined, 'this._jobId !== undefined');
3451
3978
  this._assert(this._jobIdTimestamp !== undefined, 'this._jobIdTimestamp !== undefined');
3979
+ this._fetchMethod = 'GET';
3452
3980
  let i = 0;
3453
3981
  while (i < RelayerV2AsyncRequest.MAX_GET_RETRY) {
3454
3982
  ++i;
@@ -3535,6 +4063,7 @@ class RelayerV2AsyncRequest {
3535
4063
  status: responseStatus,
3536
4064
  elapsed,
3537
4065
  cause: cause,
4066
+ bodyJson: safeJSONstringify(bodyJson),
3538
4067
  });
3539
4068
  }
3540
4069
  // RelayerV2ResultPublicDecrypt
@@ -3546,7 +4075,7 @@ class RelayerV2AsyncRequest {
3546
4075
  case 202: {
3547
4076
  const bodyJson = await this._getResponseJson(response);
3548
4077
  try {
3549
- assertIsRelayerV2ResponseQueued(bodyJson, 'body');
4078
+ assertIsRelayerV2GetResponseQueued(bodyJson, 'body');
3550
4079
  }
3551
4080
  catch (cause) {
3552
4081
  this._throwResponseInvalidBodyError({
@@ -3554,11 +4083,10 @@ class RelayerV2AsyncRequest {
3554
4083
  status: responseStatus,
3555
4084
  elapsed,
3556
4085
  cause: cause,
4086
+ bodyJson: safeJSONstringify(bodyJson),
3557
4087
  });
3558
4088
  }
3559
- let retry_after_sec = this._getRetryAfterHeaderValueInSecs(response);
3560
- if (retry_after_sec < 1)
3561
- retry_after_sec = 1;
4089
+ const retryAfterMs = this._getRetryAfterHeaderValueInMs(response);
3562
4090
  // Async onProgress callback
3563
4091
  this._postAsyncOnProgressCallback({
3564
4092
  type: 'queued',
@@ -3568,12 +4096,12 @@ class RelayerV2AsyncRequest {
3568
4096
  requestId: bodyJson.requestId,
3569
4097
  operation: this._relayerOperation,
3570
4098
  jobId: this.jobId,
3571
- retryAfter: retry_after_sec,
4099
+ retryAfterMs,
3572
4100
  retryCount: this._retryCount,
3573
4101
  elapsed,
3574
4102
  });
3575
4103
  // Wait if needed (minimum 1s)
3576
- await this._setRetryAfterTimeout(retry_after_sec * 1000);
4104
+ await this._setRetryAfterTimeout(retryAfterMs);
3577
4105
  continue;
3578
4106
  }
3579
4107
  case 400: {
@@ -3589,6 +4117,7 @@ class RelayerV2AsyncRequest {
3589
4117
  status: responseStatus,
3590
4118
  elapsed,
3591
4119
  cause: cause,
4120
+ bodyJson: safeJSONstringify(bodyJson),
3592
4121
  });
3593
4122
  }
3594
4123
  this._throwRelayerV2ResponseApiError({
@@ -3611,6 +4140,7 @@ class RelayerV2AsyncRequest {
3611
4140
  status: responseStatus,
3612
4141
  elapsed,
3613
4142
  cause: cause,
4143
+ bodyJson: safeJSONstringify(bodyJson),
3614
4144
  });
3615
4145
  }
3616
4146
  this._throwRelayerV2ResponseApiError({
@@ -3635,6 +4165,7 @@ class RelayerV2AsyncRequest {
3635
4165
  status: responseStatus,
3636
4166
  elapsed,
3637
4167
  cause: cause,
4168
+ bodyJson: safeJSONstringify(bodyJson),
3638
4169
  });
3639
4170
  }
3640
4171
  this._throwRelayerV2ResponseApiError({
@@ -3659,6 +4190,7 @@ class RelayerV2AsyncRequest {
3659
4190
  status: responseStatus,
3660
4191
  elapsed,
3661
4192
  cause: cause,
4193
+ bodyJson: safeJSONstringify(bodyJson),
3662
4194
  });
3663
4195
  }
3664
4196
  this._throwRelayerV2ResponseApiError({
@@ -3683,6 +4215,7 @@ class RelayerV2AsyncRequest {
3683
4215
  status: responseStatus,
3684
4216
  elapsed,
3685
4217
  cause: cause,
4218
+ bodyJson: safeJSONstringify(bodyJson),
3686
4219
  });
3687
4220
  }
3688
4221
  this._throwRelayerV2ResponseApiError({
@@ -3720,17 +4253,20 @@ class RelayerV2AsyncRequest {
3720
4253
  return bodyJson;
3721
4254
  }
3722
4255
  //////////////////////////////////////////////////////////////////////////////
3723
- _getRetryAfterHeaderValueInSecs(response) {
4256
+ _getRetryAfterHeaderValueInMs(response) {
3724
4257
  if (!response.headers.has('Retry-After')) {
3725
4258
  if (this._throwErrorIfNoRetryAfter) {
3726
4259
  throw new Error(`Missing 'Retry-After' header key`);
3727
4260
  }
3728
- return RelayerV2AsyncRequest.DEFAULT_RETRY_AFTER_SECS;
4261
+ return RelayerV2AsyncRequest.DEFAULT_RETRY_AFTER_MS;
3729
4262
  }
3730
4263
  try {
3731
4264
  const n = Number.parseInt(response.headers.get('Retry-After'));
3732
4265
  if (isUint(n)) {
3733
- return n;
4266
+ const ms = n * 1000;
4267
+ return ms < RelayerV2AsyncRequest.MINIMUM_RETRY_AFTER_MS
4268
+ ? RelayerV2AsyncRequest.MINIMUM_RETRY_AFTER_MS
4269
+ : ms;
3734
4270
  }
3735
4271
  }
3736
4272
  catch {
@@ -3739,7 +4275,7 @@ class RelayerV2AsyncRequest {
3739
4275
  if (this._throwErrorIfNoRetryAfter) {
3740
4276
  throw new Error(`Invalid 'Retry-After' header key`);
3741
4277
  }
3742
- return RelayerV2AsyncRequest.DEFAULT_RETRY_AFTER_SECS;
4278
+ return RelayerV2AsyncRequest.DEFAULT_RETRY_AFTER_MS;
3743
4279
  }
3744
4280
  //////////////////////////////////////////////////////////////////////////////
3745
4281
  // JobId
@@ -3778,17 +4314,19 @@ class RelayerV2AsyncRequest {
3778
4314
  this._assert(this._jobId === undefined, 'this._jobId === undefined');
3779
4315
  this._assert(!this._state.terminated, '!this._state.terminated');
3780
4316
  this._assert(!this._state.fetching, '!this._state.fetching');
3781
- this._trace('_fetchPost', 'enter');
4317
+ this._trace('_fetchPost', this._url);
3782
4318
  const init = setAuth({
3783
4319
  method: 'POST',
3784
4320
  headers: {
3785
4321
  'Content-Type': 'application/json',
4322
+ 'ZAMA-SDK-VERSION': `${version}`,
4323
+ 'ZAMA-SDK-NAME': `${sdkName}`,
3786
4324
  },
3787
4325
  body: JSON.stringify(this._payload),
3788
4326
  ...(this._internalAbortSignal
3789
4327
  ? { signal: this._internalAbortSignal }
3790
4328
  : {}),
3791
- }, this._fhevmInstanceOptions?.auth);
4329
+ }, this._fhevmAuth);
3792
4330
  this._state.fetching = true;
3793
4331
  let response;
3794
4332
  try {
@@ -3832,9 +4370,16 @@ class RelayerV2AsyncRequest {
3832
4370
  this._assert(!this._state.terminated, '!this._state.terminated');
3833
4371
  this._assert(!this._state.fetching, '!this._state.fetching');
3834
4372
  this._trace('_fetchGet', `jobId=${this.jobId}`);
3835
- const init = this._internalAbortSignal
3836
- ? { signal: this._internalAbortSignal }
3837
- : undefined;
4373
+ const init = {
4374
+ method: 'GET',
4375
+ headers: {
4376
+ 'ZAMA-SDK-VERSION': `${version}`,
4377
+ 'ZAMA-SDK-NAME': `${sdkName}`,
4378
+ },
4379
+ ...(this._internalAbortSignal
4380
+ ? { signal: this._internalAbortSignal }
4381
+ : {}),
4382
+ };
3838
4383
  this._state.fetching = true;
3839
4384
  let response;
3840
4385
  try {
@@ -3908,7 +4453,18 @@ class RelayerV2AsyncRequest {
3908
4453
  if (signal.reason !== 'cancel') {
3909
4454
  this._assert(!this._state.canceled, '!this._state.canceled');
3910
4455
  }
3911
- this._terminate('abort');
4456
+ this._postAsyncOnProgressCallback({
4457
+ type: 'abort',
4458
+ url: this._url,
4459
+ ...(this._jobId ? { jobId: this._jobId } : {}),
4460
+ operation: this._relayerOperation,
4461
+ retryCount: this._retryCount,
4462
+ });
4463
+ this._terminate('abort', new RelayerV2AbortError({
4464
+ operation: this._relayerOperation,
4465
+ jobId: this._jobId,
4466
+ url: this._url,
4467
+ }));
3912
4468
  };
3913
4469
  //////////////////////////////////////////////////////////////////////////////
3914
4470
  // Terminate
@@ -3932,7 +4488,7 @@ class RelayerV2AsyncRequest {
3932
4488
  this._terminateReason = reason;
3933
4489
  this._terminateError = error;
3934
4490
  this._state.terminated = true;
3935
- this._tryClearRetryAfterTimeout();
4491
+ this._tryClearRetryAfterTimeout(error);
3936
4492
  this._tryClearGlobalRequestTimeout();
3937
4493
  const is = this._internalAbortSignal;
3938
4494
  const es = this._externalAbortSignal;
@@ -3954,7 +4510,7 @@ class RelayerV2AsyncRequest {
3954
4510
  // Debug
3955
4511
  this._assert(!this._state.terminated, '!this._state.terminated');
3956
4512
  this._assert(this._retryAfterTimeoutID === undefined, 'this._retryAfterTimeoutID === undefined');
3957
- this._assert(delayMs >= 1000, 'delayMs >= 1000');
4513
+ this._assert(delayMs >= RelayerV2AsyncRequest.MINIMUM_RETRY_AFTER_MS, `delayMs >= ${RelayerV2AsyncRequest.MINIMUM_RETRY_AFTER_MS}`);
3958
4514
  this._trace('_setRetryAfterTimeout', `delayMs=${delayMs}`);
3959
4515
  if (this._retryAfterTimeoutID !== undefined) {
3960
4516
  return Promise.reject(new Error(`retry-after already running.`));
@@ -3974,7 +4530,7 @@ class RelayerV2AsyncRequest {
3974
4530
  return p;
3975
4531
  }
3976
4532
  //////////////////////////////////////////////////////////////////////////////
3977
- _tryClearRetryAfterTimeout() {
4533
+ _tryClearRetryAfterTimeout(error) {
3978
4534
  if (this._retryAfterTimeoutID === undefined) {
3979
4535
  // Debug
3980
4536
  this._assert(this._retryAfterTimeoutPromiseFuncReject === undefined, 'this._retryAfterTimeoutPromiseFuncReject === undefined');
@@ -3985,7 +4541,8 @@ class RelayerV2AsyncRequest {
3985
4541
  this._retryAfterTimeoutID = undefined;
3986
4542
  this._retryAfterTimeoutPromiseFuncReject = undefined;
3987
4543
  clearTimeout(tid);
3988
- reject(new Error('_tryClearRetryAfterTimeout'));
4544
+ // Calling reject will
4545
+ reject(error ?? new Error('_tryClearRetryAfterTimeout'));
3989
4546
  }
3990
4547
  //////////////////////////////////////////////////////////////////////////////
3991
4548
  // Global Request Timeout
@@ -4000,7 +4557,24 @@ class RelayerV2AsyncRequest {
4000
4557
  this._requestGlobalTimeoutID = setTimeout(callback, delayMs);
4001
4558
  }
4002
4559
  _handleGlobalRequestTimeout() {
4003
- this._terminate('timeout');
4560
+ this._state.timeout = true;
4561
+ // Debug state-check guards:
4562
+ this._assert(this instanceof RelayerV2AsyncRequest, `this instanceof RelayerV2AsyncRequest`);
4563
+ this._assert(!this._state.terminated, `!this._state.terminated`);
4564
+ this._assert(!this._state.timeout, '!this._state.timeout');
4565
+ this._postAsyncOnProgressCallback({
4566
+ type: 'timeout',
4567
+ url: this._url,
4568
+ ...(this._jobId ? { jobId: this._jobId } : {}),
4569
+ operation: this._relayerOperation,
4570
+ retryCount: this._retryCount,
4571
+ });
4572
+ this._terminate('timeout', new RelayerV2TimeoutError({
4573
+ operation: this._relayerOperation,
4574
+ jobId: this._jobId,
4575
+ url: this._url,
4576
+ timeoutMs: this._requestMaxDurationInMs,
4577
+ }));
4004
4578
  }
4005
4579
  _tryClearGlobalRequestTimeout() {
4006
4580
  if (this._requestGlobalTimeoutID === undefined) {
@@ -4087,20 +4661,11 @@ class RelayerV2AsyncRequest {
4087
4661
  elapsed,
4088
4662
  });
4089
4663
  }
4090
- _throwInvalidResponseError(params) {
4091
- throw new RelayerV2ResponseInvalidBodyError({
4092
- ...params,
4093
- url: this._url,
4094
- operation: this._relayerOperation,
4095
- state: { ...this._state },
4096
- retryCount: this._retryCount,
4097
- });
4098
- }
4099
4664
  _throwResponseInvalidBodyError(params) {
4100
4665
  throw new RelayerV2ResponseInvalidBodyError({
4101
4666
  ...params,
4102
4667
  url: this._url,
4103
- jobId: this.jobId,
4668
+ jobId: this._jobId,
4104
4669
  operation: this._relayerOperation,
4105
4670
  state: { ...this._state },
4106
4671
  retryCount: this._retryCount,
@@ -4171,7 +4736,7 @@ function assertIsRelayerV2KeyData(value, name) {
4171
4736
  assertRecordStringProperty(value, 'dataId', name);
4172
4737
  assertRecordStringArrayProperty(value, 'urls', name);
4173
4738
  }
4174
- function toRelayerKeyUrlResponse(response) {
4739
+ function toRelayerV1KeyUrlResponse(response) {
4175
4740
  const fheKeyInfoV1 = response.response.fheKeyInfo.map((v2Info) => ({
4176
4741
  fhe_public_key: {
4177
4742
  data_id: v2Info.fhePublicKey.dataId,
@@ -4201,7 +4766,7 @@ class RelayerV2Provider extends AbstractRelayerProvider {
4201
4766
  return 2;
4202
4767
  }
4203
4768
  async fetchGetKeyUrlV2() {
4204
- const response = await fetchRelayerGet('KEY_URL', this.keyUrl);
4769
+ const response = await fetchRelayerV1Get('KEY_URL', this.keyUrl);
4205
4770
  // Relayer error
4206
4771
  try {
4207
4772
  assertIsRelayerV2GetResponseKeyUrl(response, 'fetchGetKeyUrl()');
@@ -4215,39 +4780,36 @@ class RelayerV2Provider extends AbstractRelayerProvider {
4215
4780
  }
4216
4781
  async fetchGetKeyUrl() {
4217
4782
  const response = await this.fetchGetKeyUrlV2();
4218
- return toRelayerKeyUrlResponse(response);
4783
+ return toRelayerV1KeyUrlResponse(response);
4219
4784
  }
4220
- async fetchPostInputProof(payload, instanceOptions, fetchOptions) {
4785
+ async fetchPostInputProof(payload, options) {
4221
4786
  const request = new RelayerV2AsyncRequest({
4222
4787
  relayerOperation: 'INPUT_PROOF',
4223
4788
  url: this.inputProof,
4224
4789
  payload,
4225
- instanceOptions,
4226
- ...fetchOptions,
4790
+ options,
4227
4791
  });
4228
4792
  const result = (await request.run());
4229
4793
  assertIsRelayerInputProofResult(result, 'fetchPostInputProof()');
4230
4794
  return result;
4231
4795
  }
4232
- async fetchPostPublicDecrypt(payload, instanceOptions, fetchOptions) {
4796
+ async fetchPostPublicDecrypt(payload, options) {
4233
4797
  const request = new RelayerV2AsyncRequest({
4234
4798
  relayerOperation: 'PUBLIC_DECRYPT',
4235
4799
  url: this.publicDecrypt,
4236
4800
  payload,
4237
- instanceOptions,
4238
- ...fetchOptions,
4801
+ options,
4239
4802
  });
4240
4803
  const result = await request.run();
4241
4804
  assertIsRelayerPublicDecryptResult(result, 'fetchPostPublicDecrypt()');
4242
4805
  return result;
4243
4806
  }
4244
- async fetchPostUserDecrypt(payload, instanceOptions, fetchOptions) {
4807
+ async fetchPostUserDecrypt(payload, options) {
4245
4808
  const request = new RelayerV2AsyncRequest({
4246
4809
  relayerOperation: 'USER_DECRYPT',
4247
4810
  url: this.userDecrypt,
4248
4811
  payload,
4249
- instanceOptions,
4250
- ...fetchOptions,
4812
+ options,
4251
4813
  });
4252
4814
  const result = (await request.run());
4253
4815
  assertIsRelayerUserDecryptResult(result.result, 'fetchPostUserDecrypt()');
@@ -4255,6 +4817,16 @@ class RelayerV2Provider extends AbstractRelayerProvider {
4255
4817
  }
4256
4818
  }
4257
4819
 
4820
+ class TFHECrsError extends RelayerErrorBase {
4821
+ constructor({ message, cause }) {
4822
+ super({
4823
+ message,
4824
+ name: 'TFHECrsError',
4825
+ ...(cause ? { cause: ensureError(cause) } : {}),
4826
+ });
4827
+ }
4828
+ }
4829
+
4258
4830
  class AbstractRelayerFhevm {
4259
4831
  }
4260
4832
 
@@ -4269,6 +4841,15 @@ class TFHECrs {
4269
4841
  this._bits = params.bits;
4270
4842
  this._srcUrl = params.srcUrl;
4271
4843
  }
4844
+ get id() {
4845
+ return this._id;
4846
+ }
4847
+ get bits() {
4848
+ return this._bits;
4849
+ }
4850
+ get srcUrl() {
4851
+ return this._srcUrl;
4852
+ }
4272
4853
  /*
4273
4854
  {
4274
4855
  id: string,
@@ -4371,20 +4952,58 @@ class TFHECrs {
4371
4952
  return TFHECrs._fromUrl(params);
4372
4953
  }
4373
4954
  else {
4374
- throw new Error('Invalid public key (deserialization failed)');
4955
+ throw new TFHECrsError({
4956
+ message: 'Invalid public key (deserialization failed)',
4957
+ });
4375
4958
  }
4376
4959
  }
4960
+ /*
4961
+ {
4962
+ id: string;
4963
+ data: Uint8Array;
4964
+ bits: number;
4965
+ srcUrl?: string;
4966
+ }
4967
+ */
4377
4968
  static fromBytes(params) {
4378
4969
  try {
4379
4970
  TFHECrs.assertKeyBytesType(params, 'arg');
4380
4971
  return TFHECrs._fromBytes(params);
4381
4972
  }
4382
4973
  catch (e) {
4383
- throw new Error('Invalid public key (deserialization failed)', {
4974
+ throw new TFHECrsError({
4975
+ message: 'Invalid public key (deserialization failed)',
4384
4976
  cause: e,
4385
4977
  });
4386
4978
  }
4387
4979
  }
4980
+ /*
4981
+ {
4982
+ id: string;
4983
+ data: BytesHex;
4984
+ bits: number;
4985
+ srcUrl?: string;
4986
+ }
4987
+ */
4988
+ static fromBytesHex(params) {
4989
+ let data;
4990
+ try {
4991
+ assertRecordStringProperty(params, 'data', 'arg');
4992
+ data = hexToBytesFaster(params.data, true /* strict */);
4993
+ }
4994
+ catch (e) {
4995
+ throw new TFHECrsError({
4996
+ message: 'Invalid public key (deserialization failed)',
4997
+ cause: e,
4998
+ });
4999
+ }
5000
+ return TFHECrs.fromBytes({
5001
+ id: params?.id,
5002
+ bits: params?.bits,
5003
+ srcUrl: params?.srcUrl,
5004
+ data,
5005
+ });
5006
+ }
4388
5007
  static _fromBytes(params) {
4389
5008
  const _params = {
4390
5009
  compactPkeCrs: TFHE.CompactPkeCrs.safe_deserialize(params.data, SERIALIZED_SIZE_LIMIT_CRS),
@@ -4400,7 +5019,50 @@ class TFHECrs {
4400
5019
  return TFHECrs._fromPublicParamsBytes(params);
4401
5020
  }
4402
5021
  catch (e) {
4403
- throw new Error('Invalid public key (deserialization failed)', {
5022
+ throw new TFHECrsError({
5023
+ message: 'Invalid public key (deserialization failed)',
5024
+ cause: e,
5025
+ });
5026
+ }
5027
+ }
5028
+ static fromBitsPublicParamsBytes(bits, params) {
5029
+ if (bits === undefined) {
5030
+ throw new TFHECrsError({ message: 'Missing PublicParams bits format' });
5031
+ }
5032
+ if (bits !== 2048) {
5033
+ throw new TFHECrsError({
5034
+ message: `Unsupported PublicParams bits format '${bits}'`,
5035
+ });
5036
+ }
5037
+ try {
5038
+ assertRecordStringProperty(params, 'publicParamsId', `arg`);
5039
+ assertUint8ArrayProperty(params, 'publicParams', `arg`);
5040
+ return TFHECrs._fromPublicParamsBytes({
5041
+ 2048: params,
5042
+ });
5043
+ }
5044
+ catch (e) {
5045
+ throw new TFHECrsError({
5046
+ message: 'Invalid public key (deserialization failed)',
5047
+ cause: e,
5048
+ });
5049
+ }
5050
+ }
5051
+ static fromPublicParamsBytesHex(params) {
5052
+ try {
5053
+ assertNonNullableRecordProperty(params, '2048', 'arg');
5054
+ assertRecordStringProperty(params['2048'], 'publicParamsId', `arg.2048`);
5055
+ assertRecordStringProperty(params['2048'], 'publicParams', `arg.2048`);
5056
+ return TFHECrs._fromPublicParamsBytes({
5057
+ 2048: {
5058
+ publicParams: hexToBytesFaster(params['2048'].publicParams, true /* strict */),
5059
+ publicParamsId: params['2048'].publicParamsId,
5060
+ },
5061
+ });
5062
+ }
5063
+ catch (e) {
5064
+ throw new TFHECrsError({
5065
+ message: 'Invalid public key (deserialization failed)',
4404
5066
  cause: e,
4405
5067
  });
4406
5068
  }
@@ -4418,7 +5080,8 @@ class TFHECrs {
4418
5080
  return TFHECrs._fromUrl(params);
4419
5081
  }
4420
5082
  catch (e) {
4421
- throw new Error('Impossible to fetch public key: wrong relayer url.', {
5083
+ throw new TFHECrsError({
5084
+ message: 'Impossible to fetch public key: wrong relayer url.',
4422
5085
  cause: e,
4423
5086
  });
4424
5087
  }
@@ -4449,6 +5112,22 @@ class TFHECrs {
4449
5112
  ...(this._srcUrl ? { srcUrl: this._srcUrl } : {}),
4450
5113
  };
4451
5114
  }
5115
+ /*
5116
+ {
5117
+ id: string,
5118
+ bits: number,
5119
+ data: BytesHex,
5120
+ srcUrl?: string
5121
+ }
5122
+ */
5123
+ toBytesHex() {
5124
+ return {
5125
+ data: bytesToHexLarge(this._compactPkeCrs.safe_serialize(SERIALIZED_SIZE_LIMIT_CRS)),
5126
+ id: this._id,
5127
+ bits: this._bits,
5128
+ ...(this._srcUrl ? { srcUrl: this._srcUrl } : {}),
5129
+ };
5130
+ }
4452
5131
  /*
4453
5132
  {
4454
5133
  2048: {
@@ -4457,9 +5136,11 @@ class TFHECrs {
4457
5136
  }
4458
5137
  }
4459
5138
  */
4460
- toPublicParamsWasm() {
5139
+ toPublicParams2048Wasm() {
4461
5140
  if (this._bits !== 2048) {
4462
- throw new Error(`Unsupported PublicParams bits format ${this._bits}`);
5141
+ throw new TFHECrsError({
5142
+ message: `Unsupported PublicParams bits format '2048'`,
5143
+ });
4463
5144
  }
4464
5145
  const pp = {
4465
5146
  2048: {
@@ -4477,9 +5158,11 @@ class TFHECrs {
4477
5158
  }
4478
5159
  }
4479
5160
  */
4480
- toPublicParamsBytes() {
5161
+ toPublicParams2048Bytes() {
4481
5162
  if (this._bits !== 2048) {
4482
- throw new Error(`Unsupported PublicParams bits format ${this._bits}`);
5163
+ throw new TFHECrsError({
5164
+ message: `Unsupported PublicParams bits format '2048'`,
5165
+ });
4483
5166
  }
4484
5167
  const pp = {
4485
5168
  2048: {
@@ -4489,6 +5172,64 @@ class TFHECrs {
4489
5172
  };
4490
5173
  return pp;
4491
5174
  }
5175
+ /*
5176
+ {
5177
+ 2048: {
5178
+ publicParamsId: string,
5179
+ publicParams: BytesHex
5180
+ }
5181
+ }
5182
+ */
5183
+ toPublicParams2048BytesHex() {
5184
+ if (this._bits === undefined) {
5185
+ throw new TFHECrsError({ message: 'Missing PublicParams bits format' });
5186
+ }
5187
+ if (this._bits !== 2048) {
5188
+ throw new TFHECrsError({
5189
+ message: `Unsupported PublicParams bits format '${this._bits}'`,
5190
+ });
5191
+ }
5192
+ const pp = {
5193
+ 2048: {
5194
+ publicParams: this.toBytesHex().data,
5195
+ publicParamsId: this._id,
5196
+ },
5197
+ };
5198
+ return pp;
5199
+ }
5200
+ //////////////////////////////////////////////////////////////////////////////
5201
+ // JSON
5202
+ //////////////////////////////////////////////////////////////////////////////
5203
+ /*
5204
+ {
5205
+ __type: 'TFHECrs',
5206
+ id: string,
5207
+ data: BytesHex,
5208
+ srcUrl?: string
5209
+ }
5210
+ */
5211
+ toJSON() {
5212
+ return {
5213
+ __type: 'TFHECrs',
5214
+ ...this.toBytesHex(),
5215
+ };
5216
+ }
5217
+ static fromJSON(json) {
5218
+ if (json.__type !== 'TFHECrs') {
5219
+ throw new TFHECrsError({ message: 'Invalid TFHECrs JSON.' });
5220
+ }
5221
+ return TFHECrs.fromBytesHex(json);
5222
+ }
5223
+ }
5224
+
5225
+ class TFHEPublicKeyError extends RelayerErrorBase {
5226
+ constructor({ message, cause }) {
5227
+ super({
5228
+ message,
5229
+ name: 'TFHEPublicKeyError',
5230
+ ...(cause ? { cause: ensureError(cause) } : {}),
5231
+ });
5232
+ }
4492
5233
  }
4493
5234
 
4494
5235
  class TFHEPublicKey {
@@ -4500,6 +5241,12 @@ class TFHEPublicKey {
4500
5241
  this._tfheCompactPublicKey = params.tfheCompactPublicKey;
4501
5242
  this._srcUrl = params.srcUrl;
4502
5243
  }
5244
+ get id() {
5245
+ return this._id;
5246
+ }
5247
+ get srcUrl() {
5248
+ return this._srcUrl;
5249
+ }
4503
5250
  /*
4504
5251
  {
4505
5252
  id: string,
@@ -4584,6 +5331,30 @@ class TFHEPublicKey {
4584
5331
  });
4585
5332
  }
4586
5333
  }
5334
+ /*
5335
+ {
5336
+ id: string,
5337
+ data: BytesHex,
5338
+ srcUrl?: string
5339
+ }
5340
+ */
5341
+ static fromBytesHex(params) {
5342
+ let data;
5343
+ try {
5344
+ assertRecordStringProperty(params, 'data', 'arg');
5345
+ data = hexToBytesFaster(params.data, true /* strict */);
5346
+ }
5347
+ catch (e) {
5348
+ throw new Error('Invalid public key (deserialization failed)', {
5349
+ cause: e,
5350
+ });
5351
+ }
5352
+ return TFHEPublicKey.fromBytes({
5353
+ id: params?.id,
5354
+ srcUrl: params?.srcUrl,
5355
+ data,
5356
+ });
5357
+ }
4587
5358
  /*
4588
5359
  {
4589
5360
  id: string,
@@ -4644,6 +5415,20 @@ class TFHEPublicKey {
4644
5415
  ...(this._srcUrl ? { srcUrl: this._srcUrl } : {}),
4645
5416
  };
4646
5417
  }
5418
+ /*
5419
+ {
5420
+ id: string,
5421
+ data: BytesHex,
5422
+ srcUrl?: string
5423
+ }
5424
+ */
5425
+ toBytesHex() {
5426
+ return {
5427
+ data: bytesToHexLarge(this._tfheCompactPublicKey.safe_serialize(SERIALIZED_SIZE_LIMIT_PK)),
5428
+ id: this._id,
5429
+ ...(this._srcUrl ? { srcUrl: this._srcUrl } : {}),
5430
+ };
5431
+ }
4647
5432
  /*
4648
5433
  {
4649
5434
  publicKey: TFHE.TfheCompactPublicKey
@@ -4668,6 +5453,75 @@ class TFHEPublicKey {
4668
5453
  publicKeyId: this._id,
4669
5454
  };
4670
5455
  }
5456
+ /*
5457
+ {
5458
+ publicKey: Uint8Array
5459
+ publicKeyId: string
5460
+ }
5461
+ */
5462
+ toPublicKeyBytesHex() {
5463
+ return {
5464
+ publicKey: this.toBytesHex().data,
5465
+ publicKeyId: this._id,
5466
+ };
5467
+ }
5468
+ static _fromPublicKeyBytes(params) {
5469
+ return TFHEPublicKey._fromBytes({
5470
+ data: params.publicKey,
5471
+ id: params.publicKeyId,
5472
+ srcUrl: params.srcUrl,
5473
+ });
5474
+ }
5475
+ static fromPublicKeyBytesHex(params) {
5476
+ try {
5477
+ assertRecordStringProperty(params, 'publicKey', `arg`);
5478
+ assertRecordStringProperty(params, 'publicKeyId', `arg`);
5479
+ return TFHEPublicKey._fromPublicKeyBytes({
5480
+ publicKey: hexToBytesFaster(params.publicKey, true /* strict */),
5481
+ publicKeyId: params.publicKeyId,
5482
+ });
5483
+ }
5484
+ catch (e) {
5485
+ throw new Error('Invalid public key (deserialization failed)', {
5486
+ cause: e,
5487
+ });
5488
+ }
5489
+ }
5490
+ static fromPublicKeyBytes(params) {
5491
+ try {
5492
+ assertUint8ArrayProperty(params, 'publicKey', `arg`);
5493
+ assertRecordStringProperty(params, 'publicKeyId', `arg`);
5494
+ return TFHEPublicKey._fromPublicKeyBytes(params);
5495
+ }
5496
+ catch (e) {
5497
+ throw new Error('Invalid public key (deserialization failed)', {
5498
+ cause: e,
5499
+ });
5500
+ }
5501
+ }
5502
+ //////////////////////////////////////////////////////////////////////////////
5503
+ // JSON
5504
+ //////////////////////////////////////////////////////////////////////////////
5505
+ /*
5506
+ {
5507
+ __type: 'TFHEPublicKey',
5508
+ id: string,
5509
+ data: BytesHex,
5510
+ srcUrl?: string
5511
+ }
5512
+ */
5513
+ toJSON() {
5514
+ return {
5515
+ __type: 'TFHEPublicKey',
5516
+ ...this.toBytesHex(),
5517
+ };
5518
+ }
5519
+ static fromJSON(json) {
5520
+ if (json.__type !== 'TFHEPublicKey') {
5521
+ throw new TFHEPublicKeyError({ message: 'Invalid TFHEPublicKey JSON.' });
5522
+ }
5523
+ return TFHEPublicKey.fromBytesHex(json);
5524
+ }
4671
5525
  }
4672
5526
 
4673
5527
  //const __KEY_URL_CACHE__: Record<string, RelayerV2PublicKey> = {};
@@ -4743,7 +5597,7 @@ class RelayerV2PublicKey {
4743
5597
  toBytes() {
4744
5598
  return {
4745
5599
  publicKey: this._publicKey.toBytes(),
4746
- publicParams: this._crs2048.toPublicParamsBytes(),
5600
+ publicParams: this._crs2048.toPublicParams2048Bytes(),
4747
5601
  };
4748
5602
  }
4749
5603
  }
@@ -4777,23 +5631,46 @@ class RelayerV2Fhevm extends AbstractRelayerFhevm {
4777
5631
  get relayerProvider() {
4778
5632
  return this._relayerProvider;
4779
5633
  }
5634
+ getPublicKeyInfo() {
5635
+ return {
5636
+ id: this._relayerPublicKey.getTFHEPublicKey().id,
5637
+ srcUrl: this._relayerPublicKey.getTFHEPublicKey().srcUrl,
5638
+ };
5639
+ }
4780
5640
  getPublicKeyBytes() {
4781
5641
  return this._relayerPublicKey.getTFHEPublicKey().toPublicKeyBytes();
4782
5642
  }
4783
5643
  getPublicKeyWasm() {
4784
5644
  return this._relayerPublicKey.getTFHEPublicKey().toPublicKeyWasm();
4785
5645
  }
4786
- getPublicParamsBytes(bits) {
5646
+ getPublicParamsBytesForBits(bits) {
5647
+ if (bits === undefined) {
5648
+ throw new TFHECrsError({ message: `Missing PublicParams bits format` });
5649
+ }
4787
5650
  if (bits !== 2048) {
4788
- throw new Error(`Unsupported PublicParams bits format ${bits}`);
5651
+ throw new TFHECrsError({
5652
+ message: `Unsupported PublicParams bits format '${bits}'`,
5653
+ });
4789
5654
  }
4790
- return this._relayerPublicKey.getTFHECrs().toPublicParamsBytes()['2048'];
5655
+ return this._relayerPublicKey.getTFHECrs().toPublicParams2048Bytes()['2048'];
4791
5656
  }
4792
- getPublicParamsWasm(bits) {
5657
+ getPublicParamsWasmForBits(bits) {
5658
+ if (bits === undefined) {
5659
+ throw new TFHECrsError({ message: `Missing PublicParams bits format` });
5660
+ }
4793
5661
  if (bits !== 2048) {
4794
- throw new Error(`Unsupported PublicParams bits format ${bits}`);
5662
+ throw new TFHECrsError({
5663
+ message: `Unsupported PublicParams bits format '${bits}'`,
5664
+ });
4795
5665
  }
4796
- return this._relayerPublicKey.getTFHECrs().toPublicParamsWasm()['2048'];
5666
+ return this._relayerPublicKey.getTFHECrs().toPublicParams2048Wasm()['2048'];
5667
+ }
5668
+ getPublicParamsInfo() {
5669
+ return {
5670
+ id: this._relayerPublicKey.getTFHECrs().id,
5671
+ bits: this._relayerPublicKey.getTFHECrs().bits,
5672
+ srcUrl: this._relayerPublicKey.getTFHECrs().srcUrl,
5673
+ };
4797
5674
  }
4798
5675
  }
4799
5676
 
@@ -4832,24 +5709,42 @@ class RelayerV1Fhevm extends AbstractRelayerFhevm {
4832
5709
  publicKeyId: this._publicKeyData.publicKeyId,
4833
5710
  };
4834
5711
  }
5712
+ getPublicKeyInfo() {
5713
+ return {
5714
+ id: this._publicKeyData.publicKeyId,
5715
+ };
5716
+ }
5717
+ getPublicParamsInfo() {
5718
+ return {
5719
+ id: this._publicParamsData['2048'].publicParamsId,
5720
+ bits: 2048,
5721
+ };
5722
+ }
4835
5723
  getPublicKeyWasm() {
4836
5724
  return {
4837
5725
  publicKey: this._publicKeyData.publicKey,
4838
5726
  publicKeyId: this._publicKeyData.publicKeyId,
4839
5727
  };
4840
5728
  }
4841
- getPublicParamsBytes(bits) {
5729
+ getPublicParamsBytesForBits(bits) {
5730
+ if (bits === undefined) {
5731
+ throw new Error(`Missing PublicParams bits format`);
5732
+ }
4842
5733
  if (bits !== 2048) {
4843
- throw new Error(`Unsupported PublicParams bits format ${bits}`);
5734
+ throw new Error(`Unsupported PublicParams bits format '${bits}'`);
4844
5735
  }
4845
- return {
5736
+ const res = {
4846
5737
  publicParams: this._publicParamsData['2048'].publicParams.safe_serialize(SERIALIZED_SIZE_LIMIT_CRS),
4847
5738
  publicParamsId: this._publicParamsData['2048'].publicParamsId,
4848
5739
  };
5740
+ return res;
4849
5741
  }
4850
- getPublicParamsWasm(bits) {
5742
+ getPublicParamsWasmForBits(bits) {
5743
+ if (bits === undefined) {
5744
+ throw new Error(`Missing PublicParams bits format`);
5745
+ }
4851
5746
  if (bits !== 2048) {
4852
- throw new Error(`Unsupported PublicParams bits format ${bits}`);
5747
+ throw new Error(`Unsupported PublicParams bits format '${bits}'`);
4853
5748
  }
4854
5749
  return {
4855
5750
  publicParams: this._publicParamsData['2048'].publicParams,
@@ -4870,11 +5765,16 @@ async function createRelayerFhevm(config) {
4870
5765
  publicParams: config.publicParams,
4871
5766
  });
4872
5767
  }
4873
- return RelayerV1Fhevm.fromConfig({
4874
- relayerVersionUrl: resolved.url,
4875
- publicKey: config.publicKey,
4876
- publicParams: config.publicParams,
4877
- });
5768
+ else if (resolved.version === 1) {
5769
+ return RelayerV1Fhevm.fromConfig({
5770
+ relayerVersionUrl: resolved.url,
5771
+ publicKey: config.publicKey,
5772
+ publicParams: config.publicParams,
5773
+ });
5774
+ }
5775
+ else {
5776
+ throw new Error(`Invalid relayerUrl: ${config.relayerUrl}`);
5777
+ }
4878
5778
  }
4879
5779
  function _resolveRelayerUrl(value, defaultVersion) {
4880
5780
  if (!value || typeof value !== 'string') {
@@ -4905,60 +5805,39 @@ function _resolveRelayerUrl(value, defaultVersion) {
4905
5805
  };
4906
5806
  }
4907
5807
 
4908
- /**
4909
- * **FHE Type Mapping for Input Builders**
4910
- * * Maps the **number of encrypted bits** used by a FHEVM primary type
4911
- * to its corresponding **FheTypeId**. This constant is primarily used by
4912
- * `EncryptedInput` and `RelayerEncryptedInput` builders to determine the correct
4913
- * input type and calculate the total required bit-length.
4914
- *
4915
- * **Structure: \{ Encrypted Bit Length: FheTypeId \}**
4916
- *
4917
- * | Bits | FheTypeId | FHE Type Name | Note |
4918
- * | :--- | :-------- | :------------ | :--- |
4919
- * | 2 | 0 | `ebool` | The boolean type. |
4920
- * | (N/A)| 1 | `euint4` | **Deprecated** and omitted from this map. |
4921
- * | 8 | 2 | `euint8` | |
4922
- * | 16 | 3 | `euint16` | |
4923
- * | 32 | 4 | `euint32` | |
4924
- * | 64 | 5 | `euint64` | |
4925
- * | 128 | 6 | `euint128` | |
4926
- * | 160 | 7 | `eaddress` | Used for encrypted Ethereum addresses. |
4927
- * | 256 | 8 | `euint256` | The maximum supported integer size. |
4928
- */
4929
- const ENCRYPTION_TYPES = {
4930
- 2: 0, // ebool (FheTypeId=0) is using 2 encrypted bits
4931
- // euint4 (FheTypeId=1) is deprecated
4932
- 8: 2, // euint8 (FheTypeId=2) is using 8 encrypted bits
4933
- 16: 3, // euint16 (FheTypeId=3) is using 16 encrypted bits
4934
- 32: 4, // euint32 (FheTypeId=4) is using 32 encrypted bits
4935
- 64: 5, // euint64 (FheTypeId=5) is using 64 encrypted bits
4936
- 128: 6, // euint128 (FheTypeId=128) is using 128 encrypted bits
4937
- 160: 7, // eaddress (FheTypeId=7) is using 160 encrypted bits
4938
- 256: 8, // euint256 (FheTypeId=8) is using 256 encrypted bits
5808
+ ////////////////////////////////////////////////////////////////////////////////
5809
+ // MainnetConfig
5810
+ ////////////////////////////////////////////////////////////////////////////////
5811
+ const MainnetConfig = {
5812
+ aclContractAddress: '0xcA2E8f1F656CD25C01F05d0b243Ab1ecd4a8ffb6',
5813
+ kmsContractAddress: '0x77627828a55156b04Ac0DC0eb30467f1a552BB03',
5814
+ inputVerifierContractAddress: '0xCe0FC2e05CFff1B719EFF7169f7D80Af770c8EA2',
5815
+ verifyingContractAddressDecryption: '0x0f6024a97684f7d90ddb0fAAD79cB15F2C888D24',
5816
+ verifyingContractAddressInputVerification: '0xcB1bB072f38bdAF0F328CdEf1Fc6eDa1DF029287',
5817
+ chainId: 1,
5818
+ gatewayChainId: 261131,
5819
+ network: 'https://ethereum-rpc.publicnode.com',
5820
+ relayerUrl: 'https://relayer.mainnet.zama.org',
4939
5821
  };
4940
-
5822
+ Object.freeze(MainnetConfig);
5823
+ ////////////////////////////////////////////////////////////////////////////////
5824
+ // SepoliaConfig
5825
+ ////////////////////////////////////////////////////////////////////////////////
4941
5826
  const SepoliaConfig = {
4942
- // ACL_CONTRACT_ADDRESS (FHEVM Host chain)
4943
5827
  aclContractAddress: '0xf0Ffdc93b7E186bC2f8CB3dAA75D86d1930A433D',
4944
- // KMS_VERIFIER_CONTRACT_ADDRESS (FHEVM Host chain)
4945
5828
  kmsContractAddress: '0xbE0E383937d564D7FF0BC3b46c51f0bF8d5C311A',
4946
- // INPUT_VERIFIER_CONTRACT_ADDRESS (FHEVM Host chain)
4947
5829
  inputVerifierContractAddress: '0xBBC1fFCdc7C316aAAd72E807D9b0272BE8F84DA0',
4948
- // DECRYPTION_ADDRESS (Gateway chain)
4949
5830
  verifyingContractAddressDecryption: '0x5D8BD78e2ea6bbE41f26dFe9fdaEAa349e077478',
4950
- // INPUT_VERIFICATION_ADDRESS (Gateway chain)
4951
5831
  verifyingContractAddressInputVerification: '0x483b9dE06E4E4C7D35CCf5837A1668487406D955',
4952
- // FHEVM Host chain id
4953
5832
  chainId: 11155111,
4954
- // Gateway chain id
4955
5833
  gatewayChainId: 10901,
4956
- // Optional RPC provider to host chain
4957
5834
  network: 'https://ethereum-sepolia-rpc.publicnode.com',
4958
- // Relayer URL
4959
5835
  relayerUrl: 'https://relayer.testnet.zama.org',
4960
5836
  };
4961
5837
  Object.freeze(SepoliaConfig);
5838
+ ////////////////////////////////////////////////////////////////////////////////
5839
+ // createInstance
5840
+ ////////////////////////////////////////////////////////////////////////////////
4962
5841
  const createInstance = async (config) => {
4963
5842
  const { verifyingContractAddressDecryption, verifyingContractAddressInputVerification, publicKey, inputVerifierContractAddress, kmsContractAddress, aclContractAddress, gatewayChainId, auth, } = config;
4964
5843
  if (!isChecksummedAddress(aclContractAddress)) {
@@ -4990,29 +5869,33 @@ const createInstance = async (config) => {
4990
5869
  defaultRelayerVersion: 1,
4991
5870
  });
4992
5871
  const chainId = await getChainId(provider, config);
4993
- // const relayerVersionUrl = `${config.relayerUrl!}/v1`;
4994
- // const publicKeyData = await getTfheCompactPublicKey({
4995
- // relayerVersionUrl: relayerFhevm.relayerVersionUrl,
4996
- // publicKey: config.publicKey,
4997
- // });
4998
- //const aaa = relayerFhevm.getPublicKey();
4999
- // const publicParamsData = await getPublicParams({
5000
- // relayerVersionUrl,
5001
- // publicParams: config.publicParams,
5002
- // });
5003
5872
  const kmsSigners = await getKMSSigners(provider, kmsContractAddress);
5004
5873
  const thresholdKMSSigners = await getKMSSignersThreshold(provider, kmsContractAddress);
5005
5874
  const coprocessorSigners = await getCoprocessorSigners(provider, inputVerifierContractAddress);
5006
5875
  const thresholdCoprocessorSigners = await getCoprocessorSignersThreshold(provider, inputVerifierContractAddress);
5007
5876
  return {
5008
- createEncryptedInput: createRelayerEncryptedInput(aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId,
5009
- //cleanURL(config.relayerUrl),
5010
- //relayerFhevm.relayerVersionUrl,
5011
- relayerFhevm.relayerProvider,
5012
- //publicKeyData.publicKey,
5013
- relayerFhevm.getPublicKeyWasm().publicKey,
5014
- //publicParamsData,
5015
- { 2048: relayerFhevm.getPublicParamsWasm(2048) }, coprocessorSigners, thresholdCoprocessorSigners),
5877
+ createEncryptedInput: createRelayerEncryptedInput(aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerFhevm.relayerProvider, relayerFhevm.getPublicKeyWasm().publicKey, { 2048: relayerFhevm.getPublicParamsWasmForBits(2048) }, coprocessorSigners, thresholdCoprocessorSigners, auth && { auth }),
5878
+ requestZKProofVerification: (zkProof, options) => {
5879
+ if (zkProof.chainId !== chainId ||
5880
+ zkProof.aclContractAddress !== aclContractAddress) {
5881
+ throw new Error('Invalid ZKProof');
5882
+ }
5883
+ return requestCiphertextWithZKProofVerification({
5884
+ ciphertext: zkProof.ciphertextWithZkProof,
5885
+ aclContractAddress: aclContractAddress,
5886
+ contractAddress: zkProof.contractAddress,
5887
+ userAddress: zkProof.userAddress,
5888
+ chainId,
5889
+ gatewayChainId,
5890
+ bits: zkProof.bits,
5891
+ coprocessorSigners,
5892
+ extraData: '0x00',
5893
+ thresholdCoprocessorSigners,
5894
+ relayerProvider: relayerFhevm.relayerProvider,
5895
+ verifyingContractAddressInputVerification: verifyingContractAddressInputVerification,
5896
+ options,
5897
+ });
5898
+ },
5016
5899
  generateKeypair,
5017
5900
  createEIP712: createEIP712(verifyingContractAddressDecryption, chainId),
5018
5901
  publicDecrypt: publicDecryptRequest(kmsSigners, thresholdKMSSigners, gatewayChainId, verifyingContractAddressDecryption, aclContractAddress,
@@ -5022,7 +5905,7 @@ const createInstance = async (config) => {
5022
5905
  //cleanURL(config.relayerUrl),
5023
5906
  relayerFhevm.relayerProvider, provider, auth && { auth }),
5024
5907
  getPublicKey: () => relayerFhevm.getPublicKeyBytes(),
5025
- getPublicParams: (bits) => relayerFhevm.getPublicParamsBytes(bits),
5908
+ getPublicParams: (bits) => relayerFhevm.getPublicParamsBytesForBits(bits),
5026
5909
  // getPublicKey: () =>
5027
5910
  // publicKeyData.publicKey
5028
5911
  // ? {
@@ -5060,13 +5943,13 @@ const createTfheKeypair = () => {
5060
5943
  };
5061
5944
  const createTfhePublicKey = () => {
5062
5945
  const { publicKey } = createTfheKeypair();
5063
- return toHexString(publicKey.serialize());
5946
+ return bytesToHexNo0x(publicKey.serialize());
5064
5947
  };
5065
5948
 
5066
5949
  global.TFHE = TFHEPkg__namespace;
5067
5950
  global.TKMS = TKMSPkg__namespace;
5068
5951
 
5069
- exports.ENCRYPTION_TYPES = ENCRYPTION_TYPES;
5952
+ exports.MainnetConfig = MainnetConfig;
5070
5953
  exports.SepoliaConfig = SepoliaConfig;
5071
5954
  exports.createEIP712 = createEIP712;
5072
5955
  exports.createInstance = createInstance;