@cofhe/sdk 0.3.2 → 0.4.0

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.
@@ -1678,13 +1678,13 @@ var serialize = (permit) => {
1678
1678
  var deserialize = (serialized) => {
1679
1679
  return PermitUtils.deserialize(serialized);
1680
1680
  };
1681
- var getPermit = async (chainId, account, hash) => {
1681
+ var getPermit = (chainId, account, hash) => {
1682
1682
  return permitStore.getPermit(chainId, account, hash);
1683
1683
  };
1684
- var getPermits = async (chainId, account) => {
1684
+ var getPermits = (chainId, account) => {
1685
1685
  return permitStore.getPermits(chainId, account);
1686
1686
  };
1687
- var getActivePermit = async (chainId, account) => {
1687
+ var getActivePermit = (chainId, account) => {
1688
1688
  return permitStore.getActivePermit(chainId, account);
1689
1689
  };
1690
1690
  var getActivePermitHash = (chainId, account) => {
@@ -2453,7 +2453,7 @@ async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient) {
2453
2453
  signature
2454
2454
  };
2455
2455
  }
2456
- function normalizeSignature(signature) {
2456
+ function normalizeTnSignature(signature) {
2457
2457
  if (typeof signature !== "string") {
2458
2458
  throw new CofheError({
2459
2459
  code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
@@ -2509,57 +2509,77 @@ function parseDecryptedBytesToBigInt(decrypted) {
2509
2509
  }
2510
2510
  return BigInt(`0x${hex}`);
2511
2511
  }
2512
- function assertTnDecryptResponse(value) {
2512
+
2513
+ // core/decrypt/tnDecryptV2.ts
2514
+ var POLL_INTERVAL_MS2 = 1e3;
2515
+ var POLL_TIMEOUT_MS2 = 5 * 60 * 1e3;
2516
+ function assertDecryptSubmitResponseV2(value) {
2513
2517
  if (value == null || typeof value !== "object") {
2514
2518
  throw new CofheError({
2515
2519
  code: "DECRYPT_FAILED" /* DecryptFailed */,
2516
- message: "decrypt response must be a JSON object",
2520
+ message: "decrypt submit response must be a JSON object",
2517
2521
  context: {
2518
2522
  value
2519
2523
  }
2520
2524
  });
2521
2525
  }
2522
2526
  const v = value;
2523
- const decrypted = v.decrypted;
2524
- const signature = v.signature;
2525
- const encryptionType = v.encryption_type;
2526
- const errorMessage = v.error_message;
2527
- if (!Array.isArray(decrypted)) {
2527
+ if (typeof v.request_id !== "string" || v.request_id.trim().length === 0) {
2528
2528
  throw new CofheError({
2529
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2530
- message: "decrypt response missing <decrypted> byte array",
2531
- context: { decryptResponse: value }
2529
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
2530
+ message: "decrypt submit response missing request_id",
2531
+ context: {
2532
+ value
2533
+ }
2532
2534
  });
2533
2535
  }
2534
- if (typeof signature !== "string") {
2536
+ return { request_id: v.request_id };
2537
+ }
2538
+ function assertDecryptStatusResponseV2(value) {
2539
+ if (value == null || typeof value !== "object") {
2535
2540
  throw new CofheError({
2536
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2537
- message: "decrypt response missing <signature> string",
2538
- context: { decryptResponse: value }
2541
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
2542
+ message: "decrypt status response must be a JSON object",
2543
+ context: {
2544
+ value
2545
+ }
2546
+ });
2547
+ }
2548
+ const v = value;
2549
+ const requestId = v.request_id;
2550
+ const status = v.status;
2551
+ const submittedAt = v.submitted_at;
2552
+ if (typeof requestId !== "string" || requestId.trim().length === 0) {
2553
+ throw new CofheError({
2554
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
2555
+ message: "decrypt status response missing request_id",
2556
+ context: {
2557
+ value
2558
+ }
2539
2559
  });
2540
2560
  }
2541
- if (typeof encryptionType !== "number") {
2561
+ if (status !== "PROCESSING" && status !== "COMPLETED") {
2542
2562
  throw new CofheError({
2543
2563
  code: "DECRYPT_FAILED" /* DecryptFailed */,
2544
- message: "decrypt response missing <encryption_type> number",
2545
- context: { decryptResponse: value }
2564
+ message: "decrypt status response has invalid status",
2565
+ context: {
2566
+ value,
2567
+ status
2568
+ }
2546
2569
  });
2547
2570
  }
2548
- if (!(typeof errorMessage === "string" || errorMessage === null)) {
2571
+ if (typeof submittedAt !== "string" || submittedAt.trim().length === 0) {
2549
2572
  throw new CofheError({
2550
2573
  code: "DECRYPT_FAILED" /* DecryptFailed */,
2551
- message: "decrypt response field <error_message> must be string or null",
2552
- context: { decryptResponse: value }
2574
+ message: "decrypt status response missing submitted_at",
2575
+ context: {
2576
+ value
2577
+ }
2553
2578
  });
2554
2579
  }
2555
- return {
2556
- decrypted,
2557
- signature,
2558
- encryption_type: encryptionType,
2559
- error_message: errorMessage
2560
- };
2580
+ return value;
2561
2581
  }
2562
- async function tnDecrypt(ctHash, chainId, permission, thresholdNetworkUrl) {
2582
+ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, permission) {
2563
2583
  const body = {
2564
2584
  ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
2565
2585
  host_chain_id: chainId
@@ -2569,7 +2589,7 @@ async function tnDecrypt(ctHash, chainId, permission, thresholdNetworkUrl) {
2569
2589
  }
2570
2590
  let response;
2571
2591
  try {
2572
- response = await fetch(`${thresholdNetworkUrl}/decrypt`, {
2592
+ response = await fetch(`${thresholdNetworkUrl}/v2/decrypt`, {
2573
2593
  method: "POST",
2574
2594
  headers: {
2575
2595
  "Content-Type": "application/json"
@@ -2588,18 +2608,15 @@ async function tnDecrypt(ctHash, chainId, permission, thresholdNetworkUrl) {
2588
2608
  }
2589
2609
  });
2590
2610
  }
2591
- const responseText = await response.text();
2592
2611
  if (!response.ok) {
2593
- let errorMessage = response.statusText || `HTTP ${response.status}`;
2612
+ let errorMessage = `HTTP ${response.status}`;
2594
2613
  try {
2595
- const errorBody = JSON.parse(responseText);
2614
+ const errorBody = await response.json();
2596
2615
  const maybeMessage = errorBody.error_message || errorBody.message;
2597
2616
  if (typeof maybeMessage === "string" && maybeMessage.length > 0)
2598
2617
  errorMessage = maybeMessage;
2599
2618
  } catch {
2600
- const trimmed = responseText.trim();
2601
- if (trimmed.length > 0)
2602
- errorMessage = trimmed;
2619
+ errorMessage = response.statusText || errorMessage;
2603
2620
  }
2604
2621
  throw new CofheError({
2605
2622
  code: "DECRYPT_FAILED" /* DecryptFailed */,
@@ -2609,41 +2626,163 @@ async function tnDecrypt(ctHash, chainId, permission, thresholdNetworkUrl) {
2609
2626
  thresholdNetworkUrl,
2610
2627
  status: response.status,
2611
2628
  statusText: response.statusText,
2612
- body,
2613
- responseText
2629
+ body
2614
2630
  }
2615
2631
  });
2616
2632
  }
2617
2633
  let rawJson;
2618
2634
  try {
2619
- rawJson = JSON.parse(responseText);
2635
+ rawJson = await response.json();
2620
2636
  } catch (e) {
2621
2637
  throw new CofheError({
2622
2638
  code: "DECRYPT_FAILED" /* DecryptFailed */,
2623
- message: `Failed to parse decrypt response`,
2639
+ message: `Failed to parse decrypt submit response`,
2624
2640
  cause: e instanceof Error ? e : void 0,
2625
2641
  context: {
2626
2642
  thresholdNetworkUrl,
2627
- body,
2628
- responseText
2643
+ body
2629
2644
  }
2630
2645
  });
2631
2646
  }
2632
- const decryptResponse = assertTnDecryptResponse(rawJson);
2633
- if (decryptResponse.error_message) {
2634
- throw new CofheError({
2635
- code: "DECRYPT_FAILED" /* DecryptFailed */,
2636
- message: `decrypt request failed: ${decryptResponse.error_message}`,
2637
- context: {
2638
- thresholdNetworkUrl,
2639
- body,
2640
- decryptResponse
2647
+ const submitResponse = assertDecryptSubmitResponseV2(rawJson);
2648
+ return submitResponse.request_id;
2649
+ }
2650
+ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId) {
2651
+ const startTime = Date.now();
2652
+ let completed = false;
2653
+ while (!completed) {
2654
+ if (Date.now() - startTime > POLL_TIMEOUT_MS2) {
2655
+ throw new CofheError({
2656
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
2657
+ message: `decrypt polling timed out after ${POLL_TIMEOUT_MS2}ms`,
2658
+ hint: "The request may still be processing. Try again later.",
2659
+ context: {
2660
+ thresholdNetworkUrl,
2661
+ requestId,
2662
+ timeoutMs: POLL_TIMEOUT_MS2
2663
+ }
2664
+ });
2665
+ }
2666
+ let response;
2667
+ try {
2668
+ response = await fetch(`${thresholdNetworkUrl}/v2/decrypt/${requestId}`, {
2669
+ method: "GET",
2670
+ headers: {
2671
+ "Content-Type": "application/json"
2672
+ }
2673
+ });
2674
+ } catch (e) {
2675
+ throw new CofheError({
2676
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
2677
+ message: `decrypt status poll failed`,
2678
+ hint: "Ensure the threshold network URL is valid and reachable.",
2679
+ cause: e instanceof Error ? e : void 0,
2680
+ context: {
2681
+ thresholdNetworkUrl,
2682
+ requestId
2683
+ }
2684
+ });
2685
+ }
2686
+ if (response.status === 404) {
2687
+ throw new CofheError({
2688
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
2689
+ message: `decrypt request not found: ${requestId}`,
2690
+ hint: "The request may have expired or been invalid.",
2691
+ context: {
2692
+ thresholdNetworkUrl,
2693
+ requestId
2694
+ }
2695
+ });
2696
+ }
2697
+ if (!response.ok) {
2698
+ let errorMessage = `HTTP ${response.status}`;
2699
+ try {
2700
+ const errorBody = await response.json();
2701
+ const maybeMessage = errorBody.error_message || errorBody.message;
2702
+ if (typeof maybeMessage === "string" && maybeMessage.length > 0)
2703
+ errorMessage = maybeMessage;
2704
+ } catch {
2705
+ errorMessage = response.statusText || errorMessage;
2641
2706
  }
2642
- });
2707
+ throw new CofheError({
2708
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
2709
+ message: `decrypt status poll failed: ${errorMessage}`,
2710
+ context: {
2711
+ thresholdNetworkUrl,
2712
+ requestId,
2713
+ status: response.status,
2714
+ statusText: response.statusText
2715
+ }
2716
+ });
2717
+ }
2718
+ let rawJson;
2719
+ try {
2720
+ rawJson = await response.json();
2721
+ } catch (e) {
2722
+ throw new CofheError({
2723
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
2724
+ message: `Failed to parse decrypt status response`,
2725
+ cause: e instanceof Error ? e : void 0,
2726
+ context: {
2727
+ thresholdNetworkUrl,
2728
+ requestId
2729
+ }
2730
+ });
2731
+ }
2732
+ const statusResponse = assertDecryptStatusResponseV2(rawJson);
2733
+ if (statusResponse.status === "COMPLETED") {
2734
+ if (statusResponse.is_succeed === false) {
2735
+ const errorMessage = statusResponse.error_message || "Unknown error";
2736
+ throw new CofheError({
2737
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
2738
+ message: `decrypt request failed: ${errorMessage}`,
2739
+ context: {
2740
+ thresholdNetworkUrl,
2741
+ requestId,
2742
+ statusResponse
2743
+ }
2744
+ });
2745
+ }
2746
+ if (statusResponse.error_message) {
2747
+ throw new CofheError({
2748
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
2749
+ message: `decrypt request failed: ${statusResponse.error_message}`,
2750
+ context: {
2751
+ thresholdNetworkUrl,
2752
+ requestId,
2753
+ statusResponse
2754
+ }
2755
+ });
2756
+ }
2757
+ if (!Array.isArray(statusResponse.decrypted)) {
2758
+ throw new CofheError({
2759
+ code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2760
+ message: "decrypt completed but response missing <decrypted> byte array",
2761
+ context: {
2762
+ thresholdNetworkUrl,
2763
+ requestId,
2764
+ statusResponse
2765
+ }
2766
+ });
2767
+ }
2768
+ const decryptedValue = parseDecryptedBytesToBigInt(statusResponse.decrypted);
2769
+ const signature = normalizeTnSignature(statusResponse.signature);
2770
+ return { decryptedValue, signature };
2771
+ }
2772
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS2));
2643
2773
  }
2644
- const decryptedValue = parseDecryptedBytesToBigInt(decryptResponse.decrypted);
2645
- const signature = normalizeSignature(decryptResponse.signature);
2646
- return { decryptedValue, signature };
2774
+ throw new CofheError({
2775
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
2776
+ message: "Polling loop exited unexpectedly",
2777
+ context: {
2778
+ thresholdNetworkUrl,
2779
+ requestId
2780
+ }
2781
+ });
2782
+ }
2783
+ async function tnDecryptV2(ctHash, chainId, permission, thresholdNetworkUrl) {
2784
+ const requestId = await submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, permission);
2785
+ return await pollDecryptStatusV2(thresholdNetworkUrl, requestId);
2647
2786
  }
2648
2787
 
2649
2788
  // core/decrypt/decryptForTxBuilder.ts
@@ -2804,7 +2943,7 @@ var DecryptForTxBuilder = class extends BaseBuilder {
2804
2943
  this.assertPublicClient();
2805
2944
  const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
2806
2945
  const permission = permit ? PermitUtils.getPermission(permit, true) : null;
2807
- const { decryptedValue, signature } = await tnDecrypt(this.ctHash, this.chainId, permission, thresholdNetworkUrl);
2946
+ const { decryptedValue, signature } = await tnDecryptV2(this.ctHash, this.chainId, permission, thresholdNetworkUrl);
2808
2947
  return {
2809
2948
  ctHash: this.ctHash,
2810
2949
  decryptedValue,
@@ -3012,19 +3151,19 @@ function createCofheClientBase(opts) {
3012
3151
  return permits.getOrCreateSharingPermit(publicClient, walletClient, options, _chainId, _account);
3013
3152
  },
3014
3153
  // Retrieval methods (auto-fill chainId/account)
3015
- getPermit: async (hash, chainId, account) => {
3154
+ getPermit: (hash, chainId, account) => {
3016
3155
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3017
3156
  return permits.getPermit(_chainId, _account, hash);
3018
3157
  },
3019
- getPermits: async (chainId, account) => {
3158
+ getPermits: (chainId, account) => {
3020
3159
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3021
3160
  return permits.getPermits(_chainId, _account);
3022
3161
  },
3023
- getActivePermit: async (chainId, account) => {
3162
+ getActivePermit: (chainId, account) => {
3024
3163
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3025
3164
  return permits.getActivePermit(_chainId, _account);
3026
3165
  },
3027
- getActivePermitHash: async (chainId, account) => {
3166
+ getActivePermitHash: (chainId, account) => {
3028
3167
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3029
3168
  return permits.getActivePermitHash(_chainId, _account);
3030
3169
  },
@@ -165,6 +165,14 @@ type EncryptStepCallbackContext = Record<string, any> & {
165
165
  duration: number;
166
166
  };
167
167
  type EncryptStepCallbackFunction = (state: EncryptStep, context?: EncryptStepCallbackContext) => void;
168
+ /**
169
+ * Decrypted plaintext value returned by view-decryption helpers.
170
+ *
171
+ * This is a scalar JS value (not a wrapper object):
172
+ * - `boolean` for `FheTypes.Bool`
173
+ * - checksummed address `string` for `FheTypes.Uint160`
174
+ * - `bigint` for supported integer utypes
175
+ */
168
176
  type UnsealedItem<U extends FheTypes> = U extends FheTypes.Bool ? boolean : U extends FheTypes.Uint160 ? string : U extends FheUintUTypesType ? bigint : never;
169
177
 
170
178
  /**
@@ -894,9 +902,9 @@ declare const permits: {
894
902
  getHash: (permit: PermitHashFields) => string;
895
903
  serialize: (permit: Permit) => SerializedPermit;
896
904
  deserialize: (serialized: SerializedPermit) => Permit;
897
- getPermit: (chainId: number, account: string, hash: string) => Promise<Permit | undefined>;
898
- getPermits: (chainId: number, account: string) => Promise<Record<string, Permit>>;
899
- getActivePermit: (chainId: number, account: string) => Promise<Permit | undefined>;
905
+ getPermit: (chainId: number, account: string, hash: string) => Permit | undefined;
906
+ getPermits: (chainId: number, account: string) => Record<string, Permit>;
907
+ getActivePermit: (chainId: number, account: string) => Permit | undefined;
900
908
  getActivePermitHash: (chainId: number, account: string) => string | undefined;
901
909
  removePermit: (chainId: number, account: string, hash: string) => Promise<void>;
902
910
  selectActivePermit: (chainId: number, account: string, hash: string) => void;
@@ -949,10 +957,10 @@ type CofheClientPermits = {
949
957
  createSelf: (options: CreateSelfPermitOptions, clients?: CofheClientPermitsClients) => Promise<SelfPermit>;
950
958
  createSharing: (options: CreateSharingPermitOptions, clients?: CofheClientPermitsClients) => Promise<SharingPermit>;
951
959
  importShared: (options: ImportSharedPermitOptions | string, clients?: CofheClientPermitsClients) => Promise<RecipientPermit>;
952
- getPermit: (hash: string, chainId?: number, account?: string) => Promise<Permit | undefined>;
953
- getPermits: (chainId?: number, account?: string) => Promise<Record<string, Permit>>;
954
- getActivePermit: (chainId?: number, account?: string) => Promise<Permit | undefined>;
955
- getActivePermitHash: (chainId?: number, account?: string) => Promise<string | undefined>;
960
+ getPermit: (hash: string, chainId?: number, account?: string) => Permit | undefined;
961
+ getPermits: (chainId?: number, account?: string) => Record<string, Permit>;
962
+ getActivePermit: (chainId?: number, account?: string) => Permit | undefined;
963
+ getActivePermitHash: (chainId?: number, account?: string) => string | undefined;
956
964
  getOrCreateSelfPermit: (chainId?: number, account?: string, options?: CreateSelfPermitOptions) => Promise<Permit>;
957
965
  getOrCreateSharingPermit: (options: CreateSharingPermitOptions, chainId?: number, account?: string) => Promise<Permit>;
958
966
  selectActivePermit: (hash: string, chainId?: number, account?: string) => void;
@@ -165,6 +165,14 @@ type EncryptStepCallbackContext = Record<string, any> & {
165
165
  duration: number;
166
166
  };
167
167
  type EncryptStepCallbackFunction = (state: EncryptStep, context?: EncryptStepCallbackContext) => void;
168
+ /**
169
+ * Decrypted plaintext value returned by view-decryption helpers.
170
+ *
171
+ * This is a scalar JS value (not a wrapper object):
172
+ * - `boolean` for `FheTypes.Bool`
173
+ * - checksummed address `string` for `FheTypes.Uint160`
174
+ * - `bigint` for supported integer utypes
175
+ */
168
176
  type UnsealedItem<U extends FheTypes> = U extends FheTypes.Bool ? boolean : U extends FheTypes.Uint160 ? string : U extends FheUintUTypesType ? bigint : never;
169
177
 
170
178
  /**
@@ -894,9 +902,9 @@ declare const permits: {
894
902
  getHash: (permit: PermitHashFields) => string;
895
903
  serialize: (permit: Permit) => SerializedPermit;
896
904
  deserialize: (serialized: SerializedPermit) => Permit;
897
- getPermit: (chainId: number, account: string, hash: string) => Promise<Permit | undefined>;
898
- getPermits: (chainId: number, account: string) => Promise<Record<string, Permit>>;
899
- getActivePermit: (chainId: number, account: string) => Promise<Permit | undefined>;
905
+ getPermit: (chainId: number, account: string, hash: string) => Permit | undefined;
906
+ getPermits: (chainId: number, account: string) => Record<string, Permit>;
907
+ getActivePermit: (chainId: number, account: string) => Permit | undefined;
900
908
  getActivePermitHash: (chainId: number, account: string) => string | undefined;
901
909
  removePermit: (chainId: number, account: string, hash: string) => Promise<void>;
902
910
  selectActivePermit: (chainId: number, account: string, hash: string) => void;
@@ -949,10 +957,10 @@ type CofheClientPermits = {
949
957
  createSelf: (options: CreateSelfPermitOptions, clients?: CofheClientPermitsClients) => Promise<SelfPermit>;
950
958
  createSharing: (options: CreateSharingPermitOptions, clients?: CofheClientPermitsClients) => Promise<SharingPermit>;
951
959
  importShared: (options: ImportSharedPermitOptions | string, clients?: CofheClientPermitsClients) => Promise<RecipientPermit>;
952
- getPermit: (hash: string, chainId?: number, account?: string) => Promise<Permit | undefined>;
953
- getPermits: (chainId?: number, account?: string) => Promise<Record<string, Permit>>;
954
- getActivePermit: (chainId?: number, account?: string) => Promise<Permit | undefined>;
955
- getActivePermitHash: (chainId?: number, account?: string) => Promise<string | undefined>;
960
+ getPermit: (hash: string, chainId?: number, account?: string) => Permit | undefined;
961
+ getPermits: (chainId?: number, account?: string) => Record<string, Permit>;
962
+ getActivePermit: (chainId?: number, account?: string) => Permit | undefined;
963
+ getActivePermitHash: (chainId?: number, account?: string) => string | undefined;
956
964
  getOrCreateSelfPermit: (chainId?: number, account?: string, options?: CreateSelfPermitOptions) => Promise<Permit>;
957
965
  getOrCreateSharingPermit: (options: CreateSharingPermitOptions, chainId?: number, account?: string) => Promise<Permit>;
958
966
  selectActivePermit: (hash: string, chainId?: number, account?: string) => void;