@cofhe/sdk 0.6.0 → 0.7.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.
Files changed (114) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/acps/acp.ts +411 -0
  3. package/acps/index.ts +70 -0
  4. package/{permits → acps}/onchain-utils.ts +49 -24
  5. package/acps/sealing.ts +90 -0
  6. package/acps/signature.ts +89 -0
  7. package/acps/store.ts +172 -0
  8. package/acps/test/acp.test.ts +615 -0
  9. package/acps/test/localstorage.test.ts +105 -0
  10. package/acps/test/sealing.test.ts +77 -0
  11. package/acps/test/store.test.ts +88 -0
  12. package/acps/test/validation.test.ts +361 -0
  13. package/acps/test-utils.ts +32 -0
  14. package/acps/types.ts +252 -0
  15. package/acps/validation.ts +392 -0
  16. package/adapters/test/ethers5.test.ts +4 -1
  17. package/adapters/test/ethers6.test.ts +4 -1
  18. package/adapters/test/wagmi.test.ts +5 -2
  19. package/chains/chains/stagingCofhe.ts +21 -0
  20. package/chains/index.ts +3 -1
  21. package/chains/test/chains.test.ts +2 -1
  22. package/core/acps.ts +625 -0
  23. package/core/client.ts +136 -39
  24. package/core/clientTypes.ts +52 -41
  25. package/core/config.ts +66 -5
  26. package/core/debug.ts +72 -0
  27. package/core/decrypt/MockThresholdNetworkAbi.ts +20 -11
  28. package/core/decrypt/apiError.ts +104 -0
  29. package/core/decrypt/cofheMocksDecryptForTx.ts +11 -11
  30. package/core/decrypt/cofheMocksDecryptForView.ts +7 -7
  31. package/core/decrypt/decryptForTxBuilder.ts +102 -102
  32. package/core/decrypt/decryptForViewBuilder.ts +90 -90
  33. package/core/decrypt/submitRetry.ts +38 -30
  34. package/core/decrypt/tnDecryptV1.ts +5 -5
  35. package/core/decrypt/tnDecryptV2.ts +45 -34
  36. package/core/decrypt/tnSealOutputV1.ts +4 -3
  37. package/core/decrypt/tnSealOutputV2.ts +44 -31
  38. package/core/encrypt/cofheMocksZkVerifySign.ts +59 -74
  39. package/core/encrypt/encryptInputsBuilder.ts +86 -52
  40. package/core/encrypt/zkPackProveVerify.ts +25 -18
  41. package/core/error.ts +34 -6
  42. package/core/index.ts +14 -14
  43. package/core/test/acpDefaults.test.ts +52 -0
  44. package/core/test/acps.test.ts +596 -0
  45. package/core/test/apiError.test.ts +130 -0
  46. package/core/test/client.test.ts +22 -19
  47. package/core/test/config.test.ts +25 -5
  48. package/core/test/decrypt.test.ts +40 -35
  49. package/core/test/decryptBuilders.test.ts +68 -68
  50. package/core/test/decryptErrorCodes.test.ts +217 -0
  51. package/core/test/encryptInputsBuilder.test.ts +72 -41
  52. package/core/test/pollCallbacks.test.ts +89 -18
  53. package/core/test/stagingRedirect.ts +18 -0
  54. package/core/test/submitRetry.test.ts +182 -0
  55. package/core/types.ts +9 -69
  56. package/dist/acp-Wi6isVQI.d.cts +407 -0
  57. package/dist/acp-Wi6isVQI.d.ts +407 -0
  58. package/dist/acps.cjs +1081 -0
  59. package/dist/acps.d.cts +480 -0
  60. package/dist/acps.d.ts +480 -0
  61. package/dist/acps.js +2 -0
  62. package/dist/chains.cjs +14 -1
  63. package/dist/chains.d.cts +30 -1
  64. package/dist/chains.d.ts +30 -1
  65. package/dist/chains.js +1 -1
  66. package/dist/{chunk-PE5V5CCV.js → chunk-43USWPEH.js} +1000 -604
  67. package/dist/{chunk-MTRAXQXC.js → chunk-N6IDQRRU.js} +14 -2
  68. package/dist/chunk-Q7CBWGQX.js +1029 -0
  69. package/dist/{clientTypes-CyUvRRzA.d.ts → clientTypes-BN3nbzYM.d.ts} +342 -165
  70. package/dist/{clientTypes-BDy1qIBu.d.cts → clientTypes-CYZjFznO.d.cts} +342 -165
  71. package/dist/core.cjs +1431 -1026
  72. package/dist/core.d.cts +55 -10
  73. package/dist/core.d.ts +55 -10
  74. package/dist/core.js +3 -3
  75. package/dist/node.cjs +1356 -976
  76. package/dist/node.d.cts +2 -2
  77. package/dist/node.d.ts +2 -2
  78. package/dist/node.js +3 -3
  79. package/dist/web.cjs +1356 -976
  80. package/dist/web.d.cts +2 -2
  81. package/dist/web.d.ts +2 -2
  82. package/dist/web.js +3 -3
  83. package/node/test/inherited.test.ts +75 -65
  84. package/node/test/tfheinit.test.ts +23 -8
  85. package/package.json +6 -6
  86. package/web/test/client.web.test.ts +5 -1
  87. package/web/test/inherited.web.test.ts +75 -65
  88. package/web/test/tfheinit.web.test.ts +14 -5
  89. package/web/test/worker.config.web.test.ts +38 -23
  90. package/web/test/worker.output.web.test.ts +25 -24
  91. package/core/encrypt/encryptUtils.ts +0 -67
  92. package/core/permits.ts +0 -206
  93. package/core/test/permits.test.ts +0 -534
  94. package/dist/chunk-VB62WYPL.js +0 -978
  95. package/dist/permit-DnVMDT5h.d.cts +0 -376
  96. package/dist/permit-DnVMDT5h.d.ts +0 -376
  97. package/dist/permits.cjs +0 -1026
  98. package/dist/permits.d.cts +0 -353
  99. package/dist/permits.d.ts +0 -353
  100. package/dist/permits.js +0 -2
  101. package/permits/index.ts +0 -68
  102. package/permits/permit.ts +0 -385
  103. package/permits/sealing.ts +0 -131
  104. package/permits/signature.ts +0 -79
  105. package/permits/store.ts +0 -157
  106. package/permits/test/localstorage.test.ts +0 -113
  107. package/permits/test/permit.test.ts +0 -557
  108. package/permits/test/sealing.test.ts +0 -84
  109. package/permits/test/store.test.ts +0 -88
  110. package/permits/test/validation.test.ts +0 -361
  111. package/permits/test-utils.ts +0 -28
  112. package/permits/types.ts +0 -204
  113. package/permits/validation.ts +0 -327
  114. /package/{permits → acps}/utils.ts +0 -0
@@ -1,8 +1,8 @@
1
- import { hardhat as hardhat$1 } from './chunk-MTRAXQXC.js';
2
- import { permitStore, PermitUtils } from './chunk-VB62WYPL.js';
1
+ import { hardhat as hardhat$1 } from './chunk-N6IDQRRU.js';
2
+ import { acpStore, ACPUtils } from './chunk-Q7CBWGQX.js';
3
3
  import { TFHE_RS_KEY_VERSION, TASK_MANAGER_ADDRESS, TFHE_RS_ZK_MAX_BITS, TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT, MOCKS_THRESHOLD_NETWORK_ADDRESS, MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY, MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY, MOCKS_ZK_VERIFIER_ADDRESS } from './chunk-ESMZCFJY.js';
4
4
  import { createStore } from 'zustand/vanilla';
5
- import { parseAbi, isAddressEqual, zeroAddress, recoverAddress, encodePacked, keccak256, createWalletClient, http, getAddress, parseSignature, serializeSignature } from 'viem';
5
+ import { parseAbi, isAddressEqual, zeroAddress, recoverAddress, keccak256, encodeAbiParameters, encodePacked, createWalletClient, http, getAddress, parseSignature, serializeSignature } from 'viem';
6
6
  import { hardhat } from 'viem/chains';
7
7
  import { sign, privateKeyToAccount } from 'viem/accounts';
8
8
  import { z } from 'zod';
@@ -10,58 +10,78 @@ import { persist, createJSONStorage } from 'zustand/middleware';
10
10
  import { produce } from 'immer';
11
11
 
12
12
  // core/error.ts
13
- var CofheErrorCode = /* @__PURE__ */ ((CofheErrorCode3) => {
14
- CofheErrorCode3["InternalError"] = "INTERNAL_ERROR";
15
- CofheErrorCode3["UnknownEnvironment"] = "UNKNOWN_ENVIRONMENT";
16
- CofheErrorCode3["InitTfheFailed"] = "INIT_TFHE_FAILED";
17
- CofheErrorCode3["InitViemFailed"] = "INIT_VIEM_FAILED";
18
- CofheErrorCode3["InitEthersFailed"] = "INIT_ETHERS_FAILED";
19
- CofheErrorCode3["NotConnected"] = "NOT_CONNECTED";
20
- CofheErrorCode3["MissingPublicClient"] = "MISSING_PUBLIC_CLIENT";
21
- CofheErrorCode3["MissingWalletClient"] = "MISSING_WALLET_CLIENT";
22
- CofheErrorCode3["MissingProviderParam"] = "MISSING_PROVIDER_PARAM";
23
- CofheErrorCode3["EmptySecurityZonesParam"] = "EMPTY_SECURITY_ZONES_PARAM";
24
- CofheErrorCode3["InvalidPermitData"] = "INVALID_PERMIT_DATA";
25
- CofheErrorCode3["InvalidPermitDomain"] = "INVALID_PERMIT_DOMAIN";
26
- CofheErrorCode3["PermitNotFound"] = "PERMIT_NOT_FOUND";
27
- CofheErrorCode3["CannotRemoveLastPermit"] = "CANNOT_REMOVE_LAST_PERMIT";
28
- CofheErrorCode3["AccountUninitialized"] = "ACCOUNT_UNINITIALIZED";
29
- CofheErrorCode3["ChainIdUninitialized"] = "CHAIN_ID_UNINITIALIZED";
30
- CofheErrorCode3["SealOutputFailed"] = "SEAL_OUTPUT_FAILED";
31
- CofheErrorCode3["SealOutputReturnedNull"] = "SEAL_OUTPUT_RETURNED_NULL";
32
- CofheErrorCode3["InvalidUtype"] = "INVALID_UTYPE";
33
- CofheErrorCode3["DecryptFailed"] = "DECRYPT_FAILED";
34
- CofheErrorCode3["DecryptReturnedNull"] = "DECRYPT_RETURNED_NULL";
35
- CofheErrorCode3["ZkMocksInsertCtHashesFailed"] = "ZK_MOCKS_INSERT_CT_HASHES_FAILED";
36
- CofheErrorCode3["ZkMocksCalcCtHashesFailed"] = "ZK_MOCKS_CALC_CT_HASHES_FAILED";
37
- CofheErrorCode3["ZkMocksVerifySignFailed"] = "ZK_MOCKS_VERIFY_SIGN_FAILED";
38
- CofheErrorCode3["ZkMocksCreateProofSignatureFailed"] = "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED";
39
- CofheErrorCode3["ZkVerifyFailed"] = "ZK_VERIFY_FAILED";
40
- CofheErrorCode3["ZkPackFailed"] = "ZK_PACK_FAILED";
41
- CofheErrorCode3["ZkProveFailed"] = "ZK_PROVE_FAILED";
42
- CofheErrorCode3["EncryptRemainingInItems"] = "ENCRYPT_REMAINING_IN_ITEMS";
43
- CofheErrorCode3["ZkUninitialized"] = "ZK_UNINITIALIZED";
44
- CofheErrorCode3["ZkVerifierUrlUninitialized"] = "ZK_VERIFIER_URL_UNINITIALIZED";
45
- CofheErrorCode3["ThresholdNetworkUrlUninitialized"] = "THRESHOLD_NETWORK_URL_UNINITIALIZED";
46
- CofheErrorCode3["MissingConfig"] = "MISSING_CONFIG";
47
- CofheErrorCode3["UnsupportedChain"] = "UNSUPPORTED_CHAIN";
48
- CofheErrorCode3["MissingZkBuilderAndCrsGenerator"] = "MISSING_ZK_BUILDER_AND_CRS_GENERATOR";
49
- CofheErrorCode3["MissingTfhePublicKeyDeserializer"] = "MISSING_TFHE_PUBLIC_KEY_DESERIALIZER";
50
- CofheErrorCode3["MissingCompactPkeCrsDeserializer"] = "MISSING_COMPACT_PKE_CRS_DESERIALIZER";
51
- CofheErrorCode3["MissingFheKey"] = "MISSING_FHE_KEY";
52
- CofheErrorCode3["MissingCrs"] = "MISSING_CRS";
53
- CofheErrorCode3["FetchKeysFailed"] = "FETCH_KEYS_FAILED";
54
- CofheErrorCode3["PublicWalletGetChainIdFailed"] = "PUBLIC_WALLET_GET_CHAIN_ID_FAILED";
55
- CofheErrorCode3["PublicWalletGetAddressesFailed"] = "PUBLIC_WALLET_GET_ADDRESSES_FAILED";
56
- CofheErrorCode3["RehydrateKeysStoreFailed"] = "REHYDRATE_KEYS_STORE_FAILED";
57
- return CofheErrorCode3;
13
+ var CofheErrorCode = /* @__PURE__ */ ((CofheErrorCode2) => {
14
+ CofheErrorCode2["InternalError"] = "INTERNAL_ERROR";
15
+ CofheErrorCode2["UnknownEnvironment"] = "UNKNOWN_ENVIRONMENT";
16
+ CofheErrorCode2["InitTfheFailed"] = "INIT_TFHE_FAILED";
17
+ CofheErrorCode2["InitViemFailed"] = "INIT_VIEM_FAILED";
18
+ CofheErrorCode2["InitEthersFailed"] = "INIT_ETHERS_FAILED";
19
+ CofheErrorCode2["NotConnected"] = "NOT_CONNECTED";
20
+ CofheErrorCode2["MissingPublicClient"] = "MISSING_PUBLIC_CLIENT";
21
+ CofheErrorCode2["MissingWalletClient"] = "MISSING_WALLET_CLIENT";
22
+ CofheErrorCode2["MissingProviderParam"] = "MISSING_PROVIDER_PARAM";
23
+ CofheErrorCode2["EmptySecurityZonesParam"] = "EMPTY_SECURITY_ZONES_PARAM";
24
+ CofheErrorCode2["InvalidACPData"] = "INVALID_ACP_DATA";
25
+ CofheErrorCode2["InvalidACPDomain"] = "INVALID_ACP_DOMAIN";
26
+ CofheErrorCode2["ACPNotFound"] = "ACP_NOT_FOUND";
27
+ CofheErrorCode2["CannotRemoveLastACP"] = "CANNOT_REMOVE_LAST_ACP";
28
+ CofheErrorCode2["AccountUninitialized"] = "ACCOUNT_UNINITIALIZED";
29
+ CofheErrorCode2["ChainIdUninitialized"] = "CHAIN_ID_UNINITIALIZED";
30
+ CofheErrorCode2["ConsumingContractUninitialized"] = "CONSUMING_CONTRACT_UNINITIALIZED";
31
+ CofheErrorCode2["SealOutputFailed"] = "SEAL_OUTPUT_FAILED";
32
+ CofheErrorCode2["SealOutputReturnedNull"] = "SEAL_OUTPUT_RETURNED_NULL";
33
+ CofheErrorCode2["InvalidUtype"] = "INVALID_UTYPE";
34
+ CofheErrorCode2["DecryptFailed"] = "DECRYPT_FAILED";
35
+ CofheErrorCode2["DecryptReturnedNull"] = "DECRYPT_RETURNED_NULL";
36
+ CofheErrorCode2["ZkMocksInsertCtHashesFailed"] = "ZK_MOCKS_INSERT_CT_HASHES_FAILED";
37
+ CofheErrorCode2["ZkMocksCalcCtHashesFailed"] = "ZK_MOCKS_CALC_CT_HASHES_FAILED";
38
+ CofheErrorCode2["ZkMocksVerifySignFailed"] = "ZK_MOCKS_VERIFY_SIGN_FAILED";
39
+ CofheErrorCode2["ZkMocksCreateProofSignatureFailed"] = "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED";
40
+ CofheErrorCode2["ZkVerifyFailed"] = "ZK_VERIFY_FAILED";
41
+ CofheErrorCode2["ZkPackFailed"] = "ZK_PACK_FAILED";
42
+ CofheErrorCode2["ZkProveFailed"] = "ZK_PROVE_FAILED";
43
+ CofheErrorCode2["EncryptRemainingInItems"] = "ENCRYPT_REMAINING_IN_ITEMS";
44
+ CofheErrorCode2["ZkUninitialized"] = "ZK_UNINITIALIZED";
45
+ CofheErrorCode2["ZkVerifierUrlUninitialized"] = "ZK_VERIFIER_URL_UNINITIALIZED";
46
+ CofheErrorCode2["ThresholdNetworkUrlUninitialized"] = "THRESHOLD_NETWORK_URL_UNINITIALIZED";
47
+ CofheErrorCode2["MissingConfig"] = "MISSING_CONFIG";
48
+ CofheErrorCode2["UnsupportedChain"] = "UNSUPPORTED_CHAIN";
49
+ CofheErrorCode2["MissingZkBuilderAndCrsGenerator"] = "MISSING_ZK_BUILDER_AND_CRS_GENERATOR";
50
+ CofheErrorCode2["MissingTfhePublicKeyDeserializer"] = "MISSING_TFHE_PUBLIC_KEY_DESERIALIZER";
51
+ CofheErrorCode2["MissingCompactPkeCrsDeserializer"] = "MISSING_COMPACT_PKE_CRS_DESERIALIZER";
52
+ CofheErrorCode2["MissingFheKey"] = "MISSING_FHE_KEY";
53
+ CofheErrorCode2["MissingCrs"] = "MISSING_CRS";
54
+ CofheErrorCode2["FetchKeysFailed"] = "FETCH_KEYS_FAILED";
55
+ CofheErrorCode2["PublicWalletGetChainIdFailed"] = "PUBLIC_WALLET_GET_CHAIN_ID_FAILED";
56
+ CofheErrorCode2["PublicWalletGetAddressesFailed"] = "PUBLIC_WALLET_GET_ADDRESSES_FAILED";
57
+ CofheErrorCode2["RehydrateKeysStoreFailed"] = "REHYDRATE_KEYS_STORE_FAILED";
58
+ CofheErrorCode2["BadRequest"] = "BAD_REQUEST";
59
+ CofheErrorCode2["UnknownChain"] = "UNKNOWN_CHAIN";
60
+ CofheErrorCode2["ACPMalformed"] = "ACP_MALFORMED";
61
+ CofheErrorCode2["ACPDenied"] = "ACP_DENIED";
62
+ CofheErrorCode2["ACPExpired"] = "ACP_EXPIRED";
63
+ CofheErrorCode2["ACPInvalid"] = "ACP_INVALID";
64
+ CofheErrorCode2["ACPRevoked"] = "ACP_REVOKED";
65
+ CofheErrorCode2["NotPubliclyAllowed"] = "NOT_PUBLICLY_ALLOWED";
66
+ CofheErrorCode2["CtNotFound"] = "CT_NOT_FOUND";
67
+ CofheErrorCode2["UnsupportedSecurityZone"] = "UNSUPPORTED_SECURITY_ZONE";
68
+ CofheErrorCode2["UnsupportedType"] = "UNSUPPORTED_TYPE";
69
+ CofheErrorCode2["SigningFailed"] = "SIGNING_FAILED";
70
+ CofheErrorCode2["CtSourceError"] = "CT_SOURCE_ERROR";
71
+ CofheErrorCode2["ACPVerifierError"] = "ACP_VERIFIER_ERROR";
72
+ CofheErrorCode2["CtSourceTimeout"] = "CT_SOURCE_TIMEOUT";
73
+ CofheErrorCode2["ACPVerifierTimeout"] = "ACP_VERIFIER_TIMEOUT";
74
+ CofheErrorCode2["ACPRequired"] = "ACP_REQUIRED";
75
+ CofheErrorCode2["SealFailed"] = "SEAL_FAILED";
76
+ return CofheErrorCode2;
58
77
  })(CofheErrorCode || {});
59
78
  var CofheError = class _CofheError extends Error {
60
79
  code;
61
80
  cause;
62
81
  hint;
63
82
  context;
64
- constructor({ code, message, cause, hint, context }) {
83
+ apiErrorCode;
84
+ constructor({ code, message, cause, hint, context, apiErrorCode }) {
65
85
  const fullMessage = cause ? `${message} | Caused by: ${cause.message}` : message;
66
86
  super(fullMessage);
67
87
  this.name = "CofheError";
@@ -69,6 +89,7 @@ var CofheError = class _CofheError extends Error {
69
89
  this.cause = cause;
70
90
  this.hint = hint;
71
91
  this.context = context;
92
+ this.apiErrorCode = apiErrorCode;
72
93
  if (Error.captureStackTrace) {
73
94
  Error.captureStackTrace(this, _CofheError);
74
95
  }
@@ -87,6 +108,7 @@ var CofheError = class _CofheError extends Error {
87
108
  message: wrapperError?.message ?? "An internal error occurred",
88
109
  hint: wrapperError?.hint,
89
110
  context: wrapperError?.context,
111
+ apiErrorCode: wrapperError?.apiErrorCode,
90
112
  cause
91
113
  });
92
114
  }
@@ -100,6 +122,7 @@ var CofheError = class _CofheError extends Error {
100
122
  message: this.message,
101
123
  hint: this.hint,
102
124
  context: this.context,
125
+ apiErrorCode: this.apiErrorCode,
103
126
  cause: this.cause ? {
104
127
  name: this.cause.name,
105
128
  message: this.cause.message,
@@ -112,7 +135,8 @@ var CofheError = class _CofheError extends Error {
112
135
  * Returns a human-readable string representation of the error
113
136
  */
114
137
  toString() {
115
- const parts = [`${this.name} [${this.code}]: ${this.message}`];
138
+ const codeSuffix = this.apiErrorCode ? ` (api: ${this.apiErrorCode})` : "";
139
+ const parts = [`${this.name} [${this.code}]${codeSuffix}: ${this.message}`];
116
140
  if (this.hint) {
117
141
  parts.push(`Hint: ${this.hint}`);
118
142
  }
@@ -198,10 +222,6 @@ var FheAllUTypes = [
198
222
  // FheTypes.Uint256,
199
223
  7 /* Uint160 */
200
224
  ];
201
- function assertCorrectEncryptedItemInput(input) {
202
- if (!input.signature.startsWith("0x"))
203
- throw new Error("Signature must be a hex string starting with 0x");
204
- }
205
225
  var EncryptableFactoriesImpl = {
206
226
  bool: (data, securityZone = 0) => ({ data, securityZone, utype: 0 /* Bool */ }),
207
227
  address: (data, securityZone = 0) => ({ data, securityZone, utype: 7 /* Uint160 */ }),
@@ -481,18 +501,19 @@ var constructZkPoKMetadata = (accountAddr, securityZone, chainId) => {
481
501
  metadata.set(chainIdBytes, 1 + accountBytes.length);
482
502
  return metadata;
483
503
  };
484
- var zkVerify = async (verifierUrl, serializedBytes, address, securityZone, chainId) => {
504
+ var zkVerifyBatch = async (verifierUrl, serializedBytes, address, securityZone, chainId, consumingContract) => {
485
505
  const packed_list = toHexString(serializedBytes);
486
506
  const sz_byte = new Uint8Array([securityZone]);
487
507
  const payload = {
488
508
  packed_list,
489
509
  account_addr: address,
490
510
  security_zone: sz_byte[0],
491
- chain_id: chainId
511
+ chain_id: chainId,
512
+ contract_address: consumingContract
492
513
  };
493
514
  const body = JSON.stringify(payload);
494
515
  try {
495
- const response = await fetch(`${verifierUrl}/verify`, {
516
+ const response = await fetch(`${verifierUrl}/verifyBatch`, {
496
517
  method: "POST",
497
518
  headers: {
498
519
  "Content-Type": "application/json"
@@ -503,26 +524,25 @@ var zkVerify = async (verifierUrl, serializedBytes, address, securityZone, chain
503
524
  const errorBody = await response.text();
504
525
  throw new CofheError({
505
526
  code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
506
- message: `HTTP error! ZK proof verification failed - ${errorBody}`
527
+ message: `HTTP error! ZK batch proof verification failed - ${errorBody}`
507
528
  });
508
529
  }
509
530
  const json = await response.json();
510
531
  if (json.status !== "success") {
511
532
  throw new CofheError({
512
533
  code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
513
- message: `ZK proof verification response malformed - ${json.error}`
534
+ message: `ZK batch proof verification response malformed - ${json.error}`
514
535
  });
515
536
  }
516
- return json.data.map(({ ct_hash, signature, recid }) => {
517
- return {
518
- ct_hash,
519
- signature: concatSigRecid(signature, recid)
520
- };
521
- });
537
+ const { ciphertexts, signature, recid } = json.data;
538
+ return {
539
+ outputs: ciphertexts,
540
+ signature: concatSigRecid(signature, recid)
541
+ };
522
542
  } catch (e) {
523
543
  throw new CofheError({
524
544
  code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
525
- message: `ZK proof verification failed`,
545
+ message: `ZK batch proof verification failed`,
526
546
  cause: e instanceof Error ? e : void 0
527
547
  });
528
548
  }
@@ -767,75 +787,67 @@ async function insertCtHashes(items, walletClient) {
767
787
  });
768
788
  }
769
789
  }
770
- async function createProofSignatures(items, securityZone, account) {
771
- let signatures = [];
772
- let encInputSignerClient;
790
+ async function createBatchProofSignature(items, securityZone, account, consumingContract) {
773
791
  try {
774
- encInputSignerClient = createMockZkVerifierSigner();
775
- } catch (err) {
776
- throw new CofheError({
777
- code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
778
- message: `mockZkVerifySign createProofSignatures failed while creating wallet client`,
779
- cause: err instanceof Error ? err : void 0,
780
- context: {
781
- MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY
782
- }
792
+ const itemHashes = items.map(
793
+ (item) => keccak256(
794
+ encodePacked(
795
+ ["uint256", "uint8", "uint8", "address", "uint256", "address"],
796
+ [
797
+ BigInt(item.ctHash),
798
+ item.utype,
799
+ securityZone,
800
+ account,
801
+ BigInt(hardhat.id),
802
+ consumingContract
803
+ ]
804
+ )
805
+ )
806
+ );
807
+ const batchDigest = keccak256(
808
+ encodePacked(
809
+ itemHashes.map(() => "bytes32"),
810
+ itemHashes
811
+ )
812
+ );
813
+ return await sign({
814
+ hash: batchDigest,
815
+ privateKey: MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY,
816
+ to: "hex"
783
817
  });
784
- }
785
- try {
786
- for (const item of items) {
787
- const packedData = encodePacked(
788
- ["uint256", "uint8", "uint8", "address", "uint256"],
789
- [BigInt(item.ctHash), item.utype, securityZone, account, BigInt(hardhat.id)]
790
- );
791
- const messageHash = keccak256(packedData);
792
- const signature = await sign({
793
- hash: messageHash,
794
- privateKey: MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY,
795
- to: "hex"
796
- });
797
- signatures.push(signature);
798
- }
799
818
  } catch (err) {
800
819
  throw new CofheError({
801
820
  code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
802
- message: `mockZkVerifySign createProofSignatures failed while calling signMessage`,
821
+ message: `mockZkVerifySign createBatchProofSignature failed while signing the batch digest`,
803
822
  cause: err instanceof Error ? err : void 0,
804
823
  context: {
805
824
  items,
806
- securityZone
807
- }
808
- });
809
- }
810
- if (signatures.length !== items.length) {
811
- throw new CofheError({
812
- code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
813
- message: `mockZkVerifySign createProofSignatures returned incorrect number of signatures`,
814
- context: {
815
- items,
816
- securityZone
825
+ securityZone,
826
+ consumingContract
817
827
  }
818
828
  });
819
829
  }
820
- return signatures;
821
830
  }
822
- async function cofheMocksZkVerifySign(items, account, securityZone, publicClient, walletClient, zkvWalletClient) {
831
+ async function cofheMocksZkVerifySign(items, account, securityZone, consumingContract, publicClient, walletClient, zkvWalletClient) {
823
832
  const _walletClient = zkvWalletClient ?? createMockZkVerifierSigner();
824
833
  const encryptableItems = await calcCtHashes(items, account, securityZone, publicClient);
825
834
  await insertCtHashes(encryptableItems, _walletClient);
826
- const signatures = await createProofSignatures(encryptableItems, securityZone, account);
827
- return encryptableItems.map((item, index) => ({
828
- ct_hash: item.ctHash.toString(),
829
- signature: signatures[index]
830
- }));
835
+ const signature = await createBatchProofSignature(encryptableItems, securityZone, account, consumingContract);
836
+ return {
837
+ outputs: encryptableItems.map((item) => ({
838
+ ct_hash: item.ctHash.toString(),
839
+ ct_type: item.utype
840
+ })),
841
+ signature
842
+ };
831
843
  }
832
844
  var CofheConfigSchema = z.object({
833
845
  /** Environment that the SDK is running in */
834
846
  environment: z.enum(["node", "hardhat", "web", "react"]).optional().default("node"),
835
847
  /** List of supported chain configurations */
836
848
  supportedChains: z.array(z.custom()),
837
- /** Default permit expiration in seconds, default is 30 days */
838
- defaultPermitExpiration: z.number().optional().default(60 * 60 * 24 * 30),
849
+ /** Default acp expiration in seconds, default is 30 days */
850
+ defaultACPExpiration: z.number().optional().default(60 * 60 * 24 * 30),
839
851
  /** Storage method for fhe keys (defaults to indexedDB on web, filesystem on node) */
840
852
  fheKeyStorage: z.object({
841
853
  getItem: z.custom((val) => typeof val === "function", {
@@ -850,6 +862,12 @@ var CofheConfigSchema = z.object({
850
862
  }).or(z.null()).default(null),
851
863
  /** Whether to use Web Workers for ZK proof generation (web platform only) */
852
864
  useWorkers: z.boolean().optional().default(true),
865
+ /** ACP acp defaults */
866
+ acp: z.object({
867
+ defaultRevoker: z.custom().optional(),
868
+ defaultContractScopes: z.custom().optional(),
869
+ sharingRegistry: z.custom().optional()
870
+ }).optional().default({}),
853
871
  /** Mocks configs */
854
872
  mocks: z.object({
855
873
  decryptDelay: z.number().optional().default(0),
@@ -860,8 +878,19 @@ var CofheConfigSchema = z.object({
860
878
  zkvWalletClient: z.any().optional()
861
879
  }).optional()
862
880
  });
881
+ var RENAMED_COFHE_CONFIG_KEYS = {
882
+ defaultPermitExpiration: "defaultACPExpiration"
883
+ };
884
+ function assertNoRenamedConfigKeys(config, renamedKeys, label) {
885
+ const stale = Object.keys(config).filter((key) => key in renamedKeys);
886
+ if (stale.length === 0)
887
+ return;
888
+ const renames = stale.map((key) => `\`${key}\` is now \`${renamedKeys[key]}\``).join("; ");
889
+ throw new Error(`Invalid ${label}: ${renames}. See the v0.7.0 migration guide.`);
890
+ }
863
891
  function createCofheConfigBase(config) {
864
- const result = CofheConfigSchema.safeParse(config);
892
+ assertNoRenamedConfigKeys(config, RENAMED_COFHE_CONFIG_KEYS, "cofhe configuration");
893
+ const result = CofheConfigSchema.strict().safeParse(config);
865
894
  if (!result.success) {
866
895
  throw new Error(`Invalid cofhe configuration: ${z.prettifyError(result.error)}`, { cause: result.error });
867
896
  }
@@ -1213,9 +1242,9 @@ var BaseBuilder = class {
1213
1242
  // core/encrypt/encryptInputsBuilder.ts
1214
1243
  var EncryptInputsBuilder = class extends BaseBuilder {
1215
1244
  securityZone;
1245
+ consumingContract;
1216
1246
  stepCallback;
1217
1247
  inputItems;
1218
- hpp = false;
1219
1248
  zkvWalletClient;
1220
1249
  tfhePublicKeyDeserializer;
1221
1250
  compactPkeCrsDeserializer;
@@ -1282,20 +1311,6 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1282
1311
  this.keysStorage = params.keysStorage;
1283
1312
  this.useWorker = params.config?.useWorkers ?? true;
1284
1313
  }
1285
- /**
1286
- * @param account - Account that will create the tx using the encrypted inputs.
1287
- *
1288
- * If not provided, the account will be fetched from the connected walletClient.
1289
- *
1290
- * Example:
1291
- * ```typescript
1292
- * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1293
- * .setAccount("0x123")
1294
- * .execute();
1295
- * ```
1296
- *
1297
- * @returns The chainable EncryptInputsBuilder instance.
1298
- */
1299
1314
  setAccount(account) {
1300
1315
  this.account = account;
1301
1316
  return this;
@@ -1303,20 +1318,6 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1303
1318
  getAccount() {
1304
1319
  return this.account;
1305
1320
  }
1306
- /**
1307
- * @param chainId - Chain that will consume the encrypted inputs.
1308
- *
1309
- * If not provided, the chainId will be fetched from the connected publicClient.
1310
- *
1311
- * Example:
1312
- * ```typescript
1313
- * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1314
- * .setChainId(11155111)
1315
- * .execute();
1316
- * ```
1317
- *
1318
- * @returns The chainable EncryptInputsBuilder instance.
1319
- */
1320
1321
  setChainId(chainId) {
1321
1322
  this.chainId = chainId;
1322
1323
  return this;
@@ -1324,20 +1325,6 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1324
1325
  getChainId() {
1325
1326
  return this.chainId;
1326
1327
  }
1327
- /**
1328
- * @param securityZone - Security zone to encrypt the inputs for.
1329
- *
1330
- * If not provided, the default securityZone 0 will be used.
1331
- *
1332
- * Example:
1333
- * ```typescript
1334
- * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1335
- * .setSecurityZone(1)
1336
- * .execute();
1337
- * ```
1338
- *
1339
- * @returns The chainable EncryptInputsBuilder instance.
1340
- */
1341
1328
  setSecurityZone(securityZone) {
1342
1329
  this.securityZone = securityZone;
1343
1330
  return this;
@@ -1346,33 +1333,44 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1346
1333
  return this.securityZone;
1347
1334
  }
1348
1335
  /**
1336
+ * @param address - The contract that will consume the resulting hashes+signature (i.e. the
1337
+ * contract that will call `FHE.asEuint*`/`FHE.asEuint*s` with them).
1338
+ *
1339
+ * Required before `execute()` - the verifier binds this address into the signed digest, so a
1340
+ * batch signed for one contract cannot be replayed into another.
1341
+ *
1349
1342
  * Example:
1350
1343
  * ```typescript
1351
1344
  * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1352
- * .asHashPlusProof()
1345
+ * .setConsumingContract("0x123...890")
1353
1346
  * .execute();
1354
1347
  * ```
1355
1348
  *
1356
- * @returns Chainable EncryptInputsBuilder instance that will return a HashPlusProofResult instead of an array of EncryptedItemInputs.
1349
+ * @returns The chainable EncryptInputsBuilder instance.
1357
1350
  */
1358
- asHashPlusProof() {
1359
- this.hpp = true;
1351
+ setConsumingContract(address) {
1352
+ this.consumingContract = address;
1360
1353
  return this;
1361
1354
  }
1355
+ getConsumingContract() {
1356
+ return this.consumingContract;
1357
+ }
1362
1358
  /**
1363
- * @param useWorker - Whether to use Web Workers for ZK proof generation.
1364
- *
1365
- * Overrides the config-level useWorkers setting for this specific encryption.
1366
- *
1367
- * Example:
1368
- * ```typescript
1369
- * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1370
- * .setUseWorker(false)
1371
- * .execute();
1372
- * ```
1373
- *
1374
- * @returns The chainable EncryptInputsBuilder instance.
1359
+ * Asserts that this.consumingContract is populated
1360
+ * @throws {CofheError} If consumingContract is not set
1375
1361
  */
1362
+ assertConsumingContract() {
1363
+ if (this.consumingContract)
1364
+ return;
1365
+ throw new CofheError({
1366
+ code: "CONSUMING_CONTRACT_UNINITIALIZED" /* ConsumingContractUninitialized */,
1367
+ message: "Consuming contract is not set",
1368
+ hint: "Use setConsumingContract(...) to set the contract that will consume the encrypted inputs.",
1369
+ context: {
1370
+ consumingContract: this.consumingContract
1371
+ }
1372
+ });
1373
+ }
1376
1374
  setUseWorker(useWorker) {
1377
1375
  this.useWorker = useWorker;
1378
1376
  return this;
@@ -1393,21 +1391,6 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1393
1391
  getUseWorker() {
1394
1392
  return this.useWorker;
1395
1393
  }
1396
- /**
1397
- * @param callback - Function to be called with the encryption step.
1398
- *
1399
- * Useful for debugging and tracking the progress of the encryption process.
1400
- * Useful for a UI element that shows the progress of the encryption process.
1401
- *
1402
- * Example:
1403
- * ```typescript
1404
- * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1405
- * .onStep((step: EncryptStep) => console.log(step))
1406
- * .execute();
1407
- * ```
1408
- *
1409
- * @returns The EncryptInputsBuilder instance.
1410
- */
1411
1394
  onStep(callback) {
1412
1395
  this.stepCallback = callback;
1413
1396
  return this;
@@ -1546,6 +1529,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1546
1529
  this.assertAccount();
1547
1530
  this.assertPublicClient();
1548
1531
  this.assertWalletClient();
1532
+ this.assertConsumingContract();
1549
1533
  const [initTfheDelay, fetchKeysDelay, packDelay, proveDelay, verifyDelay] = this.resolveEncryptDelays();
1550
1534
  this.fireStepStart("initTfhe" /* InitTfhe */);
1551
1535
  await sleep(initTfheDelay);
@@ -1571,22 +1555,17 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1571
1555
  this.fireStepEnd("prove" /* Prove */, { isMocks: true, mockSleep: proveDelay });
1572
1556
  this.fireStepStart("verify" /* Verify */);
1573
1557
  await sleep(verifyDelay);
1574
- const signedResults = await cofheMocksZkVerifySign(
1558
+ const result = await cofheMocksZkVerifySign(
1575
1559
  this.inputItems,
1576
1560
  this.account,
1577
1561
  this.securityZone,
1562
+ this.consumingContract,
1578
1563
  this.publicClient,
1579
1564
  this.walletClient,
1580
1565
  this.zkvWalletClient
1581
1566
  );
1582
- const encryptedInputs = signedResults.map(({ ct_hash, signature }, index) => ({
1583
- ctHash: BigInt(ct_hash),
1584
- securityZone: this.securityZone,
1585
- utype: this.inputItems[index].utype,
1586
- signature
1587
- }));
1588
1567
  this.fireStepEnd("verify" /* Verify */, { isMocks: true, mockSleep: verifyDelay });
1589
- return encryptedInputs;
1568
+ return result;
1590
1569
  }
1591
1570
  /**
1592
1571
  * In the production context, perform a true encryption with the CoFHE coprocessor.
@@ -1594,6 +1573,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1594
1573
  async productionExecute() {
1595
1574
  this.assertAccount();
1596
1575
  this.assertChainId();
1576
+ this.assertConsumingContract();
1597
1577
  this.fireStepStart("initTfhe" /* InitTfhe */);
1598
1578
  const tfheInitializationExecuted = await this.initTfheOrThrow();
1599
1579
  this.fireStepEnd("initTfhe" /* InitTfhe */, { tfheInitializationExecuted });
@@ -1628,26 +1608,24 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1628
1608
  });
1629
1609
  this.fireStepStart("verify" /* Verify */);
1630
1610
  const zkVerifierUrl = await this.getZkVerifierUrl();
1631
- const verifyResults = await zkVerify(zkVerifierUrl, proof, this.account, this.securityZone, this.chainId);
1632
- const encryptedInputs = verifyResults.map(
1633
- ({ ct_hash, signature }, index) => ({
1634
- ctHash: BigInt(ct_hash),
1635
- securityZone: this.securityZone,
1636
- utype: this.inputItems[index].utype,
1637
- signature
1638
- })
1611
+ const result = await zkVerifyBatch(
1612
+ zkVerifierUrl,
1613
+ proof,
1614
+ this.account,
1615
+ this.securityZone,
1616
+ this.chainId,
1617
+ this.consumingContract
1639
1618
  );
1640
1619
  this.fireStepEnd("verify" /* Verify */);
1641
- return encryptedInputs;
1620
+ return result;
1642
1621
  }
1643
- structsToHashPlusProof(inItems) {
1644
- let hashes = [];
1645
- let proof = "";
1646
- for (const item of inItems) {
1647
- hashes.push("0x" + item.ctHash.toString(16).padStart(64, "0"));
1648
- proof += item.signature;
1649
- }
1650
- return [...hashes, proof];
1622
+ /**
1623
+ * Converts a batch-verified result (per-item ctHash/ctType + one shared signature) into the
1624
+ * tuple returned by `execute()`: per-item hashes in input order, followed by the single signature.
1625
+ */
1626
+ buildBatchResult(result) {
1627
+ const hashes = result.outputs.map((output) => "0x" + BigInt(output.ct_hash).toString(16).padStart(64, "0"));
1628
+ return [...hashes, result.signature];
1651
1629
  }
1652
1630
  /**
1653
1631
  * Final step of the encryption process. MUST BE CALLED LAST IN THE CHAIN.
@@ -1669,102 +1647,329 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1669
1647
  * @returns The encrypted inputs.
1670
1648
  */
1671
1649
  async execute() {
1672
- let items;
1650
+ let result;
1673
1651
  if (this.chainId === hardhat.id)
1674
- items = await this.mocksExecute();
1652
+ result = await this.mocksExecute();
1675
1653
  else
1676
- items = await this.productionExecute();
1677
- if (this.hpp)
1678
- return this.structsToHashPlusProof(items);
1679
- return items;
1654
+ result = await this.productionExecute();
1655
+ return this.buildBatchResult(result);
1680
1656
  }
1681
1657
  };
1682
- var storeActivePermit = async (permit, publicClient, walletClient) => {
1658
+ var ACP_VALIDATOR_ABI = parseAbi([
1659
+ "function revokeSingle(uint256 id)",
1660
+ "function revokeAllExisting()",
1661
+ "function disabled(address issuer, uint256 id) view returns (bool)"
1662
+ ]);
1663
+ var storeACP = async (acp, publicClient, walletClient) => {
1683
1664
  const chainId = await publicClient.getChainId();
1684
1665
  const account = walletClient.account.address;
1685
- permitStore.setPermit(chainId, account, permit);
1686
- permitStore.setActivePermitHash(chainId, account, permit.hash);
1666
+ acpStore.setACP(chainId, account, acp);
1687
1667
  };
1688
- var createPermitWithSign = async (options, publicClient, walletClient, permitMethod) => {
1689
- const permit = await permitMethod(options, publicClient, walletClient);
1690
- await storeActivePermit(permit, publicClient, walletClient);
1691
- return permit;
1668
+ var storeActiveACP = async (acp, publicClient, walletClient) => {
1669
+ await storeACP(acp, publicClient, walletClient);
1670
+ const chainId = await publicClient.getChainId();
1671
+ const account = walletClient.account.address;
1672
+ acpStore.setActiveACPHash(chainId, account, acp.hash);
1673
+ };
1674
+ var createACPWithSign = async (options, publicClient, walletClient, acpMethod, activate = true) => {
1675
+ const acp = await acpMethod(options, publicClient, walletClient);
1676
+ if (activate) {
1677
+ await storeActiveACP(acp, publicClient, walletClient);
1678
+ } else {
1679
+ await storeACP(acp, publicClient, walletClient);
1680
+ }
1681
+ return acp;
1692
1682
  };
1693
1683
  var createSelf = async (options, publicClient, walletClient) => {
1694
- return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSelfAndSign);
1684
+ return createACPWithSign(options, publicClient, walletClient, ACPUtils.createSelfAndSign);
1695
1685
  };
1696
1686
  var createSharing = async (options, publicClient, walletClient) => {
1697
- return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSharingAndSign);
1687
+ return createACPWithSign(options, publicClient, walletClient, ACPUtils.createSharingAndSign, false);
1698
1688
  };
1699
1689
  var importShared = async (options, publicClient, walletClient) => {
1700
- return createPermitWithSign(options, publicClient, walletClient, PermitUtils.importSharedAndSign);
1690
+ return createACPWithSign(options, publicClient, walletClient, ACPUtils.importSharedAndSign);
1701
1691
  };
1702
- var getHash = (permit) => {
1703
- return PermitUtils.getHash(permit);
1692
+ var getHash = (acp) => {
1693
+ return ACPUtils.getHash(acp);
1704
1694
  };
1705
- var exportShared = (permit) => {
1706
- return PermitUtils.export(permit);
1695
+ var exportShared = (acp) => {
1696
+ return ACPUtils.export(acp);
1707
1697
  };
1708
- var serialize = (permit) => {
1709
- return PermitUtils.serialize(permit);
1698
+ var serialize = (acp) => {
1699
+ return ACPUtils.serialize(acp);
1710
1700
  };
1711
1701
  var deserialize = (serialized) => {
1712
- return PermitUtils.deserialize(serialized);
1702
+ return ACPUtils.deserialize(serialized);
1713
1703
  };
1714
- var getPermit = (chainId, account, hash) => {
1715
- return permitStore.getPermit(chainId, account, hash);
1704
+ var getACP = (chainId, account, hash) => {
1705
+ return acpStore.getACP(chainId, account, hash);
1716
1706
  };
1717
- var getPermits = (chainId, account) => {
1718
- return permitStore.getPermits(chainId, account);
1707
+ var getACPs = (chainId, account) => {
1708
+ return acpStore.getACPs(chainId, account);
1719
1709
  };
1720
- var getActivePermit = (chainId, account) => {
1721
- return permitStore.getActivePermit(chainId, account);
1710
+ var getActiveACP = (chainId, account) => {
1711
+ return acpStore.getActiveACP(chainId, account);
1722
1712
  };
1723
- var getActivePermitHash = (chainId, account) => {
1724
- return permitStore.getActivePermitHash(chainId, account);
1713
+ var getActiveACPHash = (chainId, account) => {
1714
+ return acpStore.getActiveACPHash(chainId, account);
1725
1715
  };
1726
- var selectActivePermit = (chainId, account, hash) => {
1727
- permitStore.setActivePermitHash(chainId, account, hash);
1716
+ var selectActiveACP = (chainId, account, hash) => {
1717
+ acpStore.setActiveACPHash(chainId, account, hash);
1728
1718
  };
1729
- var getOrCreateSelfPermit = async (publicClient, walletClient, chainId, account, options) => {
1719
+ var getOrCreateSelfACP = async (publicClient, walletClient, chainId, account, options) => {
1730
1720
  const _chainId = chainId ?? await publicClient.getChainId();
1731
1721
  const _account = account ?? walletClient.account.address;
1732
- const activePermit = await getActivePermit(_chainId, _account);
1733
- if (activePermit && activePermit.type === "self") {
1734
- return activePermit;
1722
+ const activeACP = await getActiveACP(_chainId, _account);
1723
+ if (activeACP && activeACP.type === "self" && ACPUtils.isValid(activeACP).valid) {
1724
+ return activeACP;
1735
1725
  }
1736
- return createSelf(options ?? { issuer: _account, name: "Autogenerated Self Permit" }, publicClient, walletClient);
1726
+ return createSelf(options ?? { issuer: _account, name: "Autogenerated Self ACP" }, publicClient, walletClient);
1737
1727
  };
1738
- var getOrCreateSharingPermit = async (publicClient, walletClient, options, chainId, account) => {
1728
+ var getOrCreateSharingACP = async (publicClient, walletClient, options, chainId, account) => {
1739
1729
  const _chainId = chainId ?? await publicClient.getChainId();
1740
1730
  const _account = account ?? walletClient.account.address;
1741
- const activePermit = await getActivePermit(_chainId, _account);
1742
- if (activePermit && activePermit.type === "sharing") {
1743
- return activePermit;
1731
+ const activeACP = await getActiveACP(_chainId, _account);
1732
+ if (activeACP && activeACP.type === "sharing" && ACPUtils.isValid(activeACP).valid) {
1733
+ return activeACP;
1744
1734
  }
1745
1735
  return createSharing(options, publicClient, walletClient);
1746
1736
  };
1747
- var removePermit = async (chainId, account, hash) => permitStore.removePermit(chainId, account, hash);
1748
- var removeActivePermit = async (chainId, account) => permitStore.removeActivePermitHash(chainId, account);
1749
- var permits = {
1750
- getSnapshot: permitStore.store.getState,
1751
- subscribe: permitStore.store.subscribe,
1737
+ var applyACPDefaults = (options, acpConfig, chainId) => {
1738
+ const result = { ...options };
1739
+ const defaultRevoker = acpConfig?.defaultRevoker?.[chainId];
1740
+ const hasValidatorOptions = options.revokerData != null || options.revokerContract != null;
1741
+ if (defaultRevoker != null && !hasValidatorOptions) {
1742
+ result.revokerContract = defaultRevoker;
1743
+ result.revokerData = Math.round(Date.now() / 1e3) - 60;
1744
+ }
1745
+ const defaultContracts = acpConfig?.defaultContractScopes?.[chainId];
1746
+ const hasScopeOptions = options.scope != null || options.contracts != null || options.handles != null;
1747
+ if (defaultContracts != null && defaultContracts.length > 0 && !hasScopeOptions) {
1748
+ result.contracts = defaultContracts;
1749
+ }
1750
+ return result;
1751
+ };
1752
+ var ACL_SERVED_ADDRESSES_ABI = parseAbi([
1753
+ "function acl() view returns (address)",
1754
+ "function defaultRevokerContract() view returns (address)",
1755
+ "function shareRegistry() view returns (address)"
1756
+ ]);
1757
+ var aclServedAddressesCache = /* @__PURE__ */ new Map();
1758
+ var clearAclServedAddresses = () => aclServedAddressesCache.clear();
1759
+ var getAclServedAddresses = async (publicClient, chainId) => {
1760
+ const cached = aclServedAddressesCache.get(chainId);
1761
+ if (cached != null)
1762
+ return cached;
1763
+ let aclAddress;
1764
+ try {
1765
+ aclAddress = await publicClient.readContract({
1766
+ address: TASK_MANAGER_ADDRESS,
1767
+ abi: ACL_SERVED_ADDRESSES_ABI,
1768
+ functionName: "acl"
1769
+ });
1770
+ } catch {
1771
+ return {};
1772
+ }
1773
+ const [defaultRevoker, shareRegistry] = await Promise.all([
1774
+ publicClient.readContract({ address: aclAddress, abi: ACL_SERVED_ADDRESSES_ABI, functionName: "defaultRevokerContract" }).catch(() => void 0),
1775
+ publicClient.readContract({ address: aclAddress, abi: ACL_SERVED_ADDRESSES_ABI, functionName: "shareRegistry" }).catch(() => void 0)
1776
+ ]);
1777
+ const resolved = {
1778
+ defaultRevoker: defaultRevoker != null && defaultRevoker !== zeroAddress ? defaultRevoker : void 0,
1779
+ shareRegistry: shareRegistry != null && shareRegistry !== zeroAddress ? shareRegistry : void 0
1780
+ };
1781
+ aclServedAddressesCache.set(chainId, resolved);
1782
+ return resolved;
1783
+ };
1784
+ var applyACPDefaultsFromChain = async (options, acpConfig, publicClient, chainId) => {
1785
+ const hasExplicitRevoker = acpConfig?.defaultRevoker?.[chainId] != null || options.revokerData != null || options.revokerContract != null;
1786
+ if (hasExplicitRevoker)
1787
+ return applyACPDefaults(options, acpConfig, chainId);
1788
+ const served = await getAclServedAddresses(publicClient, chainId);
1789
+ const effectiveConfig = served.defaultRevoker != null ? { ...acpConfig, defaultRevoker: { ...acpConfig?.defaultRevoker, [chainId]: served.defaultRevoker } } : acpConfig;
1790
+ return applyACPDefaults(options, effectiveConfig, chainId);
1791
+ };
1792
+ var revokeACP = async (acp, walletClient) => {
1793
+ if (acp.revokerContract === zeroAddress || acp.revokerData === 0) {
1794
+ throw new Error("ACP is not revocable: it has no revoker (revokerContract/revokerData unset)");
1795
+ }
1796
+ if (walletClient.account == null)
1797
+ throw new Error("Missing walletClient account");
1798
+ if (walletClient.account.address.toLowerCase() !== acp.issuer.toLowerCase()) {
1799
+ throw new Error("Only the acp issuer can revoke it");
1800
+ }
1801
+ return walletClient.writeContract({
1802
+ address: acp.revokerContract,
1803
+ abi: ACP_VALIDATOR_ABI,
1804
+ functionName: "revokeSingle",
1805
+ args: [BigInt(acp.revokerData)],
1806
+ account: walletClient.account,
1807
+ chain: walletClient.chain
1808
+ });
1809
+ };
1810
+ var revokeAllACPs = async (walletClient, publicClient, revokerContract) => {
1811
+ if (walletClient.account == null)
1812
+ throw new Error("Missing walletClient account");
1813
+ let revoker = revokerContract;
1814
+ if (revoker == null) {
1815
+ const chainId = await publicClient.getChainId();
1816
+ const active = getActiveACP(chainId, walletClient.account.address);
1817
+ revoker = active?.revokerContract;
1818
+ }
1819
+ if (revoker == null || revoker === zeroAddress) {
1820
+ throw new Error("No revoker contract: pass `revokerContract` or activate a revocable acp first");
1821
+ }
1822
+ return walletClient.writeContract({
1823
+ address: revoker,
1824
+ abi: ACP_VALIDATOR_ABI,
1825
+ functionName: "revokeAllExisting",
1826
+ args: [],
1827
+ account: walletClient.account,
1828
+ chain: walletClient.chain
1829
+ });
1830
+ };
1831
+ var isACPRevoked = async (acp, publicClient) => {
1832
+ if (acp.revokerContract === zeroAddress || acp.revokerData === 0)
1833
+ return false;
1834
+ return publicClient.readContract({
1835
+ address: acp.revokerContract,
1836
+ abi: ACP_VALIDATOR_ABI,
1837
+ functionName: "disabled",
1838
+ args: [acp.issuer, BigInt(acp.revokerData)]
1839
+ });
1840
+ };
1841
+ var ACP_SHARE_REGISTRY_ABI = parseAbi([
1842
+ "struct ACP { address issuer; uint64 expiration; address recipient; uint256 revokerData; address revokerContract; uint8 scope; address[] contracts; bytes32[] handles; bytes32 sealingKey; bytes issuerSignature; bytes recipientSignature; }",
1843
+ "function share(ACP calldata acp) external returns (bytes32)",
1844
+ "function removeShare(bytes32 shareId) external",
1845
+ "function sharesFor(address recipient) external view returns (ACP[] memory)",
1846
+ "function getShare(bytes32 shareId) external view returns (ACP memory)",
1847
+ "function isShareValid(bytes32 shareId) external view returns (bool)"
1848
+ ]);
1849
+ var ACP_TUPLE = [
1850
+ {
1851
+ type: "tuple",
1852
+ components: [
1853
+ { name: "issuer", type: "address" },
1854
+ { name: "expiration", type: "uint64" },
1855
+ { name: "recipient", type: "address" },
1856
+ { name: "revokerData", type: "uint256" },
1857
+ { name: "revokerContract", type: "address" },
1858
+ { name: "scope", type: "uint8" },
1859
+ { name: "contracts", type: "address[]" },
1860
+ { name: "handles", type: "bytes32[]" },
1861
+ { name: "sealingKey", type: "bytes32" },
1862
+ { name: "issuerSignature", type: "bytes" },
1863
+ { name: "recipientSignature", type: "bytes" }
1864
+ ]
1865
+ }
1866
+ ];
1867
+ var ZERO_BYTES32 = `0x${"0".repeat(64)}`;
1868
+ var toChainShare = (acp) => {
1869
+ const pub = ACPUtils.getPublic(acp, true);
1870
+ return {
1871
+ ...pub,
1872
+ expiration: BigInt(pub.expiration),
1873
+ revokerData: BigInt(pub.revokerData),
1874
+ sealingKey: ZERO_BYTES32,
1875
+ recipientSignature: "0x"
1876
+ };
1877
+ };
1878
+ var computeShareId = (acp) => {
1879
+ const p = toChainShare(acp);
1880
+ return keccak256(encodeAbiParameters(ACP_TUPLE, [p]));
1881
+ };
1882
+ var shareOnChain = async (acp, walletClient, registry) => {
1883
+ if (acp.type !== "sharing") {
1884
+ throw new Error(`Cannot share a '${acp.type}' ACP on-chain \u2014 only 'sharing' ACPs are shareable.`);
1885
+ }
1886
+ if (acp.issuerSignature === "0x") {
1887
+ throw new Error("Cannot share an unsigned sharing ACP \u2014 sign it first.");
1888
+ }
1889
+ if (walletClient.account == null)
1890
+ throw new Error("Missing walletClient account");
1891
+ if (walletClient.account.address.toLowerCase() !== acp.issuer.toLowerCase()) {
1892
+ throw new Error("Only the ACP issuer can share it on-chain");
1893
+ }
1894
+ const txHash = await walletClient.writeContract({
1895
+ address: registry,
1896
+ abi: ACP_SHARE_REGISTRY_ABI,
1897
+ functionName: "share",
1898
+ args: [toChainShare(acp)],
1899
+ account: walletClient.account,
1900
+ chain: walletClient.chain ?? null
1901
+ });
1902
+ return { txHash, shareId: computeShareId(acp) };
1903
+ };
1904
+ var getIncomingShares = async (publicClient, registry, recipient) => {
1905
+ const raw = await publicClient.readContract({
1906
+ address: registry,
1907
+ abi: ACP_SHARE_REGISTRY_ABI,
1908
+ functionName: "sharesFor",
1909
+ args: [recipient]
1910
+ });
1911
+ return raw.map((s) => ({
1912
+ shareId: keccak256(encodeAbiParameters(ACP_TUPLE, [s])),
1913
+ issuer: s.issuer,
1914
+ expiration: Number(s.expiration),
1915
+ recipient: s.recipient,
1916
+ revokerData: Number(s.revokerData),
1917
+ revokerContract: s.revokerContract,
1918
+ scope: Number(s.scope),
1919
+ contracts: [...s.contracts],
1920
+ handles: [...s.handles],
1921
+ issuerSignature: s.issuerSignature
1922
+ }));
1923
+ };
1924
+ var importFromChain = async (share, publicClient, walletClient) => {
1925
+ const { shareId: _shareId, ...options } = share;
1926
+ return importShared({ ...options, type: "sharing" }, publicClient, walletClient);
1927
+ };
1928
+ var removeShareOnChain = async (shareId, walletClient, registry) => {
1929
+ if (walletClient.account == null)
1930
+ throw new Error("Missing walletClient account");
1931
+ return walletClient.writeContract({
1932
+ address: registry,
1933
+ abi: ACP_SHARE_REGISTRY_ABI,
1934
+ functionName: "removeShare",
1935
+ args: [shareId],
1936
+ account: walletClient.account,
1937
+ chain: walletClient.chain ?? null
1938
+ });
1939
+ };
1940
+ var removeACP = async (chainId, account, hash) => acpStore.removeACP(chainId, account, hash);
1941
+ var removeActiveACP = async (chainId, account) => acpStore.removeActiveACPHash(chainId, account);
1942
+ var acps = {
1943
+ getSnapshot: acpStore.store.getState,
1944
+ subscribe: acpStore.store.subscribe,
1752
1945
  createSelf,
1753
1946
  createSharing,
1754
1947
  importShared,
1755
- getOrCreateSelfPermit,
1756
- getOrCreateSharingPermit,
1948
+ getOrCreateSelfACP,
1949
+ getOrCreateSharingACP,
1757
1950
  getHash,
1758
1951
  export: exportShared,
1759
1952
  serialize,
1760
1953
  deserialize,
1761
- getPermit,
1762
- getPermits,
1763
- getActivePermit,
1764
- getActivePermitHash,
1765
- removePermit,
1766
- selectActivePermit,
1767
- removeActivePermit
1954
+ getACP,
1955
+ getACPs,
1956
+ getActiveACP,
1957
+ getActiveACPHash,
1958
+ removeACP,
1959
+ selectActiveACP,
1960
+ removeActiveACP,
1961
+ revokeACP,
1962
+ revokeAllACPs,
1963
+ isACPRevoked,
1964
+ shareOnChain,
1965
+ getIncomingShares,
1966
+ importFromChain,
1967
+ removeShareOnChain,
1968
+ computeShareId,
1969
+ applyACPDefaults,
1970
+ applyACPDefaultsFromChain,
1971
+ getAclServedAddresses,
1972
+ clearAclServedAddresses
1768
1973
  };
1769
1974
  function uint160ToAddress(uint160) {
1770
1975
  const hexStr = uint160.toString(16).padStart(40, "0");
@@ -1827,13 +2032,16 @@ var MockThresholdNetworkAbi = [
1827
2032
  {
1828
2033
  name: "permission",
1829
2034
  type: "tuple",
1830
- internalType: "struct Permission",
2035
+ internalType: "struct ACPermission",
1831
2036
  components: [
1832
2037
  { name: "issuer", type: "address", internalType: "address" },
1833
2038
  { name: "expiration", type: "uint64", internalType: "uint64" },
1834
2039
  { name: "recipient", type: "address", internalType: "address" },
1835
- { name: "validatorId", type: "uint256", internalType: "uint256" },
1836
- { name: "validatorContract", type: "address", internalType: "address" },
2040
+ { name: "revokerData", type: "uint256", internalType: "uint256" },
2041
+ { name: "revokerContract", type: "address", internalType: "address" },
2042
+ { name: "scope", type: "uint8", internalType: "uint8" },
2043
+ { name: "contracts", type: "address[]", internalType: "address[]" },
2044
+ { name: "handles", type: "bytes32[]", internalType: "bytes32[]" },
1837
2045
  { name: "sealingKey", type: "bytes32", internalType: "bytes32" },
1838
2046
  { name: "issuerSignature", type: "bytes", internalType: "bytes" },
1839
2047
  { name: "recipientSignature", type: "bytes", internalType: "bytes" }
@@ -1856,13 +2064,16 @@ var MockThresholdNetworkAbi = [
1856
2064
  {
1857
2065
  name: "permission",
1858
2066
  type: "tuple",
1859
- internalType: "struct Permission",
2067
+ internalType: "struct ACPermission",
1860
2068
  components: [
1861
2069
  { name: "issuer", type: "address", internalType: "address" },
1862
2070
  { name: "expiration", type: "uint64", internalType: "uint64" },
1863
2071
  { name: "recipient", type: "address", internalType: "address" },
1864
- { name: "validatorId", type: "uint256", internalType: "uint256" },
1865
- { name: "validatorContract", type: "address", internalType: "address" },
2072
+ { name: "revokerData", type: "uint256", internalType: "uint256" },
2073
+ { name: "revokerContract", type: "address", internalType: "address" },
2074
+ { name: "scope", type: "uint8", internalType: "uint8" },
2075
+ { name: "contracts", type: "address[]", internalType: "address[]" },
2076
+ { name: "handles", type: "bytes32[]", internalType: "bytes32[]" },
1866
2077
  { name: "sealingKey", type: "bytes32", internalType: "bytes32" },
1867
2078
  { name: "issuerSignature", type: "bytes", internalType: "bytes" },
1868
2079
  { name: "recipientSignature", type: "bytes", internalType: "bytes" }
@@ -1927,19 +2138,22 @@ var MockThresholdNetworkAbi = [
1927
2138
  },
1928
2139
  {
1929
2140
  type: "function",
1930
- name: "decryptForTxWithPermit",
2141
+ name: "decryptForTxWithACP",
1931
2142
  inputs: [
1932
2143
  { name: "ctHash", type: "uint256", internalType: "uint256" },
1933
2144
  {
1934
2145
  name: "permission",
1935
2146
  type: "tuple",
1936
- internalType: "struct Permission",
2147
+ internalType: "struct ACPermission",
1937
2148
  components: [
1938
2149
  { name: "issuer", type: "address", internalType: "address" },
1939
2150
  { name: "expiration", type: "uint64", internalType: "uint64" },
1940
2151
  { name: "recipient", type: "address", internalType: "address" },
1941
- { name: "validatorId", type: "uint256", internalType: "uint256" },
1942
- { name: "validatorContract", type: "address", internalType: "address" },
2152
+ { name: "revokerData", type: "uint256", internalType: "uint256" },
2153
+ { name: "revokerContract", type: "address", internalType: "address" },
2154
+ { name: "scope", type: "uint8", internalType: "uint8" },
2155
+ { name: "contracts", type: "address[]", internalType: "address[]" },
2156
+ { name: "handles", type: "bytes32[]", internalType: "bytes32[]" },
1943
2157
  { name: "sealingKey", type: "bytes32", internalType: "bytes32" },
1944
2158
  { name: "issuerSignature", type: "bytes", internalType: "bytes" },
1945
2159
  { name: "recipientSignature", type: "bytes", internalType: "bytes" }
@@ -1955,7 +2169,7 @@ var MockThresholdNetworkAbi = [
1955
2169
  },
1956
2170
  {
1957
2171
  type: "function",
1958
- name: "decryptForTxWithoutPermit",
2172
+ name: "decryptForTxWithoutACP",
1959
2173
  inputs: [{ name: "ctHash", type: "uint256", internalType: "uint256" }],
1960
2174
  outputs: [
1961
2175
  { name: "allowed", type: "bool", internalType: "bool" },
@@ -1967,12 +2181,12 @@ var MockThresholdNetworkAbi = [
1967
2181
  ];
1968
2182
 
1969
2183
  // core/decrypt/cofheMocksDecryptForView.ts
1970
- async function cofheMocksDecryptForView(ctHash, utype, permit, publicClient) {
1971
- const permission = PermitUtils.getPermission(permit, true);
2184
+ async function cofheMocksDecryptForView(ctHash, utype, acp, publicClient) {
2185
+ const wireAcp = ACPUtils.getPublic(acp, true);
1972
2186
  const permissionWithBigInts = {
1973
- ...permission,
1974
- expiration: BigInt(permission.expiration),
1975
- validatorId: BigInt(permission.validatorId)
2187
+ ...wireAcp,
2188
+ expiration: BigInt(wireAcp.expiration),
2189
+ revokerData: BigInt(wireAcp.revokerData)
1976
2190
  };
1977
2191
  const [allowed, error, result] = await publicClient.readContract({
1978
2192
  address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
@@ -1993,11 +2207,41 @@ async function cofheMocksDecryptForView(ctHash, utype, permit, publicClient) {
1993
2207
  });
1994
2208
  }
1995
2209
  const sealedBigInt = BigInt(result);
1996
- const sealingKeyBigInt = BigInt(permission.sealingKey);
2210
+ const sealingKeyBigInt = BigInt(acp.sealingKey);
1997
2211
  const unsealed = sealedBigInt ^ sealingKeyBigInt;
1998
2212
  return unsealed;
1999
2213
  }
2000
2214
 
2215
+ // core/debug.ts
2216
+ var interceptors = {};
2217
+ function setCofheDebugInterceptors(next) {
2218
+ interceptors.onRequest = next?.onRequest;
2219
+ interceptors.onResponse = next?.onResponse;
2220
+ }
2221
+ function getCofheDebugInterceptors() {
2222
+ return interceptors;
2223
+ }
2224
+ async function cofheFetch(url, init, ctx = { op: "request" }) {
2225
+ let finalUrl = url;
2226
+ let finalInit = init;
2227
+ if (interceptors.onRequest) {
2228
+ const override = await interceptors.onRequest(finalUrl, finalInit, ctx);
2229
+ if (override) {
2230
+ if (override.url !== void 0)
2231
+ finalUrl = override.url;
2232
+ if (override.init !== void 0)
2233
+ finalInit = override.init;
2234
+ }
2235
+ }
2236
+ let response = await fetch(finalUrl, finalInit);
2237
+ if (interceptors.onResponse) {
2238
+ const replaced = await interceptors.onResponse(response, ctx);
2239
+ if (replaced)
2240
+ response = replaced;
2241
+ }
2242
+ return response;
2243
+ }
2244
+
2001
2245
  // core/decrypt/polling.ts
2002
2246
  function computeMinuteRampPollIntervalMs(elapsedMs, params) {
2003
2247
  const elapsedSeconds = Math.floor(elapsedMs / 1e3);
@@ -2006,11 +2250,61 @@ function computeMinuteRampPollIntervalMs(elapsedMs, params) {
2006
2250
  return Math.min(params.maxIntervalMs, Math.max(params.minIntervalMs, intervalMs));
2007
2251
  }
2008
2252
 
2253
+ // core/decrypt/apiError.ts
2254
+ var BACKEND_ERROR_CODE_TO_COFHE_ERROR_CODE = {
2255
+ bad_request: "BAD_REQUEST" /* BadRequest */,
2256
+ unknown_chain: "UNKNOWN_CHAIN" /* UnknownChain */,
2257
+ acp_malformed: "ACP_MALFORMED" /* ACPMalformed */,
2258
+ acp_denied: "ACP_DENIED" /* ACPDenied */,
2259
+ // ACP-era backends fold revoked into denied
2260
+ acp_expired: "ACP_EXPIRED" /* ACPExpired */,
2261
+ acp_invalid: "ACP_INVALID" /* ACPInvalid */,
2262
+ acp_required: "ACP_REQUIRED" /* ACPRequired */,
2263
+ acp_verifier_error: "ACP_VERIFIER_ERROR" /* ACPVerifierError */,
2264
+ acp_verifier_timeout: "ACP_VERIFIER_TIMEOUT" /* ACPVerifierTimeout */,
2265
+ not_publicly_allowed: "NOT_PUBLICLY_ALLOWED" /* NotPubliclyAllowed */,
2266
+ ct_not_found: "CT_NOT_FOUND" /* CtNotFound */,
2267
+ unsupported_security_zone: "UNSUPPORTED_SECURITY_ZONE" /* UnsupportedSecurityZone */,
2268
+ unsupported_type: "UNSUPPORTED_TYPE" /* UnsupportedType */,
2269
+ internal_error: "INTERNAL_ERROR" /* InternalError */,
2270
+ signing_failed: "SIGNING_FAILED" /* SigningFailed */,
2271
+ ct_source_error: "CT_SOURCE_ERROR" /* CtSourceError */,
2272
+ ct_source_timeout: "CT_SOURCE_TIMEOUT" /* CtSourceTimeout */,
2273
+ seal_failed: "SEAL_FAILED" /* SealFailed */
2274
+ };
2275
+ function isBackendApiErrorCode(value) {
2276
+ return value in BACKEND_ERROR_CODE_TO_COFHE_ERROR_CODE;
2277
+ }
2278
+ async function parseApiErrorResponseBody(response) {
2279
+ let errorMessage = `HTTP ${response.status}`;
2280
+ let apiErrorCode;
2281
+ try {
2282
+ const body = await response.json();
2283
+ if (body && typeof body === "object") {
2284
+ const record = body;
2285
+ if (typeof record.error === "string" && record.error.length > 0) {
2286
+ apiErrorCode = record.error;
2287
+ }
2288
+ if (typeof record.error_message === "string" && record.error_message.length > 0) {
2289
+ errorMessage = record.error_message;
2290
+ } else if (typeof record.message === "string" && record.message.length > 0) {
2291
+ errorMessage = record.message;
2292
+ }
2293
+ }
2294
+ } catch {
2295
+ errorMessage = response.statusText || errorMessage;
2296
+ }
2297
+ return { apiErrorCode, errorMessage };
2298
+ }
2299
+ function mapApiErrorCodeToCofheErrorCode(apiErrorCode, fallback) {
2300
+ if (apiErrorCode && isBackendApiErrorCode(apiErrorCode)) {
2301
+ return BACKEND_ERROR_CODE_TO_COFHE_ERROR_CODE[apiErrorCode];
2302
+ }
2303
+ return fallback;
2304
+ }
2305
+
2009
2306
  // core/decrypt/submitRetry.ts
2010
2307
  var DEFAULT_404_RETRY_TIMEOUT_MS = 1e4;
2011
- function isRetryableSubmitStatus(status) {
2012
- return status === 204 || status === 404;
2013
- }
2014
2308
  function normalize404RetryTimeoutMs(params) {
2015
2309
  const { timeoutMs, operationLabel, errorCode } = params;
2016
2310
  if (timeoutMs === void 0)
@@ -2027,32 +2321,24 @@ function normalize404RetryTimeoutMs(params) {
2027
2321
  return timeoutMs;
2028
2322
  }
2029
2323
  async function classifySubmitResponse(params) {
2030
- const { response, extractErrorMessage } = params;
2031
- if (isRetryableSubmitStatus(response.status)) {
2032
- return { kind: "retryable", status: response.status };
2324
+ const { response, fallbackErrorCode } = params;
2325
+ if (response.status === 204) {
2326
+ return { kind: "retryable", status: 204 };
2033
2327
  }
2034
2328
  if (response.ok) {
2035
2329
  return { kind: "parse-json" };
2036
2330
  }
2037
- let errorMessage = `HTTP ${response.status}`;
2038
- try {
2039
- const errorBody = await response.json();
2040
- const maybeErrorMessage = extractErrorMessage?.(errorBody);
2041
- if (typeof maybeErrorMessage === "string" && maybeErrorMessage.length > 0) {
2042
- errorMessage = maybeErrorMessage;
2043
- } else if (errorBody && typeof errorBody === "object") {
2044
- const defaultMessage = errorBody.error_message;
2045
- const fallbackMessage = errorBody.message;
2046
- if (typeof defaultMessage === "string" && defaultMessage.length > 0) {
2047
- errorMessage = defaultMessage;
2048
- } else if (typeof fallbackMessage === "string" && fallbackMessage.length > 0) {
2049
- errorMessage = fallbackMessage;
2050
- }
2051
- }
2052
- } catch {
2053
- errorMessage = response.statusText || errorMessage;
2331
+ const { apiErrorCode, errorMessage } = await parseApiErrorResponseBody(response);
2332
+ if (response.status === 404) {
2333
+ return { kind: "retryable", status: 404, apiErrorMessage: errorMessage };
2054
2334
  }
2055
- return { kind: "fatal-http", errorMessage };
2335
+ return {
2336
+ kind: "fatal-http",
2337
+ status: response.status,
2338
+ cofheErrorCode: mapApiErrorCodeToCofheErrorCode(apiErrorCode, fallbackErrorCode),
2339
+ apiErrorCode,
2340
+ errorMessage
2341
+ };
2056
2342
  }
2057
2343
  function throwIfSubmitRetryTimedOut(params) {
2058
2344
  const {
@@ -2064,12 +2350,14 @@ function throwIfSubmitRetryTimedOut(params) {
2064
2350
  overallTimeoutMs,
2065
2351
  thresholdNetworkUrl,
2066
2352
  body,
2067
- attemptIndex
2353
+ attemptIndex,
2354
+ lastKnownErrorMessage
2068
2355
  } = params;
2069
2356
  if (status === 404 && elapsedMs > retry404TimeoutMs) {
2070
2357
  throw new CofheError({
2071
- code: errorCode,
2072
- message: `${operationLabel} submit retried 404 responses without receiving request_id for ${retry404TimeoutMs}ms`,
2358
+ code: "CT_NOT_FOUND" /* CtNotFound */,
2359
+ apiErrorCode: "ct_not_found",
2360
+ message: `${operationLabel} ciphertext not found after retrying for ${retry404TimeoutMs}ms` + (lastKnownErrorMessage ? `: ${lastKnownErrorMessage}` : ""),
2073
2361
  hint: "The ciphertext may not be indexed yet. Increase set404RetryTimeout(...) if the backend is slow to index ciphertexts.",
2074
2362
  context: {
2075
2363
  thresholdNetworkUrl,
@@ -2095,6 +2383,62 @@ function throwIfSubmitRetryTimedOut(params) {
2095
2383
  });
2096
2384
  }
2097
2385
  }
2386
+ function normalizeTnSignature(signature) {
2387
+ if (typeof signature !== "string") {
2388
+ throw new CofheError({
2389
+ code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2390
+ message: "decrypt response missing signature",
2391
+ context: {
2392
+ signature
2393
+ }
2394
+ });
2395
+ }
2396
+ const trimmed = signature.trim();
2397
+ if (trimmed.length === 0) {
2398
+ throw new CofheError({
2399
+ code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2400
+ message: "decrypt response returned empty signature"
2401
+ });
2402
+ }
2403
+ const prefixed = trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
2404
+ const parsed = parseSignature(prefixed);
2405
+ return serializeSignature(parsed);
2406
+ }
2407
+ function parseDecryptedBytesToBigInt(decrypted) {
2408
+ if (!Array.isArray(decrypted)) {
2409
+ throw new CofheError({
2410
+ code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2411
+ message: "decrypt response field <decrypted> must be a byte array",
2412
+ context: {
2413
+ decrypted
2414
+ }
2415
+ });
2416
+ }
2417
+ if (decrypted.length === 0) {
2418
+ throw new CofheError({
2419
+ code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2420
+ message: "decrypt response field <decrypted> was an empty byte array",
2421
+ context: {
2422
+ decrypted
2423
+ }
2424
+ });
2425
+ }
2426
+ let hex = "";
2427
+ for (const b of decrypted) {
2428
+ if (typeof b !== "number" || !Number.isInteger(b) || b < 0 || b > 255) {
2429
+ throw new CofheError({
2430
+ code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2431
+ message: "decrypt response field <decrypted> contained a non-byte value",
2432
+ context: {
2433
+ badElement: b,
2434
+ decrypted
2435
+ }
2436
+ });
2437
+ }
2438
+ hex += b.toString(16).padStart(2, "0");
2439
+ }
2440
+ return BigInt(`0x${hex}`);
2441
+ }
2098
2442
 
2099
2443
  // core/decrypt/tnSealOutputV2.ts
2100
2444
  var POLL_INTERVAL_MS = 1e3;
@@ -2157,23 +2501,28 @@ function parseCompletedSealOutputResponse(params) {
2157
2501
  }
2158
2502
  return convertSealedData(sealed);
2159
2503
  }
2160
- async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission, overallStartTime, retry404TimeoutMs, onPoll) {
2504
+ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, acp, overallStartTime, retry404TimeoutMs, onPoll) {
2161
2505
  const body = {
2162
2506
  ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
2163
2507
  host_chain_id: chainId,
2164
- permit: permission
2508
+ acp
2165
2509
  };
2166
2510
  let attemptIndex = 0;
2511
+ let last404ApiErrorMessage;
2167
2512
  for (; ; ) {
2168
2513
  let response;
2169
2514
  try {
2170
- response = await fetch(`${thresholdNetworkUrl}/v2/sealoutput`, {
2171
- method: "POST",
2172
- headers: {
2173
- "Content-Type": "application/json"
2174
- },
2175
- body: JSON.stringify(body)
2176
- });
2515
+ response = await cofheFetch(
2516
+ `${thresholdNetworkUrl}/v2/sealoutput`,
2517
+ /*op:sealoutput*/
2518
+ {
2519
+ method: "POST",
2520
+ headers: {
2521
+ "Content-Type": "application/json"
2522
+ },
2523
+ body: JSON.stringify(body)
2524
+ }
2525
+ );
2177
2526
  } catch (e) {
2178
2527
  throw new CofheError({
2179
2528
  code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
@@ -2187,16 +2536,19 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
2187
2536
  }
2188
2537
  });
2189
2538
  }
2190
- const responseClassification = await classifySubmitResponse({ response });
2539
+ const responseClassification = await classifySubmitResponse({
2540
+ response,
2541
+ fallbackErrorCode: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */
2542
+ });
2191
2543
  if (responseClassification.kind === "fatal-http") {
2192
2544
  throw new CofheError({
2193
- code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2545
+ code: responseClassification.cofheErrorCode,
2546
+ apiErrorCode: responseClassification.apiErrorCode,
2194
2547
  message: `sealOutput request failed: ${responseClassification.errorMessage}`,
2195
2548
  hint: "Check the threshold network URL and request parameters.",
2196
2549
  context: {
2197
2550
  thresholdNetworkUrl,
2198
- status: response.status,
2199
- statusText: response.statusText,
2551
+ status: responseClassification.status,
2200
2552
  body,
2201
2553
  attemptIndex
2202
2554
  }
@@ -2242,6 +2594,9 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
2242
2594
  }
2243
2595
  });
2244
2596
  }
2597
+ if (responseClassification.status === 404) {
2598
+ last404ApiErrorMessage = responseClassification.apiErrorMessage;
2599
+ }
2245
2600
  const elapsedMs = Date.now() - overallStartTime;
2246
2601
  throwIfSubmitRetryTimedOut({
2247
2602
  operationLabel: "sealOutput",
@@ -2252,7 +2607,8 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
2252
2607
  overallTimeoutMs: SEAL_OUTPUT_TIMEOUT_MS,
2253
2608
  thresholdNetworkUrl,
2254
2609
  body,
2255
- attemptIndex
2610
+ attemptIndex,
2611
+ lastKnownErrorMessage: last404ApiErrorMessage
2256
2612
  });
2257
2613
  onPoll?.({
2258
2614
  operation: "sealoutput",
@@ -2296,12 +2652,16 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId, overallStart
2296
2652
  }
2297
2653
  let response;
2298
2654
  try {
2299
- response = await fetch(`${thresholdNetworkUrl}/v2/sealoutput/${requestId}`, {
2300
- method: "GET",
2301
- headers: {
2302
- "Content-Type": "application/json"
2655
+ response = await cofheFetch(
2656
+ `${thresholdNetworkUrl}/v2/sealoutput/${requestId}`,
2657
+ /*op:sealoutput-poll*/
2658
+ {
2659
+ method: "GET",
2660
+ headers: {
2661
+ "Content-Type": "application/json"
2662
+ }
2303
2663
  }
2304
- });
2664
+ );
2305
2665
  } catch (e) {
2306
2666
  throw new CofheError({
2307
2667
  code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
@@ -2326,15 +2686,10 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId, overallStart
2326
2686
  });
2327
2687
  }
2328
2688
  if (!response.ok) {
2329
- let errorMessage = `HTTP ${response.status}`;
2330
- try {
2331
- const errorBody = await response.json();
2332
- errorMessage = errorBody.error_message || errorBody.message || errorMessage;
2333
- } catch {
2334
- errorMessage = response.statusText || errorMessage;
2335
- }
2689
+ const { apiErrorCode, errorMessage } = await parseApiErrorResponseBody(response);
2336
2690
  throw new CofheError({
2337
- code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2691
+ code: mapApiErrorCodeToCofheErrorCode(apiErrorCode, "SEAL_OUTPUT_FAILED" /* SealOutputFailed */),
2692
+ apiErrorCode,
2338
2693
  message: `sealOutput status poll failed: ${errorMessage}`,
2339
2694
  context: {
2340
2695
  thresholdNetworkUrl,
@@ -2378,7 +2733,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId, overallStart
2378
2733
  });
2379
2734
  }
2380
2735
  async function tnSealOutputV2(params) {
2381
- const { thresholdNetworkUrl, ctHash, chainId, permission, retry404TimeoutMs, onPoll } = params;
2736
+ const { thresholdNetworkUrl, ctHash, chainId, acp, retry404TimeoutMs, onPoll } = params;
2382
2737
  const normalized404RetryTimeoutMs = normalize404RetryTimeoutMs({
2383
2738
  timeoutMs: retry404TimeoutMs,
2384
2739
  operationLabel: "sealOutput",
@@ -2389,7 +2744,7 @@ async function tnSealOutputV2(params) {
2389
2744
  thresholdNetworkUrl,
2390
2745
  ctHash,
2391
2746
  chainId,
2392
- permission,
2747
+ acp,
2393
2748
  overallStartTime,
2394
2749
  normalized404RetryTimeoutMs,
2395
2750
  onPoll
@@ -2405,8 +2760,8 @@ var DEFAULT_404_RETRY_TIMEOUT_MS2 = 1e4;
2405
2760
  var DecryptForViewBuilder = class extends BaseBuilder {
2406
2761
  ctHash;
2407
2762
  utype;
2408
- permitHash;
2409
- permit;
2763
+ acpHash;
2764
+ acp;
2410
2765
  pollCallback;
2411
2766
  retry404TimeoutMs = DEFAULT_404_RETRY_TIMEOUT_MS2;
2412
2767
  constructor(params) {
@@ -2420,11 +2775,11 @@ var DecryptForViewBuilder = class extends BaseBuilder {
2420
2775
  });
2421
2776
  this.ctHash = params.ctHash;
2422
2777
  this.utype = params.utype;
2423
- this.permitHash = params.permitHash;
2424
- this.permit = params.permit;
2778
+ this.acpHash = params.acpHash;
2779
+ this.acp = params.acp;
2425
2780
  }
2426
2781
  /**
2427
- * @param chainId - Chain to decrypt values from. Used to fetch the threshold network URL and use the correct permit.
2782
+ * @param chainId - Chain to decrypt values from. Used to fetch the threshold network URL and use the correct acp.
2428
2783
  *
2429
2784
  * If not provided, the chainId will be fetched from the connected publicClient.
2430
2785
  *
@@ -2445,7 +2800,7 @@ var DecryptForViewBuilder = class extends BaseBuilder {
2445
2800
  return this.chainId;
2446
2801
  }
2447
2802
  /**
2448
- * @param account - Account to decrypt values from. Used to fetch the correct permit.
2803
+ * @param account - Account to decrypt values from. Used to fetch the correct acp.
2449
2804
  *
2450
2805
  * If not provided, the account will be fetched from the connected walletClient.
2451
2806
  *
@@ -2482,61 +2837,61 @@ var DecryptForViewBuilder = class extends BaseBuilder {
2482
2837
  this.retry404TimeoutMs = timeoutMs;
2483
2838
  return this;
2484
2839
  }
2485
- withPermit(permitOrPermitHash) {
2486
- if (typeof permitOrPermitHash === "string") {
2487
- this.permitHash = permitOrPermitHash;
2488
- this.permit = void 0;
2489
- } else if (permitOrPermitHash === void 0) {
2490
- this.permitHash = void 0;
2491
- this.permit = void 0;
2840
+ withACP(acpOrACPHash) {
2841
+ if (typeof acpOrACPHash === "string") {
2842
+ this.acpHash = acpOrACPHash;
2843
+ this.acp = void 0;
2844
+ } else if (acpOrACPHash === void 0) {
2845
+ this.acpHash = void 0;
2846
+ this.acp = void 0;
2492
2847
  } else {
2493
- this.permit = permitOrPermitHash;
2494
- this.permitHash = void 0;
2848
+ this.acp = acpOrACPHash;
2849
+ this.acpHash = void 0;
2495
2850
  }
2496
2851
  return this;
2497
2852
  }
2498
2853
  /**
2499
- * @param permitHash - Permit hash to decrypt values from. Used to fetch the correct permit.
2854
+ * @param acpHash - ACP hash to decrypt values from. Used to fetch the correct acp.
2500
2855
  *
2501
- * If not provided, the active permit for the chainId and account will be used.
2502
- * If `setPermit()` is called, it will be used regardless of chainId, account, or permitHash.
2856
+ * If not provided, the active acp for the chainId and account will be used.
2857
+ * If `setACP()` is called, it will be used regardless of chainId, account, or acpHash.
2503
2858
  *
2504
2859
  * Example:
2505
2860
  * ```typescript
2506
2861
  * const unsealed = await client.decryptForView(ctHash, utype)
2507
- * .setPermitHash('0x1234567890123456789012345678901234567890')
2862
+ * .setACPHash('0x1234567890123456789012345678901234567890')
2508
2863
  * .execute();
2509
2864
  * ```
2510
2865
  *
2511
2866
  * @returns The chainable DecryptForViewBuilder instance.
2512
2867
  */
2513
- /** @deprecated Use `withPermit(permitHash)` instead. */
2514
- setPermitHash(permitHash) {
2515
- return this.withPermit(permitHash);
2868
+ /** @deprecated Use `withACP(acpHash)` instead. */
2869
+ setACPHash(acpHash) {
2870
+ return this.withACP(acpHash);
2516
2871
  }
2517
- getPermitHash() {
2518
- return this.permitHash;
2872
+ getACPHash() {
2873
+ return this.acpHash;
2519
2874
  }
2520
2875
  /**
2521
- * @param permit - Permit to decrypt values with. If provided, it will be used regardless of chainId, account, or permitHash.
2876
+ * @param acp - ACP to decrypt values with. If provided, it will be used regardless of chainId, account, or acpHash.
2522
2877
  *
2523
- * If not provided, the permit will be determined by chainId, account, and permitHash.
2878
+ * If not provided, the acp will be determined by chainId, account, and acpHash.
2524
2879
  *
2525
2880
  * Example:
2526
2881
  * ```typescript
2527
2882
  * const unsealed = await client.decryptForView(ctHash, utype)
2528
- * .setPermit(permit)
2883
+ * .setACP(acp)
2529
2884
  * .execute();
2530
2885
  * ```
2531
2886
  *
2532
2887
  * @returns The chainable DecryptForViewBuilder instance.
2533
2888
  */
2534
- /** @deprecated Use `withPermit(permit)` instead. */
2535
- setPermit(permit) {
2536
- return this.withPermit(permit);
2889
+ /** @deprecated Use `withACP(acp)` instead. */
2890
+ setACP(acp) {
2891
+ return this.withACP(acp);
2537
2892
  }
2538
- getPermit() {
2539
- return this.permit;
2893
+ getACP() {
2894
+ return this.acp;
2540
2895
  }
2541
2896
  async getThresholdNetworkUrl() {
2542
2897
  this.assertChainId();
@@ -2552,77 +2907,77 @@ var DecryptForViewBuilder = class extends BaseBuilder {
2552
2907
  }
2553
2908
  });
2554
2909
  }
2555
- async getResolvedPermit() {
2556
- if (this.permit)
2557
- return this.permit;
2910
+ async getResolvedACP() {
2911
+ if (this.acp)
2912
+ return this.acp;
2558
2913
  this.assertChainId();
2559
2914
  this.assertAccount();
2560
- if (this.permitHash) {
2561
- const permit2 = await permits.getPermit(this.chainId, this.account, this.permitHash);
2562
- if (!permit2) {
2915
+ if (this.acpHash) {
2916
+ const acp2 = await acps.getACP(this.chainId, this.account, this.acpHash);
2917
+ if (!acp2) {
2563
2918
  throw new CofheError({
2564
- code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
2565
- message: `Permit with hash <${this.permitHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
2566
- hint: "Ensure the permit exists and is valid.",
2919
+ code: "ACP_NOT_FOUND" /* ACPNotFound */,
2920
+ message: `ACP with hash <${this.acpHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
2921
+ hint: "Ensure the acp exists and is valid.",
2567
2922
  context: {
2568
2923
  chainId: this.chainId,
2569
2924
  account: this.account,
2570
- permitHash: this.permitHash
2925
+ acpHash: this.acpHash
2571
2926
  }
2572
2927
  });
2573
2928
  }
2574
- return permit2;
2929
+ return acp2;
2575
2930
  }
2576
- const permit = await permits.getActivePermit(this.chainId, this.account);
2577
- if (!permit) {
2931
+ const acp = await acps.getActiveACP(this.chainId, this.account);
2932
+ if (!acp) {
2578
2933
  throw new CofheError({
2579
- code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
2580
- message: `Active permit not found for chainId <${this.chainId}> and account <${this.account}>`,
2581
- hint: "Ensure a permit exists for this account on this chain.",
2934
+ code: "ACP_NOT_FOUND" /* ACPNotFound */,
2935
+ message: `Active acp not found for chainId <${this.chainId}> and account <${this.account}>`,
2936
+ hint: "Ensure an ACP exists for this account on this chain.",
2582
2937
  context: {
2583
2938
  chainId: this.chainId,
2584
2939
  account: this.account
2585
2940
  }
2586
2941
  });
2587
2942
  }
2588
- return permit;
2943
+ return acp;
2589
2944
  }
2590
2945
  /**
2591
2946
  * On hardhat, interact with MockZkVerifier contract instead of CoFHE
2592
2947
  */
2593
- async mocksSealOutput(permit) {
2948
+ async mocksSealOutput(acp) {
2594
2949
  this.assertPublicClient();
2595
2950
  const mocksDecryptDelay = this.config.mocks.decryptDelay;
2596
2951
  if (mocksDecryptDelay > 0)
2597
2952
  await sleep(mocksDecryptDelay);
2598
- return cofheMocksDecryptForView(this.ctHash, this.utype, permit, this.publicClient);
2953
+ return cofheMocksDecryptForView(this.ctHash, this.utype, acp, this.publicClient);
2599
2954
  }
2600
2955
  /**
2601
2956
  * In the production context, perform a true decryption with the CoFHE coprocessor.
2602
2957
  */
2603
- async productionSealOutput(permit) {
2958
+ async productionSealOutput(acp) {
2604
2959
  this.assertChainId();
2605
2960
  this.assertPublicClient();
2606
2961
  const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
2607
- const permission = PermitUtils.getPermission(permit, true);
2962
+ const wireAcp = ACPUtils.getPublic(acp, true);
2608
2963
  const sealed = await tnSealOutputV2({
2609
2964
  ctHash: this.ctHash,
2610
2965
  chainId: this.chainId,
2611
- permission,
2966
+ acp: wireAcp,
2612
2967
  thresholdNetworkUrl,
2613
2968
  retry404TimeoutMs: this.retry404TimeoutMs,
2614
2969
  onPoll: this.pollCallback
2615
2970
  });
2616
- return PermitUtils.unseal(permit, sealed);
2971
+ return ACPUtils.unseal(acp, sealed);
2617
2972
  }
2618
2973
  /**
2619
2974
  * Final step of the decryption process. MUST BE CALLED LAST IN THE CHAIN.
2620
2975
  *
2621
2976
  * This will:
2622
- * - Use a permit based on provided permit OR chainId + account + permitHash
2623
- * - Check permit validity
2624
- * - Call CoFHE `/sealoutput` with the permit, which returns a sealed (encrypted) item
2625
- * - Unseal the sealed item with the permit
2977
+ * - Use an ACP based on provided acp OR chainId + account + acpHash
2978
+ * - Check acp validity
2979
+ * - Call CoFHE `/sealoutput` with the acp, which returns a sealed (encrypted) item
2980
+ * - Unseal the sealed item with the acp
2626
2981
  * - Return the unsealed item
2627
2982
  *
2628
2983
  * Example:
@@ -2630,7 +2985,7 @@ var DecryptForViewBuilder = class extends BaseBuilder {
2630
2985
  * const unsealed = await client.decryptForView(ctHash, utype)
2631
2986
  * .setChainId(11155111) // optional
2632
2987
  * .setAccount('0x123...890') // optional
2633
- * .withPermit() // optional
2988
+ * .withACP() // optional
2634
2989
  * .execute(); // execute
2635
2990
  * ```
2636
2991
  *
@@ -2638,14 +2993,14 @@ var DecryptForViewBuilder = class extends BaseBuilder {
2638
2993
  */
2639
2994
  async execute() {
2640
2995
  this.validateUtypeOrThrow();
2641
- const permit = await this.getResolvedPermit();
2642
- PermitUtils.validate(permit);
2643
- const chainId = permit._signedDomain.chainId;
2996
+ const acp = await this.getResolvedACP();
2997
+ ACPUtils.validate(acp);
2998
+ const chainId = acp._signedDomain.chainId;
2644
2999
  let unsealed;
2645
3000
  if (chainId === hardhat$1.id) {
2646
- unsealed = await this.mocksSealOutput(permit);
3001
+ unsealed = await this.mocksSealOutput(acp);
2647
3002
  } else {
2648
- unsealed = await this.productionSealOutput(permit);
3003
+ unsealed = await this.productionSealOutput(acp);
2649
3004
  }
2650
3005
  return convertViaUtype(this.utype, unsealed);
2651
3006
  }
@@ -2653,28 +3008,28 @@ var DecryptForViewBuilder = class extends BaseBuilder {
2653
3008
  var UINT_TYPE_MASK = 0x7fn;
2654
3009
  var TYPE_BYTE_OFFSET = 8n;
2655
3010
  var getEncryptionTypeFromCtHash = (ctHash) => Number(ctHash >> TYPE_BYTE_OFFSET & UINT_TYPE_MASK);
2656
- async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient) {
3011
+ async function cofheMocksDecryptForTx(ctHash, utype, acp, publicClient) {
2657
3012
  let allowed;
2658
3013
  let error;
2659
3014
  let decryptedValue;
2660
- if (permit !== null) {
2661
- let permission = PermitUtils.getPermission(permit, true);
3015
+ if (acp !== null) {
3016
+ const wireAcp = ACPUtils.getPublic(acp, true);
2662
3017
  const permissionWithBigInts = {
2663
- ...permission,
2664
- expiration: BigInt(permission.expiration),
2665
- validatorId: BigInt(permission.validatorId)
3018
+ ...wireAcp,
3019
+ expiration: BigInt(wireAcp.expiration),
3020
+ revokerData: BigInt(wireAcp.revokerData)
2666
3021
  };
2667
3022
  [allowed, error, decryptedValue] = await publicClient.readContract({
2668
3023
  address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
2669
3024
  abi: MockThresholdNetworkAbi,
2670
- functionName: "decryptForTxWithPermit",
3025
+ functionName: "decryptForTxWithACP",
2671
3026
  args: [BigInt(ctHash), permissionWithBigInts]
2672
3027
  });
2673
3028
  } else {
2674
3029
  [allowed, error, decryptedValue] = await publicClient.readContract({
2675
3030
  address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
2676
3031
  abi: MockThresholdNetworkAbi,
2677
- functionName: "decryptForTxWithoutPermit",
3032
+ functionName: "decryptForTxWithoutACP",
2678
3033
  args: [BigInt(ctHash)]
2679
3034
  });
2680
3035
  }
@@ -2709,62 +3064,6 @@ async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient) {
2709
3064
  signature
2710
3065
  };
2711
3066
  }
2712
- function normalizeTnSignature(signature) {
2713
- if (typeof signature !== "string") {
2714
- throw new CofheError({
2715
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2716
- message: "decrypt response missing signature",
2717
- context: {
2718
- signature
2719
- }
2720
- });
2721
- }
2722
- const trimmed = signature.trim();
2723
- if (trimmed.length === 0) {
2724
- throw new CofheError({
2725
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2726
- message: "decrypt response returned empty signature"
2727
- });
2728
- }
2729
- const prefixed = trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
2730
- const parsed = parseSignature(prefixed);
2731
- return serializeSignature(parsed);
2732
- }
2733
- function parseDecryptedBytesToBigInt(decrypted) {
2734
- if (!Array.isArray(decrypted)) {
2735
- throw new CofheError({
2736
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2737
- message: "decrypt response field <decrypted> must be a byte array",
2738
- context: {
2739
- decrypted
2740
- }
2741
- });
2742
- }
2743
- if (decrypted.length === 0) {
2744
- throw new CofheError({
2745
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2746
- message: "decrypt response field <decrypted> was an empty byte array",
2747
- context: {
2748
- decrypted
2749
- }
2750
- });
2751
- }
2752
- let hex = "";
2753
- for (const b of decrypted) {
2754
- if (typeof b !== "number" || !Number.isInteger(b) || b < 0 || b > 255) {
2755
- throw new CofheError({
2756
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2757
- message: "decrypt response field <decrypted> contained a non-byte value",
2758
- context: {
2759
- badElement: b,
2760
- decrypted
2761
- }
2762
- });
2763
- }
2764
- hex += b.toString(16).padStart(2, "0");
2765
- }
2766
- return BigInt(`0x${hex}`);
2767
- }
2768
3067
 
2769
3068
  // core/decrypt/tnDecryptV2.ts
2770
3069
  var POLL_INTERVAL_MS2 = 1e3;
@@ -2886,25 +3185,30 @@ function assertDecryptStatusResponseV2(value) {
2886
3185
  }
2887
3186
  return value;
2888
3187
  }
2889
- async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, permission, overallStartTime, retry404TimeoutMs, onPoll) {
3188
+ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, acp, overallStartTime, retry404TimeoutMs, onPoll) {
2890
3189
  const body = {
2891
3190
  ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
2892
3191
  host_chain_id: chainId
2893
3192
  };
2894
- if (permission) {
2895
- body.permit = permission;
3193
+ if (acp) {
3194
+ body.acp = acp;
2896
3195
  }
2897
3196
  let attemptIndex = 0;
3197
+ let last404ApiErrorMessage;
2898
3198
  for (; ; ) {
2899
3199
  let response;
2900
3200
  try {
2901
- response = await fetch(`${thresholdNetworkUrl}/v2/decrypt`, {
2902
- method: "POST",
2903
- headers: {
2904
- "Content-Type": "application/json"
2905
- },
2906
- body: JSON.stringify(body)
2907
- });
3201
+ response = await cofheFetch(
3202
+ `${thresholdNetworkUrl}/v2/decrypt`,
3203
+ /*op:decrypt*/
3204
+ {
3205
+ method: "POST",
3206
+ headers: {
3207
+ "Content-Type": "application/json"
3208
+ },
3209
+ body: JSON.stringify(body)
3210
+ }
3211
+ );
2908
3212
  } catch (e) {
2909
3213
  throw new CofheError({
2910
3214
  code: "DECRYPT_FAILED" /* DecryptFailed */,
@@ -2918,16 +3222,19 @@ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, perm
2918
3222
  }
2919
3223
  });
2920
3224
  }
2921
- const responseClassification = await classifySubmitResponse({ response });
3225
+ const responseClassification = await classifySubmitResponse({
3226
+ response,
3227
+ fallbackErrorCode: "DECRYPT_FAILED" /* DecryptFailed */
3228
+ });
2922
3229
  if (responseClassification.kind === "fatal-http") {
2923
3230
  throw new CofheError({
2924
- code: "DECRYPT_FAILED" /* DecryptFailed */,
3231
+ code: responseClassification.cofheErrorCode,
3232
+ apiErrorCode: responseClassification.apiErrorCode,
2925
3233
  message: `decrypt request failed: ${responseClassification.errorMessage}`,
2926
3234
  hint: "Check the threshold network URL and request parameters.",
2927
3235
  context: {
2928
3236
  thresholdNetworkUrl,
2929
- status: response.status,
2930
- statusText: response.statusText,
3237
+ status: responseClassification.status,
2931
3238
  body,
2932
3239
  attemptIndex
2933
3240
  }
@@ -2975,6 +3282,9 @@ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, perm
2975
3282
  }
2976
3283
  });
2977
3284
  }
3285
+ if (responseClassification.status === 404) {
3286
+ last404ApiErrorMessage = responseClassification.apiErrorMessage;
3287
+ }
2978
3288
  const elapsedMs = Date.now() - overallStartTime;
2979
3289
  throwIfSubmitRetryTimedOut({
2980
3290
  operationLabel: "decrypt",
@@ -2985,7 +3295,8 @@ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, perm
2985
3295
  overallTimeoutMs: DECRYPT_TIMEOUT_MS,
2986
3296
  thresholdNetworkUrl,
2987
3297
  body,
2988
- attemptIndex
3298
+ attemptIndex,
3299
+ lastKnownErrorMessage: last404ApiErrorMessage
2989
3300
  });
2990
3301
  onPoll?.({
2991
3302
  operation: "decrypt",
@@ -3029,12 +3340,16 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId, overallStartT
3029
3340
  }
3030
3341
  let response;
3031
3342
  try {
3032
- response = await fetch(`${thresholdNetworkUrl}/v2/decrypt/${requestId}`, {
3033
- method: "GET",
3034
- headers: {
3035
- "Content-Type": "application/json"
3343
+ response = await cofheFetch(
3344
+ `${thresholdNetworkUrl}/v2/decrypt/${requestId}`,
3345
+ /*op:decrypt-poll*/
3346
+ {
3347
+ method: "GET",
3348
+ headers: {
3349
+ "Content-Type": "application/json"
3350
+ }
3036
3351
  }
3037
- });
3352
+ );
3038
3353
  } catch (e) {
3039
3354
  throw new CofheError({
3040
3355
  code: "DECRYPT_FAILED" /* DecryptFailed */,
@@ -3059,17 +3374,10 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId, overallStartT
3059
3374
  });
3060
3375
  }
3061
3376
  if (!response.ok) {
3062
- let errorMessage = `HTTP ${response.status}`;
3063
- try {
3064
- const errorBody = await response.json();
3065
- const maybeMessage = errorBody.error_message || errorBody.message;
3066
- if (typeof maybeMessage === "string" && maybeMessage.length > 0)
3067
- errorMessage = maybeMessage;
3068
- } catch {
3069
- errorMessage = response.statusText || errorMessage;
3070
- }
3377
+ const { apiErrorCode, errorMessage } = await parseApiErrorResponseBody(response);
3071
3378
  throw new CofheError({
3072
- code: "DECRYPT_FAILED" /* DecryptFailed */,
3379
+ code: mapApiErrorCodeToCofheErrorCode(apiErrorCode, "DECRYPT_FAILED" /* DecryptFailed */),
3380
+ apiErrorCode,
3073
3381
  message: `decrypt status poll failed: ${errorMessage}`,
3074
3382
  context: {
3075
3383
  thresholdNetworkUrl,
@@ -3114,7 +3422,7 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId, overallStartT
3114
3422
  });
3115
3423
  }
3116
3424
  async function tnDecryptV2(params) {
3117
- const { thresholdNetworkUrl, ctHash, chainId, permission, retry404TimeoutMs, onPoll } = params;
3425
+ const { thresholdNetworkUrl, ctHash, chainId, acp, retry404TimeoutMs, onPoll } = params;
3118
3426
  const normalized404RetryTimeoutMs = normalize404RetryTimeoutMs({
3119
3427
  timeoutMs: retry404TimeoutMs,
3120
3428
  operationLabel: "decrypt",
@@ -3125,7 +3433,7 @@ async function tnDecryptV2(params) {
3125
3433
  thresholdNetworkUrl,
3126
3434
  ctHash,
3127
3435
  chainId,
3128
- permission,
3436
+ acp,
3129
3437
  overallStartTime,
3130
3438
  normalized404RetryTimeoutMs,
3131
3439
  onPoll
@@ -3140,9 +3448,9 @@ async function tnDecryptV2(params) {
3140
3448
  var DEFAULT_404_RETRY_TIMEOUT_MS3 = 1e4;
3141
3449
  var DecryptForTxBuilder = class extends BaseBuilder {
3142
3450
  ctHash;
3143
- permitHash;
3144
- permit;
3145
- permitSelection = "unset";
3451
+ acpHash;
3452
+ acp;
3453
+ acpSelection = "unset";
3146
3454
  pollCallback;
3147
3455
  retry404TimeoutMs = DEFAULT_404_RETRY_TIMEOUT_MS3;
3148
3456
  constructor(params) {
@@ -3187,137 +3495,137 @@ var DecryptForTxBuilder = class extends BaseBuilder {
3187
3495
  this.retry404TimeoutMs = timeoutMs;
3188
3496
  return this;
3189
3497
  }
3190
- withPermit(permitOrPermitHash) {
3191
- if (this.permitSelection === "with-permit") {
3498
+ withACP(acpOrACPHash) {
3499
+ if (this.acpSelection === "with-acp") {
3192
3500
  throw new CofheError({
3193
3501
  code: "INTERNAL_ERROR" /* InternalError */,
3194
- message: "decryptForTx: withPermit() can only be selected once.",
3195
- hint: "Choose the permit mode once. If you need a different permit, start a new decryptForTx() builder chain."
3502
+ message: "decryptForTx: withACP() can only be selected once.",
3503
+ hint: "Choose the acp mode once. If you need a different acp, start a new decryptForTx() builder chain."
3196
3504
  });
3197
3505
  }
3198
- if (this.permitSelection === "without-permit") {
3506
+ if (this.acpSelection === "without-acp") {
3199
3507
  throw new CofheError({
3200
3508
  code: "INTERNAL_ERROR" /* InternalError */,
3201
- message: "decryptForTx: cannot call withPermit() after withoutPermit() has been selected.",
3202
- hint: "Choose exactly one permit mode: either call .withPermit(...) or .withoutPermit(), but not both."
3509
+ message: "decryptForTx: cannot call withACP() after withoutACP() has been selected.",
3510
+ hint: "Choose exactly one acp mode: either call .withACP(...) or .withoutACP(), but not both."
3203
3511
  });
3204
3512
  }
3205
- this.permitSelection = "with-permit";
3206
- if (typeof permitOrPermitHash === "string") {
3207
- this.permitHash = permitOrPermitHash;
3208
- this.permit = void 0;
3209
- } else if (permitOrPermitHash === void 0) {
3210
- this.permitHash = void 0;
3211
- this.permit = void 0;
3513
+ this.acpSelection = "with-acp";
3514
+ if (typeof acpOrACPHash === "string") {
3515
+ this.acpHash = acpOrACPHash;
3516
+ this.acp = void 0;
3517
+ } else if (acpOrACPHash === void 0) {
3518
+ this.acpHash = void 0;
3519
+ this.acp = void 0;
3212
3520
  } else {
3213
- this.permit = permitOrPermitHash;
3214
- this.permitHash = void 0;
3521
+ this.acp = acpOrACPHash;
3522
+ this.acpHash = void 0;
3215
3523
  }
3216
3524
  return this;
3217
3525
  }
3218
3526
  /**
3219
- * Select "no permit" mode.
3527
+ * Select "no acp" mode.
3220
3528
  *
3221
- * This uses global allowance (no permit required) and sends an empty permission payload to `/decrypt`.
3529
+ * This uses global allowance (no acp required) and sends an empty permission payload to `/decrypt`.
3222
3530
  */
3223
- withoutPermit() {
3224
- if (this.permitSelection === "without-permit") {
3531
+ withoutACP() {
3532
+ if (this.acpSelection === "without-acp") {
3225
3533
  throw new CofheError({
3226
3534
  code: "INTERNAL_ERROR" /* InternalError */,
3227
- message: "decryptForTx: withoutPermit() can only be selected once.",
3228
- hint: "Choose the permit mode once. If you need a different mode, start a new decryptForTx() builder chain."
3535
+ message: "decryptForTx: withoutACP() can only be selected once.",
3536
+ hint: "Choose the acp mode once. If you need a different mode, start a new decryptForTx() builder chain."
3229
3537
  });
3230
3538
  }
3231
- if (this.permitSelection === "with-permit") {
3539
+ if (this.acpSelection === "with-acp") {
3232
3540
  throw new CofheError({
3233
3541
  code: "INTERNAL_ERROR" /* InternalError */,
3234
- message: "decryptForTx: cannot call withoutPermit() after withPermit() has been selected.",
3235
- hint: "Choose exactly one permit mode: either call .withPermit(...) or .withoutPermit(), but not both."
3542
+ message: "decryptForTx: cannot call withoutACP() after withACP() has been selected.",
3543
+ hint: "Choose exactly one acp mode: either call .withACP(...) or .withoutACP(), but not both."
3236
3544
  });
3237
3545
  }
3238
- this.permitSelection = "without-permit";
3239
- this.permitHash = void 0;
3240
- this.permit = void 0;
3546
+ this.acpSelection = "without-acp";
3547
+ this.acpHash = void 0;
3548
+ this.acp = void 0;
3241
3549
  return this;
3242
3550
  }
3243
- getPermit() {
3244
- return this.permit;
3551
+ getACP() {
3552
+ return this.acp;
3245
3553
  }
3246
- getPermitHash() {
3247
- return this.permitHash;
3554
+ getACPHash() {
3555
+ return this.acpHash;
3248
3556
  }
3249
3557
  async getThresholdNetworkUrl() {
3250
3558
  this.assertChainId();
3251
3559
  return getThresholdNetworkUrlOrThrow(this.config, this.chainId);
3252
3560
  }
3253
- async getResolvedPermit() {
3254
- if (this.permitSelection === "unset") {
3561
+ async getResolvedACP() {
3562
+ if (this.acpSelection === "unset") {
3255
3563
  throw new CofheError({
3256
3564
  code: "INTERNAL_ERROR" /* InternalError */,
3257
- message: "decryptForTx: missing permit selection; call withPermit(...) or withoutPermit() before execute().",
3258
- hint: "Call .withPermit() to use the active permit, or .withoutPermit() for global allowance."
3565
+ message: "decryptForTx: missing acp selection; call withACP(...) or withoutACP() before execute().",
3566
+ hint: "Call .withACP() to use the active acp, or .withoutACP() for global allowance."
3259
3567
  });
3260
3568
  }
3261
- if (this.permitSelection === "without-permit") {
3569
+ if (this.acpSelection === "without-acp") {
3262
3570
  return null;
3263
3571
  }
3264
- if (this.permit)
3265
- return this.permit;
3572
+ if (this.acp)
3573
+ return this.acp;
3266
3574
  this.assertChainId();
3267
3575
  this.assertAccount();
3268
- if (this.permitHash) {
3269
- const permit2 = await permits.getPermit(this.chainId, this.account, this.permitHash);
3270
- if (!permit2) {
3576
+ if (this.acpHash) {
3577
+ const acp2 = await acps.getACP(this.chainId, this.account, this.acpHash);
3578
+ if (!acp2) {
3271
3579
  throw new CofheError({
3272
- code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
3273
- message: `Permit with hash <${this.permitHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
3274
- hint: "Ensure the permit exists and is valid.",
3580
+ code: "ACP_NOT_FOUND" /* ACPNotFound */,
3581
+ message: `ACP with hash <${this.acpHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
3582
+ hint: "Ensure the acp exists and is valid.",
3275
3583
  context: {
3276
3584
  chainId: this.chainId,
3277
3585
  account: this.account,
3278
- permitHash: this.permitHash
3586
+ acpHash: this.acpHash
3279
3587
  }
3280
3588
  });
3281
3589
  }
3282
- return permit2;
3590
+ return acp2;
3283
3591
  }
3284
- const permit = await permits.getActivePermit(this.chainId, this.account);
3285
- if (!permit) {
3592
+ const acp = await acps.getActiveACP(this.chainId, this.account);
3593
+ if (!acp) {
3286
3594
  throw new CofheError({
3287
- code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
3288
- message: `Active permit not found for chainId <${this.chainId}> and account <${this.account}>`,
3289
- hint: "Create a permit (e.g. client.permits.createSelf(...)) and/or set it active (client.permits.selectActivePermit(hash)).",
3595
+ code: "ACP_NOT_FOUND" /* ACPNotFound */,
3596
+ message: `Active acp not found for chainId <${this.chainId}> and account <${this.account}>`,
3597
+ hint: "Create an ACP (e.g. client.acp.createSelf(...)) and/or set it active (client.acp.selectActiveACP(hash)).",
3290
3598
  context: {
3291
3599
  chainId: this.chainId,
3292
3600
  account: this.account
3293
3601
  }
3294
3602
  });
3295
3603
  }
3296
- return permit;
3604
+ return acp;
3297
3605
  }
3298
3606
  /**
3299
3607
  * On hardhat, interact with MockThresholdNetwork contract
3300
3608
  */
3301
- async mocksDecryptForTx(permit) {
3609
+ async mocksDecryptForTx(acp) {
3302
3610
  this.assertPublicClient();
3303
3611
  const delay = this.config.mocks.decryptDelay;
3304
3612
  if (delay > 0)
3305
3613
  await sleep(delay);
3306
- const result = await cofheMocksDecryptForTx(this.ctHash, 0, permit, this.publicClient);
3614
+ const result = await cofheMocksDecryptForTx(this.ctHash, 0, acp, this.publicClient);
3307
3615
  return result;
3308
3616
  }
3309
3617
  /**
3310
3618
  * In the production context, perform a true decryption with the CoFHE coprocessor.
3311
3619
  */
3312
- async productionDecryptForTx(permit) {
3620
+ async productionDecryptForTx(acp) {
3313
3621
  this.assertChainId();
3314
3622
  this.assertPublicClient();
3315
3623
  const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
3316
- const permission = permit ? PermitUtils.getPermission(permit, true) : null;
3624
+ const wireAcp = acp ? ACPUtils.getPublic(acp, true) : null;
3317
3625
  const { decryptedValue, signature } = await tnDecryptV2({
3318
3626
  ctHash: this.ctHash,
3319
3627
  chainId: this.chainId,
3320
- permission,
3628
+ acp: wireAcp,
3321
3629
  thresholdNetworkUrl,
3322
3630
  retry404TimeoutMs: this.retry404TimeoutMs,
3323
3631
  onPoll: this.pollCallback
@@ -3331,19 +3639,19 @@ var DecryptForTxBuilder = class extends BaseBuilder {
3331
3639
  /**
3332
3640
  * Final step of the decryptForTx process. MUST BE CALLED LAST IN THE CHAIN.
3333
3641
  *
3334
- * You must explicitly choose one permit mode before calling `execute()`:
3335
- * - `withPermit(permit)` / `withPermit(permitHash)` / `withPermit()` (active permit)
3336
- * - `withoutPermit()` (global allowance)
3642
+ * You must explicitly choose one acp mode before calling `execute()`:
3643
+ * - `withACP(acp)` / `withACP(acpHash)` / `withACP()` (active acp)
3644
+ * - `withoutACP()` (global allowance)
3337
3645
  */
3338
3646
  async execute() {
3339
- const permit = await this.getResolvedPermit();
3340
- if (permit !== null) {
3341
- PermitUtils.validate(permit);
3342
- const chainId = permit._signedDomain.chainId;
3647
+ const acp = await this.getResolvedACP();
3648
+ if (acp !== null) {
3649
+ ACPUtils.validate(acp);
3650
+ const chainId = acp._signedDomain.chainId;
3343
3651
  if (chainId === hardhat$1.id) {
3344
- return await this.mocksDecryptForTx(permit);
3652
+ return await this.mocksDecryptForTx(acp);
3345
3653
  } else {
3346
- return await this.productionDecryptForTx(permit);
3654
+ return await this.productionDecryptForTx(acp);
3347
3655
  }
3348
3656
  } else {
3349
3657
  if (!this.chainId) {
@@ -3406,6 +3714,21 @@ function createCofheClientBase(opts) {
3406
3714
  const updateConnectState = (partial) => {
3407
3715
  connectStore.setState((state) => ({ ...state, ...partial }));
3408
3716
  };
3717
+ const _resolveSharingRegistry = async (publicClient, chainId) => {
3718
+ const configured = opts.config.acp?.sharingRegistry?.[chainId];
3719
+ if (configured != null)
3720
+ return configured;
3721
+ const registry = (await acps.getAclServedAddresses(publicClient, chainId)).shareRegistry;
3722
+ if (registry == null) {
3723
+ throw new CofheError({
3724
+ code: "MISSING_CONFIG" /* MissingConfig */,
3725
+ message: `No ACP share registry available for chainId <${chainId}>`,
3726
+ hint: "The ACL on this chain does not serve a share registry address. Set `acp.sharingRegistry` in the cofhe config to use on-chain sharing.",
3727
+ context: { chainId }
3728
+ });
3729
+ }
3730
+ return registry;
3731
+ };
3409
3732
  const _requireConnected = () => {
3410
3733
  const state = connectStore.getState();
3411
3734
  const notConnected = !state.connected || !state.account || !state.chainId || !state.publicClient || !state.walletClient;
@@ -3528,74 +3851,147 @@ function createCofheClientBase(opts) {
3528
3851
  }
3529
3852
  return { chainId: _chainId, account: _account };
3530
3853
  };
3531
- const clientPermits = {
3854
+ const clientACPs = {
3532
3855
  // Pass through store access
3533
- getSnapshot: permits.getSnapshot,
3534
- subscribe: permits.subscribe,
3856
+ getSnapshot: acps.getSnapshot,
3857
+ subscribe: acps.subscribe,
3535
3858
  // Creation methods (require connection)
3536
3859
  createSelf: async (options, clients) => {
3537
3860
  _requireConnected();
3538
3861
  const { publicClient, walletClient } = clients ?? connectStore.getState();
3539
- return permits.createSelf(options, publicClient, walletClient);
3862
+ const chainId = await publicClient.getChainId();
3863
+ return acps.createSelf(
3864
+ await acps.applyACPDefaultsFromChain(options, opts.config.acp, publicClient, chainId),
3865
+ publicClient,
3866
+ walletClient
3867
+ );
3540
3868
  },
3541
3869
  createSharing: async (options, clients) => {
3542
3870
  _requireConnected();
3543
3871
  const { publicClient, walletClient } = clients ?? connectStore.getState();
3544
- return permits.createSharing(options, publicClient, walletClient);
3872
+ const chainId = await publicClient.getChainId();
3873
+ return acps.createSharing(
3874
+ await acps.applyACPDefaultsFromChain(options, opts.config.acp, publicClient, chainId),
3875
+ publicClient,
3876
+ walletClient
3877
+ );
3545
3878
  },
3546
3879
  importShared: async (options, clients) => {
3547
3880
  _requireConnected();
3548
3881
  const { publicClient, walletClient } = clients ?? connectStore.getState();
3549
- return permits.importShared(options, publicClient, walletClient);
3882
+ return acps.importShared(options, publicClient, walletClient);
3550
3883
  },
3551
3884
  // Get or create methods (require connection)
3552
- getOrCreateSelfPermit: async (chainId, account, options) => {
3885
+ getOrCreateSelfACP: async (chainId, account, options) => {
3553
3886
  _requireConnected();
3554
3887
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3555
3888
  const { publicClient, walletClient } = connectStore.getState();
3556
- return permits.getOrCreateSelfPermit(publicClient, walletClient, _chainId, _account, options);
3889
+ const optionsWithDefaults = await acps.applyACPDefaultsFromChain(
3890
+ options ?? { issuer: _account, name: "Autogenerated Self ACP" },
3891
+ opts.config.acp,
3892
+ publicClient,
3893
+ _chainId
3894
+ );
3895
+ return acps.getOrCreateSelfACP(publicClient, walletClient, _chainId, _account, optionsWithDefaults);
3557
3896
  },
3558
- getOrCreateSharingPermit: async (options, chainId, account) => {
3897
+ getOrCreateSharingACP: async (options, chainId, account) => {
3559
3898
  _requireConnected();
3560
3899
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3561
3900
  const { publicClient, walletClient } = connectStore.getState();
3562
- return permits.getOrCreateSharingPermit(publicClient, walletClient, options, _chainId, _account);
3901
+ return acps.getOrCreateSharingACP(
3902
+ publicClient,
3903
+ walletClient,
3904
+ await acps.applyACPDefaultsFromChain(options, opts.config.acp, publicClient, _chainId),
3905
+ _chainId,
3906
+ _account
3907
+ );
3908
+ },
3909
+ // Revocation (require connection)
3910
+ revokeACP: async (acp) => {
3911
+ _requireConnected();
3912
+ const { walletClient } = connectStore.getState();
3913
+ return acps.revokeACP(acp, walletClient);
3914
+ },
3915
+ revokeAllACPs: async (revokerContract) => {
3916
+ _requireConnected();
3917
+ const { publicClient, walletClient } = connectStore.getState();
3918
+ return acps.revokeAllACPs(walletClient, publicClient, revokerContract);
3919
+ },
3920
+ isACPRevoked: async (acp) => {
3921
+ _requireConnected();
3922
+ const { publicClient } = connectStore.getState();
3923
+ return acps.isACPRevoked(acp, publicClient);
3924
+ },
3925
+ // On-chain sharing (require connection + config.acp.sharingRegistry)
3926
+ shareOnChain: async (acp) => {
3927
+ _requireConnected();
3928
+ const { publicClient, walletClient } = connectStore.getState();
3929
+ const chainId = await publicClient.getChainId();
3930
+ const sharingRegistry = await _resolveSharingRegistry(publicClient, chainId);
3931
+ return acps.shareOnChain(acp, walletClient, sharingRegistry);
3932
+ },
3933
+ getIncomingShares: async () => {
3934
+ _requireConnected();
3935
+ const { publicClient, walletClient } = connectStore.getState();
3936
+ const chainId = await publicClient.getChainId();
3937
+ const account = walletClient.account.address;
3938
+ const sharingRegistry = await _resolveSharingRegistry(publicClient, chainId);
3939
+ return acps.getIncomingShares(publicClient, sharingRegistry, account);
3940
+ },
3941
+ importFromChain: async (share) => {
3942
+ _requireConnected();
3943
+ const { publicClient, walletClient } = connectStore.getState();
3944
+ return acps.importFromChain(share, publicClient, walletClient);
3945
+ },
3946
+ dismissShare: async (shareId) => {
3947
+ _requireConnected();
3948
+ const { publicClient, walletClient } = connectStore.getState();
3949
+ const chainId = await publicClient.getChainId();
3950
+ const sharingRegistry = await _resolveSharingRegistry(publicClient, chainId);
3951
+ return acps.removeShareOnChain(shareId, walletClient, sharingRegistry);
3952
+ },
3953
+ cancelShare: async (shareId) => {
3954
+ _requireConnected();
3955
+ const { publicClient, walletClient } = connectStore.getState();
3956
+ const chainId = await publicClient.getChainId();
3957
+ const sharingRegistry = await _resolveSharingRegistry(publicClient, chainId);
3958
+ return acps.removeShareOnChain(shareId, walletClient, sharingRegistry);
3563
3959
  },
3564
3960
  // Retrieval methods (auto-fill chainId/account)
3565
- getPermit: (hash, chainId, account) => {
3961
+ getACP: (hash, chainId, account) => {
3566
3962
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3567
- return permits.getPermit(_chainId, _account, hash);
3963
+ return acps.getACP(_chainId, _account, hash);
3568
3964
  },
3569
- getPermits: (chainId, account) => {
3965
+ getACPs: (chainId, account) => {
3570
3966
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3571
- return permits.getPermits(_chainId, _account);
3967
+ return acps.getACPs(_chainId, _account);
3572
3968
  },
3573
- getActivePermit: (chainId, account) => {
3969
+ getActiveACP: (chainId, account) => {
3574
3970
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3575
- return permits.getActivePermit(_chainId, _account);
3971
+ return acps.getActiveACP(_chainId, _account);
3576
3972
  },
3577
- getActivePermitHash: (chainId, account) => {
3973
+ getActiveACPHash: (chainId, account) => {
3578
3974
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3579
- return permits.getActivePermitHash(_chainId, _account);
3975
+ return acps.getActiveACPHash(_chainId, _account);
3580
3976
  },
3581
3977
  // Mutation methods (auto-fill chainId/account)
3582
- selectActivePermit: (hash, chainId, account) => {
3978
+ selectActiveACP: (hash, chainId, account) => {
3583
3979
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3584
- return permits.selectActivePermit(_chainId, _account, hash);
3980
+ return acps.selectActiveACP(_chainId, _account, hash);
3585
3981
  },
3586
- removePermit: async (hash, chainId, account) => {
3982
+ removeACP: async (hash, chainId, account) => {
3587
3983
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3588
- return permits.removePermit(_chainId, _account, hash);
3984
+ return acps.removeACP(_chainId, _account, hash);
3589
3985
  },
3590
- removeActivePermit: async (chainId, account) => {
3986
+ removeActiveACP: async (chainId, account) => {
3591
3987
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3592
- return permits.removeActivePermit(_chainId, _account);
3988
+ return acps.removeActiveACP(_chainId, _account);
3593
3989
  },
3594
3990
  // Utils (no context needed)
3595
- getHash: permits.getHash,
3596
- export: permits.export,
3597
- serialize: permits.serialize,
3598
- deserialize: permits.deserialize
3991
+ getHash: acps.getHash,
3992
+ export: acps.export,
3993
+ serialize: acps.serialize,
3994
+ deserialize: acps.deserialize
3599
3995
  };
3600
3996
  return {
3601
3997
  // Zustand reactive accessors (don't export store directly to prevent mutation)
@@ -3623,7 +4019,7 @@ function createCofheClientBase(opts) {
3623
4019
  decryptHandle: decryptForView,
3624
4020
  decryptForTx,
3625
4021
  verifyDecryptResult: verifyDecryptResult2,
3626
- permits: clientPermits
4022
+ acp: clientACPs
3627
4023
  // Add SDK-specific methods below that require connection
3628
4024
  // Example:
3629
4025
  // async encryptData(data: unknown) {
@@ -3633,4 +4029,4 @@ function createCofheClientBase(opts) {
3633
4029
  };
3634
4030
  }
3635
4031
 
3636
- export { CofheError, CofheErrorCode, DecryptForTxBuilder, DecryptForViewBuilder, EncryptInputsBuilder, EncryptStep, Encryptable, FheAllUTypes, FheTypes, FheUintUTypes, InitialConnectStore, assertCorrectEncryptedItemInput, createCofheClientBase, createCofheConfigBase, createKeysStore, fetchKeys, fheTypeToString, getCofheConfigItem, isCofheError, isEncryptableItem, isLastEncryptionStep, verifyDecryptResult, zkProveWithWorker };
4032
+ export { CofheError, CofheErrorCode, DecryptForTxBuilder, DecryptForViewBuilder, EncryptInputsBuilder, EncryptStep, Encryptable, FheAllUTypes, FheTypes, FheUintUTypes, InitialConnectStore, assertNoRenamedConfigKeys, cofheFetch, createCofheClientBase, createCofheConfigBase, createKeysStore, fetchKeys, fheTypeToString, getCofheConfigItem, getCofheDebugInterceptors, isCofheError, isEncryptableItem, isLastEncryptionStep, setCofheDebugInterceptors, verifyDecryptResult, zkProveWithWorker };