@zama-fhe/relayer-sdk 0.1.0 → 0.1.1

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/web.js CHANGED
@@ -1,4 +1,4 @@
1
- import { JsonRpcProvider, BrowserProvider, Contract, ethers, getAddress, isAddress, AbiCoder } from 'ethers';
1
+ import { JsonRpcProvider, BrowserProvider, Contract, ethers, getAddress as getAddress$2, isAddress, AbiCoder } from 'ethers';
2
2
  import createHash from 'keccak';
3
3
  import fetchRetry from 'fetch-retry';
4
4
  import { threads } from 'wasm-feature-detect';
@@ -26235,7 +26235,9 @@ const fromHexString = (hexString) => {
26235
26235
  return new Uint8Array();
26236
26236
  return Uint8Array.from(arr.map((byte) => parseInt(byte, 16)));
26237
26237
  };
26238
- const toHexString = (bytes, with0x = false) => `${with0x ? '0x' : ''}${bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '')}`;
26238
+ function toHexString(bytes, with0x = false) {
26239
+ return `${with0x ? '0x' : ''}${bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '')}`;
26240
+ }
26239
26241
  const bytesToBigInt = function (byteArray) {
26240
26242
  if (!byteArray || byteArray?.length === 0) {
26241
26243
  return BigInt(0);
@@ -26246,95 +26248,370 @@ const bytesToBigInt = function (byteArray) {
26246
26248
  return BigInt(`0x${hex}`);
26247
26249
  };
26248
26250
 
26249
- const keyurlCache = {};
26250
- const getKeysFromRelayer = async (url, publicKeyId) => {
26251
- if (keyurlCache[url]) {
26252
- return keyurlCache[url];
26251
+ function getErrorCause(e) {
26252
+ if (e instanceof Error && typeof e.cause === 'object' && e.cause !== null) {
26253
+ return e.cause;
26253
26254
  }
26254
- try {
26255
- const response = await fetch(`${url}/v1/keyurl`);
26256
- if (!response.ok) {
26257
- throw new Error(`HTTP error! status: ${response.status}`);
26258
- }
26259
- const data = await response.json();
26260
- if (data) {
26261
- let pubKeyUrl;
26262
- // If no publicKeyId is provided, use the first one
26263
- // Warning: if there are multiple keys available, the first one will most likely never be the
26264
- // same between several calls (fetching the infos is non-deterministic)
26265
- if (!publicKeyId) {
26266
- pubKeyUrl = data.response.fhe_key_info[0].fhe_public_key.urls[0];
26267
- publicKeyId = data.response.fhe_key_info[0].fhe_public_key.data_id;
26268
- }
26269
- else {
26270
- // If a publicKeyId is provided, get the corresponding info
26271
- const keyInfo = data.response.fhe_key_info.find((info) => info.fhe_public_key.data_id === publicKeyId);
26272
- if (!keyInfo) {
26273
- throw new Error(`Could not find FHE key info with data_id ${publicKeyId}`);
26274
- }
26275
- // TODO: Get a given party's public key url instead of the first one
26276
- pubKeyUrl = keyInfo.fhe_public_key.urls[0];
26277
- }
26278
- const publicKeyResponse = await fetch(pubKeyUrl);
26279
- if (!publicKeyResponse.ok) {
26280
- throw new Error(`HTTP error! status: ${publicKeyResponse.status} on ${publicKeyResponse.url}`);
26281
- }
26282
- let publicKey;
26283
- if (typeof publicKeyResponse.bytes === 'function') {
26284
- // bytes is not widely supported yet
26285
- publicKey = await publicKeyResponse.bytes();
26286
- }
26287
- else {
26288
- publicKey = new Uint8Array(await publicKeyResponse.arrayBuffer());
26255
+ return undefined;
26256
+ }
26257
+ function getErrorCauseCode(e) {
26258
+ const cause = getErrorCause(e);
26259
+ if (!cause || !('code' in cause) || !cause.code) {
26260
+ return undefined;
26261
+ }
26262
+ if (typeof cause.code !== 'string') {
26263
+ return undefined;
26264
+ }
26265
+ return cause.code;
26266
+ }
26267
+ function getErrorCauseStatus(e) {
26268
+ const cause = getErrorCause(e);
26269
+ if (!cause || !('status' in cause) || cause.status === undefined) {
26270
+ return undefined;
26271
+ }
26272
+ if (typeof cause.status !== 'number') {
26273
+ return undefined;
26274
+ }
26275
+ return cause.status;
26276
+ }
26277
+ async function throwRelayerResponseError(operation, response) {
26278
+ let message;
26279
+ // Special case for 429
26280
+ if (response.status === 429) {
26281
+ message = `Relayer rate limit exceeded: Please wait and try again later.`;
26282
+ }
26283
+ else {
26284
+ switch (operation) {
26285
+ case 'PUBLIC_DECRYPT': {
26286
+ message = `Public decrypt failed: relayer respond with HTTP code ${response.status}`;
26287
+ break;
26289
26288
  }
26290
- const publicParamsUrl = data.response.crs['2048'].urls[0];
26291
- const publicParamsId = data.response.crs['2048'].data_id;
26292
- const publicParams2048Response = await fetch(publicParamsUrl);
26293
- if (!publicParams2048Response.ok) {
26294
- throw new Error(`HTTP error! status: ${publicParams2048Response.status} on ${publicParams2048Response.url}`);
26289
+ case 'USER_DECRYPT': {
26290
+ message = `User decrypt failed: relayer respond with HTTP code ${response.status}`;
26291
+ break;
26295
26292
  }
26296
- let publicParams2048;
26297
- if (typeof publicParams2048Response.bytes === 'function') {
26298
- // bytes is not widely supported yet
26299
- publicParams2048 = await publicParams2048Response.bytes();
26293
+ case 'KEY_URL': {
26294
+ message = `HTTP error! status: ${response.status}`;
26295
+ break;
26300
26296
  }
26301
- else {
26302
- publicParams2048 = new Uint8Array(await publicParams2048Response.arrayBuffer());
26297
+ default: {
26298
+ const responseText = await response.text();
26299
+ message = `Relayer didn't response correctly. Bad status ${response.statusText}. Content: ${responseText}`;
26300
+ break;
26303
26301
  }
26304
- let pub_key;
26305
- try {
26306
- pub_key = TFHE.TfheCompactPublicKey.safe_deserialize(publicKey, SERIALIZED_SIZE_LIMIT_PK);
26302
+ }
26303
+ }
26304
+ const cause = {
26305
+ code: 'RELAYER_FETCH_ERROR',
26306
+ operation,
26307
+ status: response.status,
26308
+ statusText: response.statusText,
26309
+ url: response.url,
26310
+ };
26311
+ throw new Error(message, {
26312
+ cause,
26313
+ });
26314
+ }
26315
+ function throwRelayerJSONError(operation, error) {
26316
+ let message;
26317
+ switch (operation) {
26318
+ case 'PUBLIC_DECRYPT': {
26319
+ message = "Public decrypt failed: Relayer didn't return a JSON";
26320
+ break;
26321
+ }
26322
+ case 'USER_DECRYPT': {
26323
+ message = "User decrypt failed: Relayer didn't return a JSON";
26324
+ break;
26325
+ }
26326
+ default: {
26327
+ message = "Relayer didn't return a JSON";
26328
+ break;
26329
+ }
26330
+ }
26331
+ const cause = {
26332
+ code: 'RELAYER_NO_JSON_ERROR',
26333
+ operation,
26334
+ error,
26335
+ };
26336
+ throw new Error(message, {
26337
+ cause,
26338
+ });
26339
+ }
26340
+ function throwRelayerUnexpectedJSONError(operation, error) {
26341
+ let message;
26342
+ switch (operation) {
26343
+ case 'PUBLIC_DECRYPT': {
26344
+ message =
26345
+ 'Public decrypt failed: Relayer returned an unexpected JSON response';
26346
+ break;
26347
+ }
26348
+ case 'USER_DECRYPT': {
26349
+ message =
26350
+ 'User decrypt failed: Relayer returned an unexpected JSON response';
26351
+ break;
26352
+ }
26353
+ default: {
26354
+ message = 'Relayer returned an unexpected JSON response';
26355
+ break;
26356
+ }
26357
+ }
26358
+ const cause = {
26359
+ code: 'RELAYER_UNEXPECTED_JSON_ERROR',
26360
+ operation,
26361
+ error,
26362
+ };
26363
+ throw new Error(message, {
26364
+ cause,
26365
+ });
26366
+ }
26367
+ function throwRelayerInternalError(operation, json) {
26368
+ let message;
26369
+ switch (operation) {
26370
+ case 'PUBLIC_DECRYPT': {
26371
+ message =
26372
+ "Pulbic decrypt failed: the public decryption didn't succeed for an unknown reason";
26373
+ break;
26374
+ }
26375
+ case 'USER_DECRYPT': {
26376
+ message =
26377
+ "User decrypt failed: the user decryption didn't succeed for an unknown reason";
26378
+ break;
26379
+ }
26380
+ default: {
26381
+ message = "Relayer didn't response correctly.";
26382
+ break;
26383
+ }
26384
+ }
26385
+ const cause = {
26386
+ code: 'RELAYER_INTERNAL_ERROR',
26387
+ operation,
26388
+ error: json,
26389
+ };
26390
+ throw new Error(message, {
26391
+ cause,
26392
+ });
26393
+ }
26394
+ function throwRelayerUnknownError(operation, error, message) {
26395
+ if (!message) {
26396
+ switch (operation) {
26397
+ case 'PUBLIC_DECRYPT': {
26398
+ message = "Public decrypt failed: Relayer didn't respond";
26399
+ break;
26307
26400
  }
26308
- catch (e) {
26309
- throw new Error('Invalid public key (deserialization failed)', {
26310
- cause: e,
26311
- });
26401
+ case 'USER_DECRYPT': {
26402
+ message = "User decrypt failed: Relayer didn't respond";
26403
+ break;
26312
26404
  }
26313
- let crs;
26314
- try {
26315
- crs = TFHE.CompactPkeCrs.safe_deserialize(new Uint8Array(publicParams2048), SERIALIZED_SIZE_LIMIT_CRS);
26405
+ default: {
26406
+ message = "Relayer didn't response correctly. Bad JSON.";
26407
+ break;
26316
26408
  }
26317
- catch (e) {
26318
- throw new Error('Invalid crs (deserialization failed)', {
26319
- cause: e,
26320
- });
26409
+ }
26410
+ }
26411
+ const cause = {
26412
+ code: 'RELAYER_UNKNOWN_ERROR',
26413
+ operation,
26414
+ error,
26415
+ };
26416
+ throw new Error(message ?? "Relayer didn't response correctly.", {
26417
+ cause,
26418
+ });
26419
+ }
26420
+
26421
+ function assertIsRelayerFetchResponseJson(json) {
26422
+ if (!json || typeof json !== 'object') {
26423
+ throw new Error('Unexpected response JSON.');
26424
+ }
26425
+ if (!('response' in json &&
26426
+ json.response !== null &&
26427
+ json.response !== undefined)) {
26428
+ throw new Error("Unexpected response JSON format: missing 'response' property.");
26429
+ }
26430
+ }
26431
+ async function fetchRelayerJsonRpcPost(relayerOperation, url, payload, options) {
26432
+ const init = {
26433
+ method: 'POST',
26434
+ headers: {
26435
+ 'Content-Type': 'application/json',
26436
+ ...(options?.apiKey && { 'x-api-key': options.apiKey }),
26437
+ },
26438
+ body: JSON.stringify(payload),
26439
+ };
26440
+ let response;
26441
+ let json;
26442
+ try {
26443
+ response = await fetch(url, init);
26444
+ }
26445
+ catch (e) {
26446
+ throwRelayerUnknownError(relayerOperation, e);
26447
+ }
26448
+ if (!response.ok) {
26449
+ await throwRelayerResponseError(relayerOperation, response);
26450
+ }
26451
+ let parsed;
26452
+ try {
26453
+ parsed = await response.json();
26454
+ }
26455
+ catch (e) {
26456
+ throwRelayerJSONError(relayerOperation, e);
26457
+ }
26458
+ try {
26459
+ assertIsRelayerFetchResponseJson(parsed);
26460
+ json = parsed;
26461
+ }
26462
+ catch (e) {
26463
+ throwRelayerUnexpectedJSONError(relayerOperation, e);
26464
+ }
26465
+ return json;
26466
+ }
26467
+ async function fetchRelayerGet(relayerOperation, url) {
26468
+ let response;
26469
+ let json;
26470
+ try {
26471
+ response = await fetch(url);
26472
+ }
26473
+ catch (e) {
26474
+ throwRelayerUnknownError(relayerOperation, e);
26475
+ }
26476
+ if (!response.ok) {
26477
+ await throwRelayerResponseError(relayerOperation, response);
26478
+ }
26479
+ let parsed;
26480
+ try {
26481
+ parsed = await response.json();
26482
+ }
26483
+ catch (e) {
26484
+ throwRelayerJSONError(relayerOperation, e);
26485
+ }
26486
+ try {
26487
+ assertIsRelayerFetchResponseJson(parsed);
26488
+ json = parsed;
26489
+ }
26490
+ catch (e) {
26491
+ throwRelayerUnexpectedJSONError(relayerOperation, e);
26492
+ }
26493
+ return json;
26494
+ }
26495
+
26496
+ // export type RelayerKeysItem = {
26497
+ // data_id: string;
26498
+ // param_choice: number;
26499
+ // urls: string[];
26500
+ // signatures: string[];
26501
+ // };
26502
+ // export type RelayerKey = {
26503
+ // data_id: string;
26504
+ // param_choice: number;
26505
+ // signatures: string[];
26506
+ // urls: string[];
26507
+ // };
26508
+ // export type RelayerKeys = {
26509
+ // response: {
26510
+ // fhe_key_info: {
26511
+ // fhe_public_key: RelayerKey;
26512
+ // fhe_server_key: RelayerKey;
26513
+ // }[];
26514
+ // verf_public_key: {
26515
+ // key_id: string;
26516
+ // server_id: number;
26517
+ // verf_public_key_address: string;
26518
+ // verf_public_key_url: string;
26519
+ // }[];
26520
+ // crs: {
26521
+ // [key: string]: RelayerKeysItem;
26522
+ // };
26523
+ // };
26524
+ // status: string;
26525
+ // };
26526
+ const keyurlCache = {};
26527
+ const getKeysFromRelayer = async (url, publicKeyId) => {
26528
+ if (keyurlCache[url]) {
26529
+ return keyurlCache[url];
26530
+ }
26531
+ const data = await fetchRelayerGet('KEY_URL', `${url}/v1/keyurl`);
26532
+ try {
26533
+ // const response = await fetch(`${url}/v1/keyurl`);
26534
+ // if (!response.ok) {
26535
+ // await throwRelayerResponseError("KEY_URL", response);
26536
+ // }
26537
+ //const data: RelayerKeys = await response.json();
26538
+ //if (data) {
26539
+ let pubKeyUrl;
26540
+ // If no publicKeyId is provided, use the first one
26541
+ // Warning: if there are multiple keys available, the first one will most likely never be the
26542
+ // same between several calls (fetching the infos is non-deterministic)
26543
+ if (!publicKeyId) {
26544
+ pubKeyUrl = data.response.fhe_key_info[0].fhe_public_key.urls[0];
26545
+ publicKeyId = data.response.fhe_key_info[0].fhe_public_key.data_id;
26546
+ }
26547
+ else {
26548
+ // If a publicKeyId is provided, get the corresponding info
26549
+ const keyInfo = data.response.fhe_key_info.find((info) => info.fhe_public_key.data_id === publicKeyId);
26550
+ if (!keyInfo) {
26551
+ throw new Error(`Could not find FHE key info with data_id ${publicKeyId}`);
26321
26552
  }
26322
- const result = {
26323
- publicKey: pub_key,
26324
- publicKeyId,
26325
- publicParams: {
26326
- 2048: {
26327
- publicParams: crs,
26328
- publicParamsId,
26329
- },
26330
- },
26331
- };
26332
- keyurlCache[url] = result;
26333
- return result;
26553
+ // TODO: Get a given party's public key url instead of the first one
26554
+ pubKeyUrl = keyInfo.fhe_public_key.urls[0];
26555
+ }
26556
+ const publicKeyResponse = await fetch(pubKeyUrl);
26557
+ if (!publicKeyResponse.ok) {
26558
+ throw new Error(`HTTP error! status: ${publicKeyResponse.status} on ${publicKeyResponse.url}`);
26559
+ }
26560
+ let publicKey;
26561
+ if (typeof publicKeyResponse.bytes === 'function') {
26562
+ // bytes is not widely supported yet
26563
+ publicKey = await publicKeyResponse.bytes();
26334
26564
  }
26335
26565
  else {
26336
- throw new Error('No public key available');
26566
+ publicKey = new Uint8Array(await publicKeyResponse.arrayBuffer());
26567
+ }
26568
+ const publicParamsUrl = data.response.crs['2048'].urls[0];
26569
+ const publicParamsId = data.response.crs['2048'].data_id;
26570
+ const publicParams2048Response = await fetch(publicParamsUrl);
26571
+ if (!publicParams2048Response.ok) {
26572
+ throw new Error(`HTTP error! status: ${publicParams2048Response.status} on ${publicParams2048Response.url}`);
26337
26573
  }
26574
+ let publicParams2048;
26575
+ if (typeof publicParams2048Response.bytes === 'function') {
26576
+ // bytes is not widely supported yet
26577
+ publicParams2048 = await publicParams2048Response.bytes();
26578
+ }
26579
+ else {
26580
+ publicParams2048 = new Uint8Array(await publicParams2048Response.arrayBuffer());
26581
+ }
26582
+ let pub_key;
26583
+ try {
26584
+ pub_key = TFHE.TfheCompactPublicKey.safe_deserialize(publicKey, SERIALIZED_SIZE_LIMIT_PK);
26585
+ }
26586
+ catch (e) {
26587
+ throw new Error('Invalid public key (deserialization failed)', {
26588
+ cause: e,
26589
+ });
26590
+ }
26591
+ let crs;
26592
+ try {
26593
+ crs = TFHE.CompactPkeCrs.safe_deserialize(new Uint8Array(publicParams2048), SERIALIZED_SIZE_LIMIT_CRS);
26594
+ }
26595
+ catch (e) {
26596
+ throw new Error('Invalid crs (deserialization failed)', {
26597
+ cause: e,
26598
+ });
26599
+ }
26600
+ const result = {
26601
+ publicKey: pub_key,
26602
+ publicKeyId,
26603
+ publicParams: {
26604
+ 2048: {
26605
+ publicParams: crs,
26606
+ publicParamsId,
26607
+ },
26608
+ },
26609
+ };
26610
+ keyurlCache[url] = result;
26611
+ return result;
26612
+ // } else {
26613
+ // throw new Error('No public key available');
26614
+ // }
26338
26615
  }
26339
26616
  catch (e) {
26340
26617
  throw new Error('Impossible to fetch public key: wrong relayer url.', {
@@ -26450,9 +26727,6 @@ const NumEncryptedBits = {
26450
26727
  6: 128, // euint128
26451
26728
  7: 160, // eaddress
26452
26729
  8: 256, // euint256
26453
- 9: 512, // ebytes64
26454
- 10: 1024, // ebytes128
26455
- 11: 2048, // ebytes256
26456
26730
  };
26457
26731
  function checkEncryptedBits(handles) {
26458
26732
  let total = 0;
@@ -26475,6 +26749,8 @@ function checkEncryptedBits(handles) {
26475
26749
  return total;
26476
26750
  }
26477
26751
 
26752
+ // Add type checking
26753
+ const getAddress$1 = (value) => getAddress$2(value);
26478
26754
  const aclABI$1 = [
26479
26755
  'function persistAllowed(bytes32 handle, address account) view returns (bool)',
26480
26756
  ];
@@ -26487,7 +26763,7 @@ function formatAccordingToType(decryptedBigInt, type) {
26487
26763
  }
26488
26764
  else if (type === 7) {
26489
26765
  // eaddress
26490
- return getAddress('0x' + decryptedBigInt.toString(16).padStart(40, '0'));
26766
+ return getAddress$1('0x' + decryptedBigInt.toString(16).padStart(40, '0'));
26491
26767
  }
26492
26768
  else if (type === 9) {
26493
26769
  // ebytes64
@@ -26530,7 +26806,16 @@ function checkDeadlineValidity(startTimestamp, durationDays) {
26530
26806
  throw Error('User decrypt request has expired');
26531
26807
  }
26532
26808
  }
26533
- const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider) => async (_handles, privateKey, publicKey, signature, contractAddresses, userAddress, startTimestamp, durationDays) => {
26809
+ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider, options) => async (_handles, privateKey, publicKey, signature, contractAddresses, userAddress, startTimestamp, durationDays) => {
26810
+ let pubKey;
26811
+ let privKey;
26812
+ try {
26813
+ pubKey = TKMS.u8vec_to_ml_kem_pke_pk(fromHexString(publicKey));
26814
+ privKey = TKMS.u8vec_to_ml_kem_pke_sk(fromHexString(privateKey));
26815
+ }
26816
+ catch (e) {
26817
+ throw new Error('Invalid public or private key', { cause: e });
26818
+ }
26534
26819
  // Casting handles if string
26535
26820
  const signatureSanitized = signature.replace(/^(0x)/, '');
26536
26821
  const publicKeySanitized = publicKey.replace(/^(0x)/, '');
@@ -26538,7 +26823,7 @@ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContra
26538
26823
  handle: typeof h.handle === 'string'
26539
26824
  ? toHexString(fromHexString(h.handle), true)
26540
26825
  : toHexString(h.handle, true),
26541
- contractAddress: h.contractAddress,
26826
+ contractAddress: getAddress$1(h.contractAddress),
26542
26827
  }));
26543
26828
  checkEncryptedBits(handles.map((h) => h.handle));
26544
26829
  checkDeadlineValidity(BigInt(startTimestamp), BigInt(durationDays));
@@ -26573,51 +26858,12 @@ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContra
26573
26858
  durationDays: durationDays.toString(), // Convert to string
26574
26859
  },
26575
26860
  contractsChainId: chainId.toString(), // Convert to string
26576
- contractAddresses: contractAddresses.map((c) => getAddress(c)),
26577
- userAddress: getAddress(userAddress),
26861
+ contractAddresses: contractAddresses.map((c) => getAddress$1(c)),
26862
+ userAddress: getAddress$1(userAddress),
26578
26863
  signature: signatureSanitized,
26579
26864
  publicKey: publicKeySanitized,
26580
26865
  };
26581
- const options = {
26582
- method: 'POST',
26583
- headers: {
26584
- 'Content-Type': 'application/json',
26585
- },
26586
- body: JSON.stringify(payloadForRequest),
26587
- };
26588
- let pubKey;
26589
- let privKey;
26590
- try {
26591
- pubKey = TKMS.u8vec_to_ml_kem_pke_pk(fromHexString(publicKey));
26592
- privKey = TKMS.u8vec_to_ml_kem_pke_sk(fromHexString(privateKey));
26593
- }
26594
- catch (e) {
26595
- throw new Error('Invalid public or private key', { cause: e });
26596
- }
26597
- let response;
26598
- let json;
26599
- try {
26600
- response = await fetch(`${relayerUrl}/v1/user-decrypt`, options);
26601
- if (!response.ok) {
26602
- throw new Error(`User decrypt failed: relayer respond with HTTP code ${response.status}`);
26603
- }
26604
- }
26605
- catch (e) {
26606
- throw new Error("User decrypt failed: Relayer didn't respond", {
26607
- cause: e,
26608
- });
26609
- }
26610
- try {
26611
- json = await response.json();
26612
- }
26613
- catch (e) {
26614
- throw new Error("User decrypt failed: Relayer didn't return a JSON", {
26615
- cause: e,
26616
- });
26617
- }
26618
- if (json.status === 'failure') {
26619
- throw new Error("User decrypt failed: the user decryption didn't succeed for an unknown reason", { cause: json });
26620
- }
26866
+ const json = await fetchRelayerJsonRpcPost('USER_DECRYPT', `${relayerUrl}/v1/user-decrypt`, payloadForRequest, options);
26621
26867
  // assume the KMS Signers have the correct order
26622
26868
  let indexedKmsSigners = kmsSigners.map((signer, index) => {
26623
26869
  return TKMS.new_server_id_addr(index + 1, signer);
@@ -26864,6 +27110,8 @@ const computeHandles = (ciphertextWithZKProof, bitwidths, aclContractAddress, ch
26864
27110
  return handles;
26865
27111
  };
26866
27112
 
27113
+ // Add type checking
27114
+ const getAddress = (value) => getAddress$2(value);
26867
27115
  const currentCiphertextVersion = () => {
26868
27116
  return 0;
26869
27117
  };
@@ -26883,6 +27131,20 @@ function isThresholdReached$1(coprocessorSigners, recoveredAddresses, threshold)
26883
27131
  }
26884
27132
  return recoveredAddresses.length >= threshold;
26885
27133
  }
27134
+ function isFhevmRelayerInputProofResponse(json) {
27135
+ const response = json.response;
27136
+ if (typeof response !== 'object' || response === null) {
27137
+ return false;
27138
+ }
27139
+ if (!('handles' in response && Array.isArray(response.handles))) {
27140
+ return false;
27141
+ }
27142
+ if (!('signatures' in response && Array.isArray(response.signatures))) {
27143
+ return false;
27144
+ }
27145
+ return (response.signatures.every((s) => typeof s === 'string') &&
27146
+ response.handles.every((h) => typeof h === 'string'));
27147
+ }
26886
27148
  const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerUrl, tfheCompactPublicKey, publicParams, coprocessorSigners, thresholdCoprocessorSigners) => (contractAddress, userAddress) => {
26887
27149
  if (!isAddress(contractAddress)) {
26888
27150
  throw new Error('Contract address is not a valid address.');
@@ -26928,18 +27190,6 @@ const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddres
26928
27190
  input.add256(value);
26929
27191
  return this;
26930
27192
  },
26931
- addBytes64(value) {
26932
- input.addBytes64(value);
26933
- return this;
26934
- },
26935
- addBytes128(value) {
26936
- input.addBytes128(value);
26937
- return this;
26938
- },
26939
- addBytes256(value) {
26940
- input.addBytes256(value);
26941
- return this;
26942
- },
26943
27193
  addAddress(value) {
26944
27194
  input.addAddress(value);
26945
27195
  return this;
@@ -26947,43 +27197,18 @@ const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddres
26947
27197
  getBits() {
26948
27198
  return input.getBits();
26949
27199
  },
26950
- encrypt: async () => {
27200
+ encrypt: async (options) => {
26951
27201
  const bits = input.getBits();
26952
27202
  const ciphertext = input.encrypt();
26953
- // https://github.com/zama-ai/fhevm-relayer/blob/978b08f62de060a9b50d2c6cc19fd71b5fb8d873/src/input_http_listener.rs#L13C1-L22C1
26954
27203
  const payload = {
26955
27204
  contractAddress: getAddress(contractAddress),
26956
27205
  userAddress: getAddress(userAddress),
26957
27206
  ciphertextWithInputVerification: toHexString(ciphertext),
26958
- contractChainId: '0x' + chainId.toString(16),
27207
+ contractChainId: ('0x' + chainId.toString(16)),
26959
27208
  };
26960
- const options = {
26961
- method: 'POST',
26962
- headers: {
26963
- 'Content-Type': 'application/json',
26964
- },
26965
- body: JSON.stringify(payload),
26966
- };
26967
- const url = `${relayerUrl}/v1/input-proof`;
26968
- let json;
26969
- try {
26970
- const response = await fetch(url, options);
26971
- if (!response.ok) {
26972
- throw new Error(`Relayer didn't response correctly. Bad status ${response.statusText}. Content: ${await response.text()}`);
26973
- }
26974
- try {
26975
- json = await response.json();
26976
- }
26977
- catch (e) {
26978
- throw new Error("Relayer didn't response correctly. Bad JSON.", {
26979
- cause: e,
26980
- });
26981
- }
26982
- }
26983
- catch (e) {
26984
- throw new Error("Relayer didn't response correctly.", {
26985
- cause: e,
26986
- });
27209
+ const json = await fetchRelayerJsonRpcPost('INPUT_PROOF', `${relayerUrl}/v1/input-proof`, payload, options);
27210
+ if (!isFhevmRelayerInputProofResponse(json)) {
27211
+ throwRelayerInternalError('INPUT_PROOF', json);
26987
27212
  }
26988
27213
  const handles = computeHandles(ciphertext, bits, aclContractAddress, chainId, currentCiphertextVersion());
26989
27214
  // Note that the hex strings returned by the relayer do have have the 0x prefix
@@ -27075,9 +27300,6 @@ const CiphertextType = {
27075
27300
  6: 'uint256',
27076
27301
  7: 'address',
27077
27302
  8: 'uint256',
27078
- 9: 'bytes',
27079
- 10: 'bytes',
27080
- 11: 'bytes',
27081
27303
  };
27082
27304
  function deserializeDecryptedResult(handles, decryptedResult) {
27083
27305
  let typesList = [];
@@ -27102,7 +27324,7 @@ function deserializeDecryptedResult(handles, decryptedResult) {
27102
27324
  handles.forEach((handle, idx) => (results[handle] = rawValues[idx]));
27103
27325
  return results;
27104
27326
  }
27105
- const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider) => async (_handles) => {
27327
+ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider, options) => async (_handles) => {
27106
27328
  const acl = new ethers.Contract(aclContractAddress, aclABI, provider);
27107
27329
  let handles;
27108
27330
  try {
@@ -27120,51 +27342,12 @@ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, veri
27120
27342
  catch (e) {
27121
27343
  throw e;
27122
27344
  }
27123
- const verifications = handles.map(async (ctHandle) => {
27124
- const isAllowedForDecryption = await acl.isAllowedForDecryption(ctHandle);
27125
- if (!isAllowedForDecryption) {
27126
- throw new Error(`Handle ${ctHandle} is not allowed for public decryption!`);
27127
- }
27128
- });
27129
- await Promise.all(verifications).catch((e) => {
27130
- throw e;
27131
- });
27132
27345
  // check 2048 bits limit
27133
27346
  checkEncryptedBits(handles);
27134
27347
  const payloadForRequest = {
27135
27348
  ciphertextHandles: handles,
27136
27349
  };
27137
- const options = {
27138
- method: 'POST',
27139
- headers: {
27140
- 'Content-Type': 'application/json',
27141
- },
27142
- body: JSON.stringify(payloadForRequest),
27143
- };
27144
- let response;
27145
- let json;
27146
- try {
27147
- response = await fetch(`${relayerUrl}/v1/public-decrypt`, options);
27148
- if (!response.ok) {
27149
- throw new Error(`Public decrypt failed: relayer respond with HTTP code ${response.status}`);
27150
- }
27151
- }
27152
- catch (e) {
27153
- throw new Error("Public decrypt failed: Relayer didn't respond", {
27154
- cause: e,
27155
- });
27156
- }
27157
- try {
27158
- json = await response.json();
27159
- }
27160
- catch (e) {
27161
- throw new Error("Public decrypt failed: Relayer didn't return a JSON", {
27162
- cause: e,
27163
- });
27164
- }
27165
- if (json.status === 'failure') {
27166
- throw new Error("Public decrypt failed: the public decrypt didn't succeed for an unknown reason", { cause: json });
27167
- }
27350
+ const json = await fetchRelayerJsonRpcPost('PUBLIC_DECRYPT', `${relayerUrl}/v1/public-decrypt`, payloadForRequest, options);
27168
27351
  // verify signatures on decryption:
27169
27352
  const domain = {
27170
27353
  name: 'Decryption',
@@ -27418,4 +27601,4 @@ window.TKMS = {
27418
27601
  ml_kem_pke_get_pk,
27419
27602
  };
27420
27603
 
27421
- export { ENCRYPTION_TYPES, SepoliaConfig, createEIP712, createInstance, generateKeypair, initSDK };
27604
+ export { ENCRYPTION_TYPES, SepoliaConfig, createEIP712, createInstance, generateKeypair, getErrorCauseCode, getErrorCauseStatus, initSDK };