@cofhe/sdk 0.3.1 → 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.
package/dist/web.cjs CHANGED
@@ -652,7 +652,7 @@ async function insertCtHashes(items, walletClient) {
652
652
  });
653
653
  }
654
654
  }
655
- async function createProofSignatures(items, securityZone) {
655
+ async function createProofSignatures(items, securityZone, account) {
656
656
  let signatures = [];
657
657
  let encInputSignerClient;
658
658
  try {
@@ -669,12 +669,15 @@ async function createProofSignatures(items, securityZone) {
669
669
  }
670
670
  try {
671
671
  for (const item of items) {
672
- const packedData = viem.encodePacked(["uint256", "int32", "uint8"], [BigInt(item.data), securityZone, item.utype]);
672
+ const packedData = viem.encodePacked(
673
+ ["uint256", "uint8", "uint8", "address", "uint256"],
674
+ [BigInt(item.ctHash), item.utype, securityZone, account, BigInt(chains.hardhat.id)]
675
+ );
673
676
  const messageHash = viem.keccak256(packedData);
674
- const ethSignedHash = viem.hashMessage({ raw: viem.toBytes(messageHash) });
675
- const signature = await encInputSignerClient.signMessage({
676
- message: { raw: viem.toBytes(ethSignedHash) },
677
- account: encInputSignerClient.account
677
+ const signature = await accounts.sign({
678
+ hash: messageHash,
679
+ privateKey: MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY,
680
+ to: "hex"
678
681
  });
679
682
  signatures.push(signature);
680
683
  }
@@ -705,7 +708,7 @@ async function cofheMocksZkVerifySign(items, account, securityZone, publicClient
705
708
  const _walletClient = zkvWalletClient ?? createMockZkVerifierSigner();
706
709
  const encryptableItems = await calcCtHashes(items, account, securityZone, publicClient);
707
710
  await insertCtHashes(encryptableItems, _walletClient);
708
- const signatures = await createProofSignatures(encryptableItems, securityZone);
711
+ const signatures = await createProofSignatures(encryptableItems, securityZone, account);
709
712
  return encryptableItems.map((item, index) => ({
710
713
  ct_hash: item.ctHash.toString(),
711
714
  signature: signatures[index]
@@ -2510,13 +2513,13 @@ var serialize = (permit) => {
2510
2513
  var deserialize = (serialized) => {
2511
2514
  return PermitUtils.deserialize(serialized);
2512
2515
  };
2513
- var getPermit2 = async (chainId, account, hash) => {
2516
+ var getPermit2 = (chainId, account, hash) => {
2514
2517
  return permitStore.getPermit(chainId, account, hash);
2515
2518
  };
2516
- var getPermits2 = async (chainId, account) => {
2519
+ var getPermits2 = (chainId, account) => {
2517
2520
  return permitStore.getPermits(chainId, account);
2518
2521
  };
2519
- var getActivePermit2 = async (chainId, account) => {
2522
+ var getActivePermit2 = (chainId, account) => {
2520
2523
  return permitStore.getActivePermit(chainId, account);
2521
2524
  };
2522
2525
  var getActivePermitHash2 = (chainId, account) => {
@@ -2765,9 +2768,7 @@ var MockThresholdNetworkAbi = [
2765
2768
  ];
2766
2769
 
2767
2770
  // core/decrypt/cofheMocksDecryptForView.ts
2768
- async function cofheMocksDecryptForView(ctHash, utype, permit, publicClient, mocksDecryptDelay) {
2769
- if (mocksDecryptDelay > 0)
2770
- await sleep(mocksDecryptDelay);
2771
+ async function cofheMocksDecryptForView(ctHash, utype, permit, publicClient) {
2771
2772
  const permission = PermitUtils.getPermission(permit, true);
2772
2773
  const permissionWithBigInts = {
2773
2774
  ...permission,
@@ -2778,7 +2779,7 @@ async function cofheMocksDecryptForView(ctHash, utype, permit, publicClient, moc
2778
2779
  address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
2779
2780
  abi: MockThresholdNetworkAbi,
2780
2781
  functionName: "querySealOutput",
2781
- args: [ctHash, BigInt(utype), permissionWithBigInts]
2782
+ args: [BigInt(ctHash), BigInt(utype), permissionWithBigInts]
2782
2783
  });
2783
2784
  if (error != "") {
2784
2785
  throw new CofheError({
@@ -2819,7 +2820,7 @@ function convertSealedData(sealed) {
2819
2820
  }
2820
2821
  async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission) {
2821
2822
  const body = {
2822
- ct_tempkey: ctHash.toString(16).padStart(64, "0"),
2823
+ ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
2823
2824
  host_chain_id: chainId,
2824
2825
  permit: permission
2825
2826
  };
@@ -3012,96 +3013,6 @@ async function tnSealOutputV2(ctHash, chainId, permission, thresholdNetworkUrl)
3012
3013
  const requestId = await submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission);
3013
3014
  return await pollSealOutputStatus(thresholdNetworkUrl, requestId);
3014
3015
  }
3015
- async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient, mocksDecryptForTxDelay) {
3016
- if (mocksDecryptForTxDelay > 0)
3017
- await sleep(mocksDecryptForTxDelay);
3018
- if (permit !== null) {
3019
- let permission = PermitUtils.getPermission(permit, true);
3020
- const permissionWithBigInts = {
3021
- ...permission,
3022
- expiration: BigInt(permission.expiration),
3023
- validatorId: BigInt(permission.validatorId)
3024
- };
3025
- const [allowed2, error2, result2] = await publicClient.readContract({
3026
- address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
3027
- abi: MockThresholdNetworkAbi,
3028
- functionName: "decryptForTxWithPermit",
3029
- args: [ctHash, permissionWithBigInts]
3030
- });
3031
- if (error2 != "") {
3032
- throw new CofheError({
3033
- code: "DECRYPT_FAILED" /* DecryptFailed */,
3034
- message: `mocks decryptForTx call failed: ${error2}`
3035
- });
3036
- }
3037
- if (allowed2 == false) {
3038
- throw new CofheError({
3039
- code: "DECRYPT_FAILED" /* DecryptFailed */,
3040
- message: `mocks decryptForTx call failed: ACL Access Denied (NotAllowed)`
3041
- });
3042
- }
3043
- const chainId2 = await publicClient.getChainId();
3044
- const ctHashBigInt2 = BigInt(ctHash);
3045
- const resultBigInt2 = BigInt(result2);
3046
- const encryptionType2 = Number((ctHashBigInt2 & 0x7fn << 8n) >> 8n);
3047
- const ctHashBytes322 = viem.pad(viem.toHex(ctHashBigInt2), { size: 32 });
3048
- const packed2 = viem.encodePacked(
3049
- ["uint256", "uint32", "uint64", "bytes32"],
3050
- [resultBigInt2, encryptionType2, BigInt(chainId2), ctHashBytes322]
3051
- );
3052
- const messageHash2 = viem.keccak256(packed2);
3053
- const signatureHex2 = await accounts.sign({
3054
- hash: messageHash2,
3055
- privateKey: MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY,
3056
- to: "hex"
3057
- });
3058
- const signature2 = signatureHex2.slice(2);
3059
- return {
3060
- ctHash,
3061
- decryptedValue: BigInt(result2),
3062
- signature: signature2
3063
- };
3064
- }
3065
- const [allowed, error, result] = await publicClient.readContract({
3066
- address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
3067
- abi: MockThresholdNetworkAbi,
3068
- functionName: "decryptForTxWithoutPermit",
3069
- args: [ctHash]
3070
- });
3071
- if (error != "") {
3072
- throw new CofheError({
3073
- code: "DECRYPT_FAILED" /* DecryptFailed */,
3074
- message: `mocks decryptForTx call failed: ${error}`
3075
- });
3076
- }
3077
- if (allowed == false) {
3078
- throw new CofheError({
3079
- code: "DECRYPT_FAILED" /* DecryptFailed */,
3080
- message: `mocks decryptForTx call failed: ACL Access Denied (NotAllowed)`
3081
- });
3082
- }
3083
- const chainId = await publicClient.getChainId();
3084
- const ctHashBigInt = BigInt(ctHash);
3085
- const resultBigInt = BigInt(result);
3086
- const encryptionType = Number((ctHashBigInt & 0x7fn << 8n) >> 8n);
3087
- const ctHashBytes32 = viem.pad(viem.toHex(ctHashBigInt), { size: 32 });
3088
- const packed = viem.encodePacked(
3089
- ["uint256", "uint32", "uint64", "bytes32"],
3090
- [resultBigInt, encryptionType, BigInt(chainId), ctHashBytes32]
3091
- );
3092
- const messageHash = viem.keccak256(packed);
3093
- const signatureHex = await accounts.sign({
3094
- hash: messageHash,
3095
- privateKey: MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY,
3096
- to: "hex"
3097
- });
3098
- const signature = signatureHex.slice(2);
3099
- return {
3100
- ctHash,
3101
- decryptedValue: BigInt(result),
3102
- signature
3103
- };
3104
- }
3105
3016
 
3106
3017
  // core/decrypt/decryptForViewBuilder.ts
3107
3018
  var DecryptForViewBuilder = class extends BaseBuilder {
@@ -3276,7 +3187,9 @@ var DecryptForViewBuilder = class extends BaseBuilder {
3276
3187
  async mocksSealOutput(permit) {
3277
3188
  this.assertPublicClient();
3278
3189
  const mocksDecryptDelay = this.config.mocks.decryptDelay;
3279
- return cofheMocksDecryptForView(this.ctHash, this.utype, permit, this.publicClient, mocksDecryptDelay);
3190
+ if (mocksDecryptDelay > 0)
3191
+ await sleep(mocksDecryptDelay);
3192
+ return cofheMocksDecryptForView(this.ctHash, this.utype, permit, this.publicClient);
3280
3193
  }
3281
3194
  /**
3282
3195
  * In the production context, perform a true decryption with the CoFHE coprocessor.
@@ -3325,9 +3238,57 @@ var DecryptForViewBuilder = class extends BaseBuilder {
3325
3238
  return convertViaUtype(this.utype, unsealed);
3326
3239
  }
3327
3240
  };
3328
-
3329
- // core/decrypt/tnDecrypt.ts
3330
- function normalizeSignature(signature) {
3241
+ async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient) {
3242
+ let allowed;
3243
+ let error;
3244
+ let decryptedValue;
3245
+ if (permit !== null) {
3246
+ let permission = PermitUtils.getPermission(permit, true);
3247
+ const permissionWithBigInts = {
3248
+ ...permission,
3249
+ expiration: BigInt(permission.expiration),
3250
+ validatorId: BigInt(permission.validatorId)
3251
+ };
3252
+ [allowed, error, decryptedValue] = await publicClient.readContract({
3253
+ address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
3254
+ abi: MockThresholdNetworkAbi,
3255
+ functionName: "decryptForTxWithPermit",
3256
+ args: [BigInt(ctHash), permissionWithBigInts]
3257
+ });
3258
+ } else {
3259
+ [allowed, error, decryptedValue] = await publicClient.readContract({
3260
+ address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
3261
+ abi: MockThresholdNetworkAbi,
3262
+ functionName: "decryptForTxWithoutPermit",
3263
+ args: [BigInt(ctHash)]
3264
+ });
3265
+ }
3266
+ if (error != "") {
3267
+ throw new CofheError({
3268
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
3269
+ message: `mocks decryptForTx call failed: ${error}`
3270
+ });
3271
+ }
3272
+ if (allowed == false) {
3273
+ throw new CofheError({
3274
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
3275
+ message: `mocks decryptForTx call failed: ACL Access Denied (NotAllowed)`
3276
+ });
3277
+ }
3278
+ const packed = viem.encodePacked(["uint256", "uint256"], [BigInt(ctHash), decryptedValue]);
3279
+ const messageHash = viem.keccak256(packed);
3280
+ const signature = await accounts.sign({
3281
+ hash: messageHash,
3282
+ privateKey: MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY,
3283
+ to: "hex"
3284
+ });
3285
+ return {
3286
+ ctHash,
3287
+ decryptedValue,
3288
+ signature
3289
+ };
3290
+ }
3291
+ function normalizeTnSignature(signature) {
3331
3292
  if (typeof signature !== "string") {
3332
3293
  throw new CofheError({
3333
3294
  code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
@@ -3344,7 +3305,9 @@ function normalizeSignature(signature) {
3344
3305
  message: "decrypt response returned empty signature"
3345
3306
  });
3346
3307
  }
3347
- return trimmed.startsWith("0x") ? trimmed.slice(2) : trimmed;
3308
+ const prefixed = trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
3309
+ const parsed = viem.parseSignature(prefixed);
3310
+ return viem.serializeSignature(parsed);
3348
3311
  }
3349
3312
  function parseDecryptedBytesToBigInt(decrypted) {
3350
3313
  if (!Array.isArray(decrypted)) {
@@ -3381,59 +3344,79 @@ function parseDecryptedBytesToBigInt(decrypted) {
3381
3344
  }
3382
3345
  return BigInt(`0x${hex}`);
3383
3346
  }
3384
- function assertTnDecryptResponse(value) {
3347
+
3348
+ // core/decrypt/tnDecryptV2.ts
3349
+ var POLL_INTERVAL_MS2 = 1e3;
3350
+ var POLL_TIMEOUT_MS2 = 5 * 60 * 1e3;
3351
+ function assertDecryptSubmitResponseV2(value) {
3385
3352
  if (value == null || typeof value !== "object") {
3386
3353
  throw new CofheError({
3387
3354
  code: "DECRYPT_FAILED" /* DecryptFailed */,
3388
- message: "decrypt response must be a JSON object",
3355
+ message: "decrypt submit response must be a JSON object",
3389
3356
  context: {
3390
3357
  value
3391
3358
  }
3392
3359
  });
3393
3360
  }
3394
3361
  const v = value;
3395
- const decrypted = v.decrypted;
3396
- const signature = v.signature;
3397
- const encryptionType = v.encryption_type;
3398
- const errorMessage = v.error_message;
3399
- if (!Array.isArray(decrypted)) {
3362
+ if (typeof v.request_id !== "string" || v.request_id.trim().length === 0) {
3400
3363
  throw new CofheError({
3401
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
3402
- message: "decrypt response missing <decrypted> byte array",
3403
- context: { decryptResponse: value }
3364
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
3365
+ message: "decrypt submit response missing request_id",
3366
+ context: {
3367
+ value
3368
+ }
3404
3369
  });
3405
3370
  }
3406
- if (typeof signature !== "string") {
3371
+ return { request_id: v.request_id };
3372
+ }
3373
+ function assertDecryptStatusResponseV2(value) {
3374
+ if (value == null || typeof value !== "object") {
3407
3375
  throw new CofheError({
3408
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
3409
- message: "decrypt response missing <signature> string",
3410
- context: { decryptResponse: value }
3376
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
3377
+ message: "decrypt status response must be a JSON object",
3378
+ context: {
3379
+ value
3380
+ }
3411
3381
  });
3412
3382
  }
3413
- if (typeof encryptionType !== "number") {
3383
+ const v = value;
3384
+ const requestId = v.request_id;
3385
+ const status = v.status;
3386
+ const submittedAt = v.submitted_at;
3387
+ if (typeof requestId !== "string" || requestId.trim().length === 0) {
3414
3388
  throw new CofheError({
3415
3389
  code: "DECRYPT_FAILED" /* DecryptFailed */,
3416
- message: "decrypt response missing <encryption_type> number",
3417
- context: { decryptResponse: value }
3390
+ message: "decrypt status response missing request_id",
3391
+ context: {
3392
+ value
3393
+ }
3418
3394
  });
3419
3395
  }
3420
- if (!(typeof errorMessage === "string" || errorMessage === null)) {
3396
+ if (status !== "PROCESSING" && status !== "COMPLETED") {
3421
3397
  throw new CofheError({
3422
3398
  code: "DECRYPT_FAILED" /* DecryptFailed */,
3423
- message: "decrypt response field <error_message> must be string or null",
3424
- context: { decryptResponse: value }
3399
+ message: "decrypt status response has invalid status",
3400
+ context: {
3401
+ value,
3402
+ status
3403
+ }
3425
3404
  });
3426
3405
  }
3427
- return {
3428
- decrypted,
3429
- signature,
3430
- encryption_type: encryptionType,
3431
- error_message: errorMessage
3432
- };
3406
+ if (typeof submittedAt !== "string" || submittedAt.trim().length === 0) {
3407
+ throw new CofheError({
3408
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
3409
+ message: "decrypt status response missing submitted_at",
3410
+ context: {
3411
+ value
3412
+ }
3413
+ });
3414
+ }
3415
+ return value;
3433
3416
  }
3434
- async function tnDecrypt(ctHash, chainId, permission, thresholdNetworkUrl) {
3417
+ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, permission) {
3435
3418
  const body = {
3436
- ct_tempkey: ctHash.toString(16).padStart(64, "0"),
3419
+ ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
3437
3420
  host_chain_id: chainId
3438
3421
  };
3439
3422
  if (permission) {
@@ -3441,7 +3424,7 @@ async function tnDecrypt(ctHash, chainId, permission, thresholdNetworkUrl) {
3441
3424
  }
3442
3425
  let response;
3443
3426
  try {
3444
- response = await fetch(`${thresholdNetworkUrl}/decrypt`, {
3427
+ response = await fetch(`${thresholdNetworkUrl}/v2/decrypt`, {
3445
3428
  method: "POST",
3446
3429
  headers: {
3447
3430
  "Content-Type": "application/json"
@@ -3460,18 +3443,15 @@ async function tnDecrypt(ctHash, chainId, permission, thresholdNetworkUrl) {
3460
3443
  }
3461
3444
  });
3462
3445
  }
3463
- const responseText = await response.text();
3464
3446
  if (!response.ok) {
3465
- let errorMessage = response.statusText || `HTTP ${response.status}`;
3447
+ let errorMessage = `HTTP ${response.status}`;
3466
3448
  try {
3467
- const errorBody = JSON.parse(responseText);
3449
+ const errorBody = await response.json();
3468
3450
  const maybeMessage = errorBody.error_message || errorBody.message;
3469
3451
  if (typeof maybeMessage === "string" && maybeMessage.length > 0)
3470
3452
  errorMessage = maybeMessage;
3471
3453
  } catch {
3472
- const trimmed = responseText.trim();
3473
- if (trimmed.length > 0)
3474
- errorMessage = trimmed;
3454
+ errorMessage = response.statusText || errorMessage;
3475
3455
  }
3476
3456
  throw new CofheError({
3477
3457
  code: "DECRYPT_FAILED" /* DecryptFailed */,
@@ -3481,41 +3461,163 @@ async function tnDecrypt(ctHash, chainId, permission, thresholdNetworkUrl) {
3481
3461
  thresholdNetworkUrl,
3482
3462
  status: response.status,
3483
3463
  statusText: response.statusText,
3484
- body,
3485
- responseText
3464
+ body
3486
3465
  }
3487
3466
  });
3488
3467
  }
3489
3468
  let rawJson;
3490
3469
  try {
3491
- rawJson = JSON.parse(responseText);
3470
+ rawJson = await response.json();
3492
3471
  } catch (e) {
3493
3472
  throw new CofheError({
3494
3473
  code: "DECRYPT_FAILED" /* DecryptFailed */,
3495
- message: `Failed to parse decrypt response`,
3474
+ message: `Failed to parse decrypt submit response`,
3496
3475
  cause: e instanceof Error ? e : void 0,
3497
3476
  context: {
3498
3477
  thresholdNetworkUrl,
3499
- body,
3500
- responseText
3478
+ body
3501
3479
  }
3502
3480
  });
3503
3481
  }
3504
- const decryptResponse = assertTnDecryptResponse(rawJson);
3505
- if (decryptResponse.error_message) {
3506
- throw new CofheError({
3507
- code: "DECRYPT_FAILED" /* DecryptFailed */,
3508
- message: `decrypt request failed: ${decryptResponse.error_message}`,
3509
- context: {
3510
- thresholdNetworkUrl,
3511
- body,
3512
- decryptResponse
3482
+ const submitResponse = assertDecryptSubmitResponseV2(rawJson);
3483
+ return submitResponse.request_id;
3484
+ }
3485
+ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId) {
3486
+ const startTime = Date.now();
3487
+ let completed = false;
3488
+ while (!completed) {
3489
+ if (Date.now() - startTime > POLL_TIMEOUT_MS2) {
3490
+ throw new CofheError({
3491
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
3492
+ message: `decrypt polling timed out after ${POLL_TIMEOUT_MS2}ms`,
3493
+ hint: "The request may still be processing. Try again later.",
3494
+ context: {
3495
+ thresholdNetworkUrl,
3496
+ requestId,
3497
+ timeoutMs: POLL_TIMEOUT_MS2
3498
+ }
3499
+ });
3500
+ }
3501
+ let response;
3502
+ try {
3503
+ response = await fetch(`${thresholdNetworkUrl}/v2/decrypt/${requestId}`, {
3504
+ method: "GET",
3505
+ headers: {
3506
+ "Content-Type": "application/json"
3507
+ }
3508
+ });
3509
+ } catch (e) {
3510
+ throw new CofheError({
3511
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
3512
+ message: `decrypt status poll failed`,
3513
+ hint: "Ensure the threshold network URL is valid and reachable.",
3514
+ cause: e instanceof Error ? e : void 0,
3515
+ context: {
3516
+ thresholdNetworkUrl,
3517
+ requestId
3518
+ }
3519
+ });
3520
+ }
3521
+ if (response.status === 404) {
3522
+ throw new CofheError({
3523
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
3524
+ message: `decrypt request not found: ${requestId}`,
3525
+ hint: "The request may have expired or been invalid.",
3526
+ context: {
3527
+ thresholdNetworkUrl,
3528
+ requestId
3529
+ }
3530
+ });
3531
+ }
3532
+ if (!response.ok) {
3533
+ let errorMessage = `HTTP ${response.status}`;
3534
+ try {
3535
+ const errorBody = await response.json();
3536
+ const maybeMessage = errorBody.error_message || errorBody.message;
3537
+ if (typeof maybeMessage === "string" && maybeMessage.length > 0)
3538
+ errorMessage = maybeMessage;
3539
+ } catch {
3540
+ errorMessage = response.statusText || errorMessage;
3513
3541
  }
3514
- });
3542
+ throw new CofheError({
3543
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
3544
+ message: `decrypt status poll failed: ${errorMessage}`,
3545
+ context: {
3546
+ thresholdNetworkUrl,
3547
+ requestId,
3548
+ status: response.status,
3549
+ statusText: response.statusText
3550
+ }
3551
+ });
3552
+ }
3553
+ let rawJson;
3554
+ try {
3555
+ rawJson = await response.json();
3556
+ } catch (e) {
3557
+ throw new CofheError({
3558
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
3559
+ message: `Failed to parse decrypt status response`,
3560
+ cause: e instanceof Error ? e : void 0,
3561
+ context: {
3562
+ thresholdNetworkUrl,
3563
+ requestId
3564
+ }
3565
+ });
3566
+ }
3567
+ const statusResponse = assertDecryptStatusResponseV2(rawJson);
3568
+ if (statusResponse.status === "COMPLETED") {
3569
+ if (statusResponse.is_succeed === false) {
3570
+ const errorMessage = statusResponse.error_message || "Unknown error";
3571
+ throw new CofheError({
3572
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
3573
+ message: `decrypt request failed: ${errorMessage}`,
3574
+ context: {
3575
+ thresholdNetworkUrl,
3576
+ requestId,
3577
+ statusResponse
3578
+ }
3579
+ });
3580
+ }
3581
+ if (statusResponse.error_message) {
3582
+ throw new CofheError({
3583
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
3584
+ message: `decrypt request failed: ${statusResponse.error_message}`,
3585
+ context: {
3586
+ thresholdNetworkUrl,
3587
+ requestId,
3588
+ statusResponse
3589
+ }
3590
+ });
3591
+ }
3592
+ if (!Array.isArray(statusResponse.decrypted)) {
3593
+ throw new CofheError({
3594
+ code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
3595
+ message: "decrypt completed but response missing <decrypted> byte array",
3596
+ context: {
3597
+ thresholdNetworkUrl,
3598
+ requestId,
3599
+ statusResponse
3600
+ }
3601
+ });
3602
+ }
3603
+ const decryptedValue = parseDecryptedBytesToBigInt(statusResponse.decrypted);
3604
+ const signature = normalizeTnSignature(statusResponse.signature);
3605
+ return { decryptedValue, signature };
3606
+ }
3607
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS2));
3515
3608
  }
3516
- const decryptedValue = parseDecryptedBytesToBigInt(decryptResponse.decrypted);
3517
- const signature = normalizeSignature(decryptResponse.signature);
3518
- return { decryptedValue, signature };
3609
+ throw new CofheError({
3610
+ code: "DECRYPT_FAILED" /* DecryptFailed */,
3611
+ message: "Polling loop exited unexpectedly",
3612
+ context: {
3613
+ thresholdNetworkUrl,
3614
+ requestId
3615
+ }
3616
+ });
3617
+ }
3618
+ async function tnDecryptV2(ctHash, chainId, permission, thresholdNetworkUrl) {
3619
+ const requestId = await submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, permission);
3620
+ return await pollDecryptStatusV2(thresholdNetworkUrl, requestId);
3519
3621
  }
3520
3622
 
3521
3623
  // core/decrypt/decryptForTxBuilder.ts
@@ -3663,7 +3765,9 @@ var DecryptForTxBuilder = class extends BaseBuilder {
3663
3765
  async mocksDecryptForTx(permit) {
3664
3766
  this.assertPublicClient();
3665
3767
  const delay = this.config.mocks.decryptDelay;
3666
- const result = await cofheMocksDecryptForTx(this.ctHash, 0, permit, this.publicClient, delay);
3768
+ if (delay > 0)
3769
+ await sleep(delay);
3770
+ const result = await cofheMocksDecryptForTx(this.ctHash, 0, permit, this.publicClient);
3667
3771
  return result;
3668
3772
  }
3669
3773
  /**
@@ -3674,7 +3778,7 @@ var DecryptForTxBuilder = class extends BaseBuilder {
3674
3778
  this.assertPublicClient();
3675
3779
  const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
3676
3780
  const permission = permit ? PermitUtils.getPermission(permit, true) : null;
3677
- const { decryptedValue, signature } = await tnDecrypt(this.ctHash, this.chainId, permission, thresholdNetworkUrl);
3781
+ const { decryptedValue, signature } = await tnDecryptV2(this.ctHash, this.chainId, permission, thresholdNetworkUrl);
3678
3782
  return {
3679
3783
  ctHash: this.ctHash,
3680
3784
  decryptedValue,
@@ -3882,19 +3986,19 @@ function createCofheClientBase(opts) {
3882
3986
  return permits.getOrCreateSharingPermit(publicClient, walletClient, options, _chainId, _account);
3883
3987
  },
3884
3988
  // Retrieval methods (auto-fill chainId/account)
3885
- getPermit: async (hash, chainId, account) => {
3989
+ getPermit: (hash, chainId, account) => {
3886
3990
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3887
3991
  return permits.getPermit(_chainId, _account, hash);
3888
3992
  },
3889
- getPermits: async (chainId, account) => {
3993
+ getPermits: (chainId, account) => {
3890
3994
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3891
3995
  return permits.getPermits(_chainId, _account);
3892
3996
  },
3893
- getActivePermit: async (chainId, account) => {
3997
+ getActivePermit: (chainId, account) => {
3894
3998
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3895
3999
  return permits.getActivePermit(_chainId, _account);
3896
4000
  },
3897
- getActivePermitHash: async (chainId, account) => {
4001
+ getActivePermitHash: (chainId, account) => {
3898
4002
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3899
4003
  return permits.getActivePermitHash(_chainId, _account);
3900
4004
  },
package/dist/web.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { C as CofheInputConfig, a as CofheConfig, b as CofheClient, E as EncryptableItem } from './clientTypes-Bhq7pCSA.cjs';
1
+ import { C as CofheInputConfig, a as CofheConfig, b as CofheClient, E as EncryptableItem } from './clientTypes-ACVWbrXL.cjs';
2
2
  import 'viem';
3
3
  import './types-YiAC4gig.cjs';
4
4
  import 'zod';
package/dist/web.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { C as CofheInputConfig, a as CofheConfig, b as CofheClient, E as EncryptableItem } from './clientTypes-6aTZPQ_4.js';
1
+ import { C as CofheInputConfig, a as CofheConfig, b as CofheClient, E as EncryptableItem } from './clientTypes-kkrRdawm.js';
2
2
  import 'viem';
3
3
  import './types-YiAC4gig.js';
4
4
  import 'zod';
package/dist/web.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createCofheConfigBase, createCofheClientBase, fheTypeToString } from './chunk-2TPSCOW3.js';
1
+ import { createCofheConfigBase, createCofheClientBase, fheTypeToString } from './chunk-MXND5SVN.js';
2
2
  import './chunk-TBLR7NNE.js';
3
3
  import './chunk-NWDKXBIP.js';
4
4
  import { constructClient } from 'iframe-shared-storage';
@@ -136,7 +136,7 @@ describe('@cofhe/node - Client Integration Tests', () => {
136
136
  it('should create decrypt builder after connection', async () => {
137
137
  await cofheClient.connect(publicClient, walletClient);
138
138
 
139
- const builder = cofheClient.decryptForView(123n, 2);
139
+ const builder = cofheClient.decryptForView('0x123', 2);
140
140
 
141
141
  expect(builder).toBeDefined();
142
142
  expect(typeof builder.setChainId).toBe('function');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cofhe/sdk",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "SDK for Fhenix COFHE coprocessor interaction",
6
6
  "main": "./dist/core.cjs",
@@ -136,7 +136,7 @@ describe('@cofhe/web - Client', () => {
136
136
  it('should create decrypt builder after connection', async () => {
137
137
  await cofheClient.connect(publicClient, walletClient);
138
138
 
139
- const builder = cofheClient.decryptForView(123n, 2);
139
+ const builder = cofheClient.decryptForView('0x123', 2);
140
140
 
141
141
  expect(builder).toBeDefined();
142
142
  expect(typeof builder.setChainId).toBe('function');