@cofhe/sdk 0.6.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/CHANGELOG.md +45 -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/decrypt/MockThresholdNetworkAbi.ts +20 -11
  27. package/core/decrypt/apiError.ts +104 -0
  28. package/core/decrypt/cofheMocksDecryptForTx.ts +11 -11
  29. package/core/decrypt/cofheMocksDecryptForView.ts +7 -7
  30. package/core/decrypt/decryptForTxBuilder.ts +102 -102
  31. package/core/decrypt/decryptForViewBuilder.ts +90 -90
  32. package/core/decrypt/submitRetry.ts +38 -30
  33. package/core/decrypt/tnDecryptV1.ts +5 -5
  34. package/core/decrypt/tnDecryptV2.ts +25 -21
  35. package/core/decrypt/tnSealOutputV1.ts +4 -3
  36. package/core/decrypt/tnSealOutputV2.ts +24 -18
  37. package/core/encrypt/cofheMocksZkVerifySign.ts +59 -74
  38. package/core/encrypt/encryptInputsBuilder.ts +86 -52
  39. package/core/encrypt/zkPackProveVerify.ts +25 -18
  40. package/core/error.ts +34 -6
  41. package/core/index.ts +4 -14
  42. package/core/test/acpDefaults.test.ts +52 -0
  43. package/core/test/acps.test.ts +596 -0
  44. package/core/test/apiError.test.ts +130 -0
  45. package/core/test/client.test.ts +22 -19
  46. package/core/test/config.test.ts +25 -5
  47. package/core/test/decrypt.test.ts +40 -35
  48. package/core/test/decryptBuilders.test.ts +68 -68
  49. package/core/test/decryptErrorCodes.test.ts +217 -0
  50. package/core/test/encryptInputsBuilder.test.ts +72 -41
  51. package/core/test/pollCallbacks.test.ts +89 -18
  52. package/core/test/stagingRedirect.ts +18 -0
  53. package/core/test/submitRetry.test.ts +182 -0
  54. package/core/types.ts +9 -69
  55. package/dist/acp-Wi6isVQI.d.cts +407 -0
  56. package/dist/acp-Wi6isVQI.d.ts +407 -0
  57. package/dist/acps.cjs +1081 -0
  58. package/dist/acps.d.cts +480 -0
  59. package/dist/acps.d.ts +480 -0
  60. package/dist/acps.js +2 -0
  61. package/dist/chains.cjs +14 -1
  62. package/dist/chains.d.cts +30 -1
  63. package/dist/chains.d.ts +30 -1
  64. package/dist/chains.js +1 -1
  65. package/dist/{chunk-NOC3PYB7.js → chunk-43USWPEH.js} +930 -580
  66. package/dist/{chunk-MTRAXQXC.js → chunk-N6IDQRRU.js} +14 -2
  67. package/dist/chunk-Q7CBWGQX.js +1029 -0
  68. package/dist/{clientTypes-CyUvRRzA.d.ts → clientTypes-BN3nbzYM.d.ts} +342 -165
  69. package/dist/{clientTypes-BDy1qIBu.d.cts → clientTypes-CYZjFznO.d.cts} +342 -165
  70. package/dist/core.cjs +1358 -1002
  71. package/dist/core.d.cts +31 -9
  72. package/dist/core.d.ts +31 -9
  73. package/dist/core.js +3 -3
  74. package/dist/node.cjs +1293 -952
  75. package/dist/node.d.cts +2 -2
  76. package/dist/node.d.ts +2 -2
  77. package/dist/node.js +3 -3
  78. package/dist/web.cjs +1293 -952
  79. package/dist/web.d.cts +2 -2
  80. package/dist/web.d.ts +2 -2
  81. package/dist/web.js +3 -3
  82. package/node/test/inherited.test.ts +75 -65
  83. package/node/test/tfheinit.test.ts +23 -8
  84. package/package.json +6 -6
  85. package/web/test/client.web.test.ts +5 -1
  86. package/web/test/inherited.web.test.ts +75 -65
  87. package/web/test/tfheinit.web.test.ts +14 -5
  88. package/web/test/worker.config.web.test.ts +38 -23
  89. package/web/test/worker.output.web.test.ts +25 -24
  90. package/core/encrypt/encryptUtils.ts +0 -67
  91. package/core/permits.ts +0 -216
  92. package/core/test/permits.test.ts +0 -596
  93. package/dist/chunk-VB62WYPL.js +0 -978
  94. package/dist/permit-DnVMDT5h.d.cts +0 -376
  95. package/dist/permit-DnVMDT5h.d.ts +0 -376
  96. package/dist/permits.cjs +0 -1026
  97. package/dist/permits.d.cts +0 -353
  98. package/dist/permits.d.ts +0 -353
  99. package/dist/permits.js +0 -2
  100. package/permits/index.ts +0 -68
  101. package/permits/permit.ts +0 -385
  102. package/permits/sealing.ts +0 -131
  103. package/permits/signature.ts +0 -79
  104. package/permits/store.ts +0 -157
  105. package/permits/test/localstorage.test.ts +0 -113
  106. package/permits/test/permit.test.ts +0 -557
  107. package/permits/test/sealing.test.ts +0 -84
  108. package/permits/test/store.test.ts +0 -88
  109. package/permits/test/validation.test.ts +0 -361
  110. package/permits/test-utils.ts +0 -28
  111. package/permits/types.ts +0 -204
  112. package/permits/validation.ts +0 -327
  113. /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) => {
1664
+ const chainId = await publicClient.getChainId();
1665
+ const account = walletClient.account.address;
1666
+ acpStore.setACP(chainId, account, acp);
1667
+ };
1668
+ var storeActiveACP = async (acp, publicClient, walletClient) => {
1669
+ await storeACP(acp, publicClient, walletClient);
1683
1670
  const chainId = await publicClient.getChainId();
1684
1671
  const account = walletClient.account.address;
1685
- permitStore.setPermit(chainId, account, permit);
1686
- permitStore.setActivePermitHash(chainId, account, permit.hash);
1672
+ acpStore.setActiveACPHash(chainId, account, acp.hash);
1687
1673
  };
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;
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" && PermitUtils.isValid(activePermit).valid) {
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" && PermitUtils.isValid(activePermit).valid) {
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,7 +2207,7 @@ 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
  }
@@ -2036,11 +2250,61 @@ function computeMinuteRampPollIntervalMs(elapsedMs, params) {
2036
2250
  return Math.min(params.maxIntervalMs, Math.max(params.minIntervalMs, intervalMs));
2037
2251
  }
2038
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
+
2039
2306
  // core/decrypt/submitRetry.ts
2040
2307
  var DEFAULT_404_RETRY_TIMEOUT_MS = 1e4;
2041
- function isRetryableSubmitStatus(status) {
2042
- return status === 204 || status === 404;
2043
- }
2044
2308
  function normalize404RetryTimeoutMs(params) {
2045
2309
  const { timeoutMs, operationLabel, errorCode } = params;
2046
2310
  if (timeoutMs === void 0)
@@ -2057,32 +2321,24 @@ function normalize404RetryTimeoutMs(params) {
2057
2321
  return timeoutMs;
2058
2322
  }
2059
2323
  async function classifySubmitResponse(params) {
2060
- const { response, extractErrorMessage } = params;
2061
- if (isRetryableSubmitStatus(response.status)) {
2062
- return { kind: "retryable", status: response.status };
2324
+ const { response, fallbackErrorCode } = params;
2325
+ if (response.status === 204) {
2326
+ return { kind: "retryable", status: 204 };
2063
2327
  }
2064
2328
  if (response.ok) {
2065
2329
  return { kind: "parse-json" };
2066
2330
  }
2067
- let errorMessage = `HTTP ${response.status}`;
2068
- try {
2069
- const errorBody = await response.json();
2070
- const maybeErrorMessage = extractErrorMessage?.(errorBody);
2071
- if (typeof maybeErrorMessage === "string" && maybeErrorMessage.length > 0) {
2072
- errorMessage = maybeErrorMessage;
2073
- } else if (errorBody && typeof errorBody === "object") {
2074
- const defaultMessage = errorBody.error_message;
2075
- const fallbackMessage = errorBody.message;
2076
- if (typeof defaultMessage === "string" && defaultMessage.length > 0) {
2077
- errorMessage = defaultMessage;
2078
- } else if (typeof fallbackMessage === "string" && fallbackMessage.length > 0) {
2079
- errorMessage = fallbackMessage;
2080
- }
2081
- }
2082
- } catch {
2083
- errorMessage = response.statusText || errorMessage;
2331
+ const { apiErrorCode, errorMessage } = await parseApiErrorResponseBody(response);
2332
+ if (response.status === 404) {
2333
+ return { kind: "retryable", status: 404, apiErrorMessage: errorMessage };
2084
2334
  }
2085
- 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
+ };
2086
2342
  }
2087
2343
  function throwIfSubmitRetryTimedOut(params) {
2088
2344
  const {
@@ -2094,12 +2350,14 @@ function throwIfSubmitRetryTimedOut(params) {
2094
2350
  overallTimeoutMs,
2095
2351
  thresholdNetworkUrl,
2096
2352
  body,
2097
- attemptIndex
2353
+ attemptIndex,
2354
+ lastKnownErrorMessage
2098
2355
  } = params;
2099
2356
  if (status === 404 && elapsedMs > retry404TimeoutMs) {
2100
2357
  throw new CofheError({
2101
- code: errorCode,
2102
- 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}` : ""),
2103
2361
  hint: "The ciphertext may not be indexed yet. Increase set404RetryTimeout(...) if the backend is slow to index ciphertexts.",
2104
2362
  context: {
2105
2363
  thresholdNetworkUrl,
@@ -2125,6 +2383,62 @@ function throwIfSubmitRetryTimedOut(params) {
2125
2383
  });
2126
2384
  }
2127
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
+ }
2128
2442
 
2129
2443
  // core/decrypt/tnSealOutputV2.ts
2130
2444
  var POLL_INTERVAL_MS = 1e3;
@@ -2187,13 +2501,14 @@ function parseCompletedSealOutputResponse(params) {
2187
2501
  }
2188
2502
  return convertSealedData(sealed);
2189
2503
  }
2190
- async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission, overallStartTime, retry404TimeoutMs, onPoll) {
2504
+ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, acp, overallStartTime, retry404TimeoutMs, onPoll) {
2191
2505
  const body = {
2192
2506
  ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
2193
2507
  host_chain_id: chainId,
2194
- permit: permission
2508
+ acp
2195
2509
  };
2196
2510
  let attemptIndex = 0;
2511
+ let last404ApiErrorMessage;
2197
2512
  for (; ; ) {
2198
2513
  let response;
2199
2514
  try {
@@ -2221,16 +2536,19 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
2221
2536
  }
2222
2537
  });
2223
2538
  }
2224
- const responseClassification = await classifySubmitResponse({ response });
2539
+ const responseClassification = await classifySubmitResponse({
2540
+ response,
2541
+ fallbackErrorCode: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */
2542
+ });
2225
2543
  if (responseClassification.kind === "fatal-http") {
2226
2544
  throw new CofheError({
2227
- code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2545
+ code: responseClassification.cofheErrorCode,
2546
+ apiErrorCode: responseClassification.apiErrorCode,
2228
2547
  message: `sealOutput request failed: ${responseClassification.errorMessage}`,
2229
2548
  hint: "Check the threshold network URL and request parameters.",
2230
2549
  context: {
2231
2550
  thresholdNetworkUrl,
2232
- status: response.status,
2233
- statusText: response.statusText,
2551
+ status: responseClassification.status,
2234
2552
  body,
2235
2553
  attemptIndex
2236
2554
  }
@@ -2276,6 +2594,9 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
2276
2594
  }
2277
2595
  });
2278
2596
  }
2597
+ if (responseClassification.status === 404) {
2598
+ last404ApiErrorMessage = responseClassification.apiErrorMessage;
2599
+ }
2279
2600
  const elapsedMs = Date.now() - overallStartTime;
2280
2601
  throwIfSubmitRetryTimedOut({
2281
2602
  operationLabel: "sealOutput",
@@ -2286,7 +2607,8 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
2286
2607
  overallTimeoutMs: SEAL_OUTPUT_TIMEOUT_MS,
2287
2608
  thresholdNetworkUrl,
2288
2609
  body,
2289
- attemptIndex
2610
+ attemptIndex,
2611
+ lastKnownErrorMessage: last404ApiErrorMessage
2290
2612
  });
2291
2613
  onPoll?.({
2292
2614
  operation: "sealoutput",
@@ -2364,15 +2686,10 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId, overallStart
2364
2686
  });
2365
2687
  }
2366
2688
  if (!response.ok) {
2367
- let errorMessage = `HTTP ${response.status}`;
2368
- try {
2369
- const errorBody = await response.json();
2370
- errorMessage = errorBody.error_message || errorBody.message || errorMessage;
2371
- } catch {
2372
- errorMessage = response.statusText || errorMessage;
2373
- }
2689
+ const { apiErrorCode, errorMessage } = await parseApiErrorResponseBody(response);
2374
2690
  throw new CofheError({
2375
- code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
2691
+ code: mapApiErrorCodeToCofheErrorCode(apiErrorCode, "SEAL_OUTPUT_FAILED" /* SealOutputFailed */),
2692
+ apiErrorCode,
2376
2693
  message: `sealOutput status poll failed: ${errorMessage}`,
2377
2694
  context: {
2378
2695
  thresholdNetworkUrl,
@@ -2416,7 +2733,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId, overallStart
2416
2733
  });
2417
2734
  }
2418
2735
  async function tnSealOutputV2(params) {
2419
- const { thresholdNetworkUrl, ctHash, chainId, permission, retry404TimeoutMs, onPoll } = params;
2736
+ const { thresholdNetworkUrl, ctHash, chainId, acp, retry404TimeoutMs, onPoll } = params;
2420
2737
  const normalized404RetryTimeoutMs = normalize404RetryTimeoutMs({
2421
2738
  timeoutMs: retry404TimeoutMs,
2422
2739
  operationLabel: "sealOutput",
@@ -2427,7 +2744,7 @@ async function tnSealOutputV2(params) {
2427
2744
  thresholdNetworkUrl,
2428
2745
  ctHash,
2429
2746
  chainId,
2430
- permission,
2747
+ acp,
2431
2748
  overallStartTime,
2432
2749
  normalized404RetryTimeoutMs,
2433
2750
  onPoll
@@ -2443,8 +2760,8 @@ var DEFAULT_404_RETRY_TIMEOUT_MS2 = 1e4;
2443
2760
  var DecryptForViewBuilder = class extends BaseBuilder {
2444
2761
  ctHash;
2445
2762
  utype;
2446
- permitHash;
2447
- permit;
2763
+ acpHash;
2764
+ acp;
2448
2765
  pollCallback;
2449
2766
  retry404TimeoutMs = DEFAULT_404_RETRY_TIMEOUT_MS2;
2450
2767
  constructor(params) {
@@ -2458,11 +2775,11 @@ var DecryptForViewBuilder = class extends BaseBuilder {
2458
2775
  });
2459
2776
  this.ctHash = params.ctHash;
2460
2777
  this.utype = params.utype;
2461
- this.permitHash = params.permitHash;
2462
- this.permit = params.permit;
2778
+ this.acpHash = params.acpHash;
2779
+ this.acp = params.acp;
2463
2780
  }
2464
2781
  /**
2465
- * @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.
2466
2783
  *
2467
2784
  * If not provided, the chainId will be fetched from the connected publicClient.
2468
2785
  *
@@ -2483,7 +2800,7 @@ var DecryptForViewBuilder = class extends BaseBuilder {
2483
2800
  return this.chainId;
2484
2801
  }
2485
2802
  /**
2486
- * @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.
2487
2804
  *
2488
2805
  * If not provided, the account will be fetched from the connected walletClient.
2489
2806
  *
@@ -2520,61 +2837,61 @@ var DecryptForViewBuilder = class extends BaseBuilder {
2520
2837
  this.retry404TimeoutMs = timeoutMs;
2521
2838
  return this;
2522
2839
  }
2523
- withPermit(permitOrPermitHash) {
2524
- if (typeof permitOrPermitHash === "string") {
2525
- this.permitHash = permitOrPermitHash;
2526
- this.permit = void 0;
2527
- } else if (permitOrPermitHash === void 0) {
2528
- this.permitHash = void 0;
2529
- 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;
2530
2847
  } else {
2531
- this.permit = permitOrPermitHash;
2532
- this.permitHash = void 0;
2848
+ this.acp = acpOrACPHash;
2849
+ this.acpHash = void 0;
2533
2850
  }
2534
2851
  return this;
2535
2852
  }
2536
2853
  /**
2537
- * @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.
2538
2855
  *
2539
- * If not provided, the active permit for the chainId and account will be used.
2540
- * 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.
2541
2858
  *
2542
2859
  * Example:
2543
2860
  * ```typescript
2544
2861
  * const unsealed = await client.decryptForView(ctHash, utype)
2545
- * .setPermitHash('0x1234567890123456789012345678901234567890')
2862
+ * .setACPHash('0x1234567890123456789012345678901234567890')
2546
2863
  * .execute();
2547
2864
  * ```
2548
2865
  *
2549
2866
  * @returns The chainable DecryptForViewBuilder instance.
2550
2867
  */
2551
- /** @deprecated Use `withPermit(permitHash)` instead. */
2552
- setPermitHash(permitHash) {
2553
- return this.withPermit(permitHash);
2868
+ /** @deprecated Use `withACP(acpHash)` instead. */
2869
+ setACPHash(acpHash) {
2870
+ return this.withACP(acpHash);
2554
2871
  }
2555
- getPermitHash() {
2556
- return this.permitHash;
2872
+ getACPHash() {
2873
+ return this.acpHash;
2557
2874
  }
2558
2875
  /**
2559
- * @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.
2560
2877
  *
2561
- * 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.
2562
2879
  *
2563
2880
  * Example:
2564
2881
  * ```typescript
2565
2882
  * const unsealed = await client.decryptForView(ctHash, utype)
2566
- * .setPermit(permit)
2883
+ * .setACP(acp)
2567
2884
  * .execute();
2568
2885
  * ```
2569
2886
  *
2570
2887
  * @returns The chainable DecryptForViewBuilder instance.
2571
2888
  */
2572
- /** @deprecated Use `withPermit(permit)` instead. */
2573
- setPermit(permit) {
2574
- return this.withPermit(permit);
2889
+ /** @deprecated Use `withACP(acp)` instead. */
2890
+ setACP(acp) {
2891
+ return this.withACP(acp);
2575
2892
  }
2576
- getPermit() {
2577
- return this.permit;
2893
+ getACP() {
2894
+ return this.acp;
2578
2895
  }
2579
2896
  async getThresholdNetworkUrl() {
2580
2897
  this.assertChainId();
@@ -2590,77 +2907,77 @@ var DecryptForViewBuilder = class extends BaseBuilder {
2590
2907
  }
2591
2908
  });
2592
2909
  }
2593
- async getResolvedPermit() {
2594
- if (this.permit)
2595
- return this.permit;
2910
+ async getResolvedACP() {
2911
+ if (this.acp)
2912
+ return this.acp;
2596
2913
  this.assertChainId();
2597
2914
  this.assertAccount();
2598
- if (this.permitHash) {
2599
- const permit2 = await permits.getPermit(this.chainId, this.account, this.permitHash);
2600
- if (!permit2) {
2915
+ if (this.acpHash) {
2916
+ const acp2 = await acps.getACP(this.chainId, this.account, this.acpHash);
2917
+ if (!acp2) {
2601
2918
  throw new CofheError({
2602
- code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
2603
- message: `Permit with hash <${this.permitHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
2604
- 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.",
2605
2922
  context: {
2606
2923
  chainId: this.chainId,
2607
2924
  account: this.account,
2608
- permitHash: this.permitHash
2925
+ acpHash: this.acpHash
2609
2926
  }
2610
2927
  });
2611
2928
  }
2612
- return permit2;
2929
+ return acp2;
2613
2930
  }
2614
- const permit = await permits.getActivePermit(this.chainId, this.account);
2615
- if (!permit) {
2931
+ const acp = await acps.getActiveACP(this.chainId, this.account);
2932
+ if (!acp) {
2616
2933
  throw new CofheError({
2617
- code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
2618
- message: `Active permit not found for chainId <${this.chainId}> and account <${this.account}>`,
2619
- 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.",
2620
2937
  context: {
2621
2938
  chainId: this.chainId,
2622
2939
  account: this.account
2623
2940
  }
2624
2941
  });
2625
2942
  }
2626
- return permit;
2943
+ return acp;
2627
2944
  }
2628
2945
  /**
2629
2946
  * On hardhat, interact with MockZkVerifier contract instead of CoFHE
2630
2947
  */
2631
- async mocksSealOutput(permit) {
2948
+ async mocksSealOutput(acp) {
2632
2949
  this.assertPublicClient();
2633
2950
  const mocksDecryptDelay = this.config.mocks.decryptDelay;
2634
2951
  if (mocksDecryptDelay > 0)
2635
2952
  await sleep(mocksDecryptDelay);
2636
- return cofheMocksDecryptForView(this.ctHash, this.utype, permit, this.publicClient);
2953
+ return cofheMocksDecryptForView(this.ctHash, this.utype, acp, this.publicClient);
2637
2954
  }
2638
2955
  /**
2639
2956
  * In the production context, perform a true decryption with the CoFHE coprocessor.
2640
2957
  */
2641
- async productionSealOutput(permit) {
2958
+ async productionSealOutput(acp) {
2642
2959
  this.assertChainId();
2643
2960
  this.assertPublicClient();
2644
2961
  const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
2645
- const permission = PermitUtils.getPermission(permit, true);
2962
+ const wireAcp = ACPUtils.getPublic(acp, true);
2646
2963
  const sealed = await tnSealOutputV2({
2647
2964
  ctHash: this.ctHash,
2648
2965
  chainId: this.chainId,
2649
- permission,
2966
+ acp: wireAcp,
2650
2967
  thresholdNetworkUrl,
2651
2968
  retry404TimeoutMs: this.retry404TimeoutMs,
2652
2969
  onPoll: this.pollCallback
2653
2970
  });
2654
- return PermitUtils.unseal(permit, sealed);
2971
+ return ACPUtils.unseal(acp, sealed);
2655
2972
  }
2656
2973
  /**
2657
2974
  * Final step of the decryption process. MUST BE CALLED LAST IN THE CHAIN.
2658
2975
  *
2659
2976
  * This will:
2660
- * - Use a permit based on provided permit OR chainId + account + permitHash
2661
- * - Check permit validity
2662
- * - Call CoFHE `/sealoutput` with the permit, which returns a sealed (encrypted) item
2663
- * - 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
2664
2981
  * - Return the unsealed item
2665
2982
  *
2666
2983
  * Example:
@@ -2668,7 +2985,7 @@ var DecryptForViewBuilder = class extends BaseBuilder {
2668
2985
  * const unsealed = await client.decryptForView(ctHash, utype)
2669
2986
  * .setChainId(11155111) // optional
2670
2987
  * .setAccount('0x123...890') // optional
2671
- * .withPermit() // optional
2988
+ * .withACP() // optional
2672
2989
  * .execute(); // execute
2673
2990
  * ```
2674
2991
  *
@@ -2676,14 +2993,14 @@ var DecryptForViewBuilder = class extends BaseBuilder {
2676
2993
  */
2677
2994
  async execute() {
2678
2995
  this.validateUtypeOrThrow();
2679
- const permit = await this.getResolvedPermit();
2680
- PermitUtils.validate(permit);
2681
- const chainId = permit._signedDomain.chainId;
2996
+ const acp = await this.getResolvedACP();
2997
+ ACPUtils.validate(acp);
2998
+ const chainId = acp._signedDomain.chainId;
2682
2999
  let unsealed;
2683
3000
  if (chainId === hardhat$1.id) {
2684
- unsealed = await this.mocksSealOutput(permit);
3001
+ unsealed = await this.mocksSealOutput(acp);
2685
3002
  } else {
2686
- unsealed = await this.productionSealOutput(permit);
3003
+ unsealed = await this.productionSealOutput(acp);
2687
3004
  }
2688
3005
  return convertViaUtype(this.utype, unsealed);
2689
3006
  }
@@ -2691,28 +3008,28 @@ var DecryptForViewBuilder = class extends BaseBuilder {
2691
3008
  var UINT_TYPE_MASK = 0x7fn;
2692
3009
  var TYPE_BYTE_OFFSET = 8n;
2693
3010
  var getEncryptionTypeFromCtHash = (ctHash) => Number(ctHash >> TYPE_BYTE_OFFSET & UINT_TYPE_MASK);
2694
- async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient) {
3011
+ async function cofheMocksDecryptForTx(ctHash, utype, acp, publicClient) {
2695
3012
  let allowed;
2696
3013
  let error;
2697
3014
  let decryptedValue;
2698
- if (permit !== null) {
2699
- let permission = PermitUtils.getPermission(permit, true);
3015
+ if (acp !== null) {
3016
+ const wireAcp = ACPUtils.getPublic(acp, true);
2700
3017
  const permissionWithBigInts = {
2701
- ...permission,
2702
- expiration: BigInt(permission.expiration),
2703
- validatorId: BigInt(permission.validatorId)
3018
+ ...wireAcp,
3019
+ expiration: BigInt(wireAcp.expiration),
3020
+ revokerData: BigInt(wireAcp.revokerData)
2704
3021
  };
2705
3022
  [allowed, error, decryptedValue] = await publicClient.readContract({
2706
3023
  address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
2707
3024
  abi: MockThresholdNetworkAbi,
2708
- functionName: "decryptForTxWithPermit",
3025
+ functionName: "decryptForTxWithACP",
2709
3026
  args: [BigInt(ctHash), permissionWithBigInts]
2710
3027
  });
2711
3028
  } else {
2712
3029
  [allowed, error, decryptedValue] = await publicClient.readContract({
2713
3030
  address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
2714
3031
  abi: MockThresholdNetworkAbi,
2715
- functionName: "decryptForTxWithoutPermit",
3032
+ functionName: "decryptForTxWithoutACP",
2716
3033
  args: [BigInt(ctHash)]
2717
3034
  });
2718
3035
  }
@@ -2747,62 +3064,6 @@ async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient) {
2747
3064
  signature
2748
3065
  };
2749
3066
  }
2750
- function normalizeTnSignature(signature) {
2751
- if (typeof signature !== "string") {
2752
- throw new CofheError({
2753
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2754
- message: "decrypt response missing signature",
2755
- context: {
2756
- signature
2757
- }
2758
- });
2759
- }
2760
- const trimmed = signature.trim();
2761
- if (trimmed.length === 0) {
2762
- throw new CofheError({
2763
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2764
- message: "decrypt response returned empty signature"
2765
- });
2766
- }
2767
- const prefixed = trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
2768
- const parsed = parseSignature(prefixed);
2769
- return serializeSignature(parsed);
2770
- }
2771
- function parseDecryptedBytesToBigInt(decrypted) {
2772
- if (!Array.isArray(decrypted)) {
2773
- throw new CofheError({
2774
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2775
- message: "decrypt response field <decrypted> must be a byte array",
2776
- context: {
2777
- decrypted
2778
- }
2779
- });
2780
- }
2781
- if (decrypted.length === 0) {
2782
- throw new CofheError({
2783
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2784
- message: "decrypt response field <decrypted> was an empty byte array",
2785
- context: {
2786
- decrypted
2787
- }
2788
- });
2789
- }
2790
- let hex = "";
2791
- for (const b of decrypted) {
2792
- if (typeof b !== "number" || !Number.isInteger(b) || b < 0 || b > 255) {
2793
- throw new CofheError({
2794
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
2795
- message: "decrypt response field <decrypted> contained a non-byte value",
2796
- context: {
2797
- badElement: b,
2798
- decrypted
2799
- }
2800
- });
2801
- }
2802
- hex += b.toString(16).padStart(2, "0");
2803
- }
2804
- return BigInt(`0x${hex}`);
2805
- }
2806
3067
 
2807
3068
  // core/decrypt/tnDecryptV2.ts
2808
3069
  var POLL_INTERVAL_MS2 = 1e3;
@@ -2924,15 +3185,16 @@ function assertDecryptStatusResponseV2(value) {
2924
3185
  }
2925
3186
  return value;
2926
3187
  }
2927
- async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, permission, overallStartTime, retry404TimeoutMs, onPoll) {
3188
+ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, acp, overallStartTime, retry404TimeoutMs, onPoll) {
2928
3189
  const body = {
2929
3190
  ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
2930
3191
  host_chain_id: chainId
2931
3192
  };
2932
- if (permission) {
2933
- body.permit = permission;
3193
+ if (acp) {
3194
+ body.acp = acp;
2934
3195
  }
2935
3196
  let attemptIndex = 0;
3197
+ let last404ApiErrorMessage;
2936
3198
  for (; ; ) {
2937
3199
  let response;
2938
3200
  try {
@@ -2960,16 +3222,19 @@ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, perm
2960
3222
  }
2961
3223
  });
2962
3224
  }
2963
- const responseClassification = await classifySubmitResponse({ response });
3225
+ const responseClassification = await classifySubmitResponse({
3226
+ response,
3227
+ fallbackErrorCode: "DECRYPT_FAILED" /* DecryptFailed */
3228
+ });
2964
3229
  if (responseClassification.kind === "fatal-http") {
2965
3230
  throw new CofheError({
2966
- code: "DECRYPT_FAILED" /* DecryptFailed */,
3231
+ code: responseClassification.cofheErrorCode,
3232
+ apiErrorCode: responseClassification.apiErrorCode,
2967
3233
  message: `decrypt request failed: ${responseClassification.errorMessage}`,
2968
3234
  hint: "Check the threshold network URL and request parameters.",
2969
3235
  context: {
2970
3236
  thresholdNetworkUrl,
2971
- status: response.status,
2972
- statusText: response.statusText,
3237
+ status: responseClassification.status,
2973
3238
  body,
2974
3239
  attemptIndex
2975
3240
  }
@@ -3017,6 +3282,9 @@ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, perm
3017
3282
  }
3018
3283
  });
3019
3284
  }
3285
+ if (responseClassification.status === 404) {
3286
+ last404ApiErrorMessage = responseClassification.apiErrorMessage;
3287
+ }
3020
3288
  const elapsedMs = Date.now() - overallStartTime;
3021
3289
  throwIfSubmitRetryTimedOut({
3022
3290
  operationLabel: "decrypt",
@@ -3027,7 +3295,8 @@ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, perm
3027
3295
  overallTimeoutMs: DECRYPT_TIMEOUT_MS,
3028
3296
  thresholdNetworkUrl,
3029
3297
  body,
3030
- attemptIndex
3298
+ attemptIndex,
3299
+ lastKnownErrorMessage: last404ApiErrorMessage
3031
3300
  });
3032
3301
  onPoll?.({
3033
3302
  operation: "decrypt",
@@ -3105,17 +3374,10 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId, overallStartT
3105
3374
  });
3106
3375
  }
3107
3376
  if (!response.ok) {
3108
- let errorMessage = `HTTP ${response.status}`;
3109
- try {
3110
- const errorBody = await response.json();
3111
- const maybeMessage = errorBody.error_message || errorBody.message;
3112
- if (typeof maybeMessage === "string" && maybeMessage.length > 0)
3113
- errorMessage = maybeMessage;
3114
- } catch {
3115
- errorMessage = response.statusText || errorMessage;
3116
- }
3377
+ const { apiErrorCode, errorMessage } = await parseApiErrorResponseBody(response);
3117
3378
  throw new CofheError({
3118
- code: "DECRYPT_FAILED" /* DecryptFailed */,
3379
+ code: mapApiErrorCodeToCofheErrorCode(apiErrorCode, "DECRYPT_FAILED" /* DecryptFailed */),
3380
+ apiErrorCode,
3119
3381
  message: `decrypt status poll failed: ${errorMessage}`,
3120
3382
  context: {
3121
3383
  thresholdNetworkUrl,
@@ -3160,7 +3422,7 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId, overallStartT
3160
3422
  });
3161
3423
  }
3162
3424
  async function tnDecryptV2(params) {
3163
- const { thresholdNetworkUrl, ctHash, chainId, permission, retry404TimeoutMs, onPoll } = params;
3425
+ const { thresholdNetworkUrl, ctHash, chainId, acp, retry404TimeoutMs, onPoll } = params;
3164
3426
  const normalized404RetryTimeoutMs = normalize404RetryTimeoutMs({
3165
3427
  timeoutMs: retry404TimeoutMs,
3166
3428
  operationLabel: "decrypt",
@@ -3171,7 +3433,7 @@ async function tnDecryptV2(params) {
3171
3433
  thresholdNetworkUrl,
3172
3434
  ctHash,
3173
3435
  chainId,
3174
- permission,
3436
+ acp,
3175
3437
  overallStartTime,
3176
3438
  normalized404RetryTimeoutMs,
3177
3439
  onPoll
@@ -3186,9 +3448,9 @@ async function tnDecryptV2(params) {
3186
3448
  var DEFAULT_404_RETRY_TIMEOUT_MS3 = 1e4;
3187
3449
  var DecryptForTxBuilder = class extends BaseBuilder {
3188
3450
  ctHash;
3189
- permitHash;
3190
- permit;
3191
- permitSelection = "unset";
3451
+ acpHash;
3452
+ acp;
3453
+ acpSelection = "unset";
3192
3454
  pollCallback;
3193
3455
  retry404TimeoutMs = DEFAULT_404_RETRY_TIMEOUT_MS3;
3194
3456
  constructor(params) {
@@ -3233,137 +3495,137 @@ var DecryptForTxBuilder = class extends BaseBuilder {
3233
3495
  this.retry404TimeoutMs = timeoutMs;
3234
3496
  return this;
3235
3497
  }
3236
- withPermit(permitOrPermitHash) {
3237
- if (this.permitSelection === "with-permit") {
3498
+ withACP(acpOrACPHash) {
3499
+ if (this.acpSelection === "with-acp") {
3238
3500
  throw new CofheError({
3239
3501
  code: "INTERNAL_ERROR" /* InternalError */,
3240
- message: "decryptForTx: withPermit() can only be selected once.",
3241
- 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."
3242
3504
  });
3243
3505
  }
3244
- if (this.permitSelection === "without-permit") {
3506
+ if (this.acpSelection === "without-acp") {
3245
3507
  throw new CofheError({
3246
3508
  code: "INTERNAL_ERROR" /* InternalError */,
3247
- message: "decryptForTx: cannot call withPermit() after withoutPermit() has been selected.",
3248
- 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."
3249
3511
  });
3250
3512
  }
3251
- this.permitSelection = "with-permit";
3252
- if (typeof permitOrPermitHash === "string") {
3253
- this.permitHash = permitOrPermitHash;
3254
- this.permit = void 0;
3255
- } else if (permitOrPermitHash === void 0) {
3256
- this.permitHash = void 0;
3257
- 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;
3258
3520
  } else {
3259
- this.permit = permitOrPermitHash;
3260
- this.permitHash = void 0;
3521
+ this.acp = acpOrACPHash;
3522
+ this.acpHash = void 0;
3261
3523
  }
3262
3524
  return this;
3263
3525
  }
3264
3526
  /**
3265
- * Select "no permit" mode.
3527
+ * Select "no acp" mode.
3266
3528
  *
3267
- * 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`.
3268
3530
  */
3269
- withoutPermit() {
3270
- if (this.permitSelection === "without-permit") {
3531
+ withoutACP() {
3532
+ if (this.acpSelection === "without-acp") {
3271
3533
  throw new CofheError({
3272
3534
  code: "INTERNAL_ERROR" /* InternalError */,
3273
- message: "decryptForTx: withoutPermit() can only be selected once.",
3274
- 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."
3275
3537
  });
3276
3538
  }
3277
- if (this.permitSelection === "with-permit") {
3539
+ if (this.acpSelection === "with-acp") {
3278
3540
  throw new CofheError({
3279
3541
  code: "INTERNAL_ERROR" /* InternalError */,
3280
- message: "decryptForTx: cannot call withoutPermit() after withPermit() has been selected.",
3281
- 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."
3282
3544
  });
3283
3545
  }
3284
- this.permitSelection = "without-permit";
3285
- this.permitHash = void 0;
3286
- this.permit = void 0;
3546
+ this.acpSelection = "without-acp";
3547
+ this.acpHash = void 0;
3548
+ this.acp = void 0;
3287
3549
  return this;
3288
3550
  }
3289
- getPermit() {
3290
- return this.permit;
3551
+ getACP() {
3552
+ return this.acp;
3291
3553
  }
3292
- getPermitHash() {
3293
- return this.permitHash;
3554
+ getACPHash() {
3555
+ return this.acpHash;
3294
3556
  }
3295
3557
  async getThresholdNetworkUrl() {
3296
3558
  this.assertChainId();
3297
3559
  return getThresholdNetworkUrlOrThrow(this.config, this.chainId);
3298
3560
  }
3299
- async getResolvedPermit() {
3300
- if (this.permitSelection === "unset") {
3561
+ async getResolvedACP() {
3562
+ if (this.acpSelection === "unset") {
3301
3563
  throw new CofheError({
3302
3564
  code: "INTERNAL_ERROR" /* InternalError */,
3303
- message: "decryptForTx: missing permit selection; call withPermit(...) or withoutPermit() before execute().",
3304
- 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."
3305
3567
  });
3306
3568
  }
3307
- if (this.permitSelection === "without-permit") {
3569
+ if (this.acpSelection === "without-acp") {
3308
3570
  return null;
3309
3571
  }
3310
- if (this.permit)
3311
- return this.permit;
3572
+ if (this.acp)
3573
+ return this.acp;
3312
3574
  this.assertChainId();
3313
3575
  this.assertAccount();
3314
- if (this.permitHash) {
3315
- const permit2 = await permits.getPermit(this.chainId, this.account, this.permitHash);
3316
- if (!permit2) {
3576
+ if (this.acpHash) {
3577
+ const acp2 = await acps.getACP(this.chainId, this.account, this.acpHash);
3578
+ if (!acp2) {
3317
3579
  throw new CofheError({
3318
- code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
3319
- message: `Permit with hash <${this.permitHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
3320
- 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.",
3321
3583
  context: {
3322
3584
  chainId: this.chainId,
3323
3585
  account: this.account,
3324
- permitHash: this.permitHash
3586
+ acpHash: this.acpHash
3325
3587
  }
3326
3588
  });
3327
3589
  }
3328
- return permit2;
3590
+ return acp2;
3329
3591
  }
3330
- const permit = await permits.getActivePermit(this.chainId, this.account);
3331
- if (!permit) {
3592
+ const acp = await acps.getActiveACP(this.chainId, this.account);
3593
+ if (!acp) {
3332
3594
  throw new CofheError({
3333
- code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
3334
- message: `Active permit not found for chainId <${this.chainId}> and account <${this.account}>`,
3335
- 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)).",
3336
3598
  context: {
3337
3599
  chainId: this.chainId,
3338
3600
  account: this.account
3339
3601
  }
3340
3602
  });
3341
3603
  }
3342
- return permit;
3604
+ return acp;
3343
3605
  }
3344
3606
  /**
3345
3607
  * On hardhat, interact with MockThresholdNetwork contract
3346
3608
  */
3347
- async mocksDecryptForTx(permit) {
3609
+ async mocksDecryptForTx(acp) {
3348
3610
  this.assertPublicClient();
3349
3611
  const delay = this.config.mocks.decryptDelay;
3350
3612
  if (delay > 0)
3351
3613
  await sleep(delay);
3352
- const result = await cofheMocksDecryptForTx(this.ctHash, 0, permit, this.publicClient);
3614
+ const result = await cofheMocksDecryptForTx(this.ctHash, 0, acp, this.publicClient);
3353
3615
  return result;
3354
3616
  }
3355
3617
  /**
3356
3618
  * In the production context, perform a true decryption with the CoFHE coprocessor.
3357
3619
  */
3358
- async productionDecryptForTx(permit) {
3620
+ async productionDecryptForTx(acp) {
3359
3621
  this.assertChainId();
3360
3622
  this.assertPublicClient();
3361
3623
  const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
3362
- const permission = permit ? PermitUtils.getPermission(permit, true) : null;
3624
+ const wireAcp = acp ? ACPUtils.getPublic(acp, true) : null;
3363
3625
  const { decryptedValue, signature } = await tnDecryptV2({
3364
3626
  ctHash: this.ctHash,
3365
3627
  chainId: this.chainId,
3366
- permission,
3628
+ acp: wireAcp,
3367
3629
  thresholdNetworkUrl,
3368
3630
  retry404TimeoutMs: this.retry404TimeoutMs,
3369
3631
  onPoll: this.pollCallback
@@ -3377,19 +3639,19 @@ var DecryptForTxBuilder = class extends BaseBuilder {
3377
3639
  /**
3378
3640
  * Final step of the decryptForTx process. MUST BE CALLED LAST IN THE CHAIN.
3379
3641
  *
3380
- * You must explicitly choose one permit mode before calling `execute()`:
3381
- * - `withPermit(permit)` / `withPermit(permitHash)` / `withPermit()` (active permit)
3382
- * - `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)
3383
3645
  */
3384
3646
  async execute() {
3385
- const permit = await this.getResolvedPermit();
3386
- if (permit !== null) {
3387
- PermitUtils.validate(permit);
3388
- 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;
3389
3651
  if (chainId === hardhat$1.id) {
3390
- return await this.mocksDecryptForTx(permit);
3652
+ return await this.mocksDecryptForTx(acp);
3391
3653
  } else {
3392
- return await this.productionDecryptForTx(permit);
3654
+ return await this.productionDecryptForTx(acp);
3393
3655
  }
3394
3656
  } else {
3395
3657
  if (!this.chainId) {
@@ -3452,6 +3714,21 @@ function createCofheClientBase(opts) {
3452
3714
  const updateConnectState = (partial) => {
3453
3715
  connectStore.setState((state) => ({ ...state, ...partial }));
3454
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
+ };
3455
3732
  const _requireConnected = () => {
3456
3733
  const state = connectStore.getState();
3457
3734
  const notConnected = !state.connected || !state.account || !state.chainId || !state.publicClient || !state.walletClient;
@@ -3574,74 +3851,147 @@ function createCofheClientBase(opts) {
3574
3851
  }
3575
3852
  return { chainId: _chainId, account: _account };
3576
3853
  };
3577
- const clientPermits = {
3854
+ const clientACPs = {
3578
3855
  // Pass through store access
3579
- getSnapshot: permits.getSnapshot,
3580
- subscribe: permits.subscribe,
3856
+ getSnapshot: acps.getSnapshot,
3857
+ subscribe: acps.subscribe,
3581
3858
  // Creation methods (require connection)
3582
3859
  createSelf: async (options, clients) => {
3583
3860
  _requireConnected();
3584
3861
  const { publicClient, walletClient } = clients ?? connectStore.getState();
3585
- 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
+ );
3586
3868
  },
3587
3869
  createSharing: async (options, clients) => {
3588
3870
  _requireConnected();
3589
3871
  const { publicClient, walletClient } = clients ?? connectStore.getState();
3590
- 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
+ );
3591
3878
  },
3592
3879
  importShared: async (options, clients) => {
3593
3880
  _requireConnected();
3594
3881
  const { publicClient, walletClient } = clients ?? connectStore.getState();
3595
- return permits.importShared(options, publicClient, walletClient);
3882
+ return acps.importShared(options, publicClient, walletClient);
3596
3883
  },
3597
3884
  // Get or create methods (require connection)
3598
- getOrCreateSelfPermit: async (chainId, account, options) => {
3885
+ getOrCreateSelfACP: async (chainId, account, options) => {
3599
3886
  _requireConnected();
3600
3887
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3601
3888
  const { publicClient, walletClient } = connectStore.getState();
3602
- 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);
3603
3896
  },
3604
- getOrCreateSharingPermit: async (options, chainId, account) => {
3897
+ getOrCreateSharingACP: async (options, chainId, account) => {
3605
3898
  _requireConnected();
3606
3899
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3607
3900
  const { publicClient, walletClient } = connectStore.getState();
3608
- 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);
3609
3959
  },
3610
3960
  // Retrieval methods (auto-fill chainId/account)
3611
- getPermit: (hash, chainId, account) => {
3961
+ getACP: (hash, chainId, account) => {
3612
3962
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3613
- return permits.getPermit(_chainId, _account, hash);
3963
+ return acps.getACP(_chainId, _account, hash);
3614
3964
  },
3615
- getPermits: (chainId, account) => {
3965
+ getACPs: (chainId, account) => {
3616
3966
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3617
- return permits.getPermits(_chainId, _account);
3967
+ return acps.getACPs(_chainId, _account);
3618
3968
  },
3619
- getActivePermit: (chainId, account) => {
3969
+ getActiveACP: (chainId, account) => {
3620
3970
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3621
- return permits.getActivePermit(_chainId, _account);
3971
+ return acps.getActiveACP(_chainId, _account);
3622
3972
  },
3623
- getActivePermitHash: (chainId, account) => {
3973
+ getActiveACPHash: (chainId, account) => {
3624
3974
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3625
- return permits.getActivePermitHash(_chainId, _account);
3975
+ return acps.getActiveACPHash(_chainId, _account);
3626
3976
  },
3627
3977
  // Mutation methods (auto-fill chainId/account)
3628
- selectActivePermit: (hash, chainId, account) => {
3978
+ selectActiveACP: (hash, chainId, account) => {
3629
3979
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3630
- return permits.selectActivePermit(_chainId, _account, hash);
3980
+ return acps.selectActiveACP(_chainId, _account, hash);
3631
3981
  },
3632
- removePermit: async (hash, chainId, account) => {
3982
+ removeACP: async (hash, chainId, account) => {
3633
3983
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3634
- return permits.removePermit(_chainId, _account, hash);
3984
+ return acps.removeACP(_chainId, _account, hash);
3635
3985
  },
3636
- removeActivePermit: async (chainId, account) => {
3986
+ removeActiveACP: async (chainId, account) => {
3637
3987
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
3638
- return permits.removeActivePermit(_chainId, _account);
3988
+ return acps.removeActiveACP(_chainId, _account);
3639
3989
  },
3640
3990
  // Utils (no context needed)
3641
- getHash: permits.getHash,
3642
- export: permits.export,
3643
- serialize: permits.serialize,
3644
- deserialize: permits.deserialize
3991
+ getHash: acps.getHash,
3992
+ export: acps.export,
3993
+ serialize: acps.serialize,
3994
+ deserialize: acps.deserialize
3645
3995
  };
3646
3996
  return {
3647
3997
  // Zustand reactive accessors (don't export store directly to prevent mutation)
@@ -3669,7 +4019,7 @@ function createCofheClientBase(opts) {
3669
4019
  decryptHandle: decryptForView,
3670
4020
  decryptForTx,
3671
4021
  verifyDecryptResult: verifyDecryptResult2,
3672
- permits: clientPermits
4022
+ acp: clientACPs
3673
4023
  // Add SDK-specific methods below that require connection
3674
4024
  // Example:
3675
4025
  // async encryptData(data: unknown) {
@@ -3679,4 +4029,4 @@ function createCofheClientBase(opts) {
3679
4029
  };
3680
4030
  }
3681
4031
 
3682
- export { CofheError, CofheErrorCode, DecryptForTxBuilder, DecryptForViewBuilder, EncryptInputsBuilder, EncryptStep, Encryptable, FheAllUTypes, FheTypes, FheUintUTypes, InitialConnectStore, assertCorrectEncryptedItemInput, cofheFetch, createCofheClientBase, createCofheConfigBase, createKeysStore, fetchKeys, fheTypeToString, getCofheConfigItem, getCofheDebugInterceptors, isCofheError, isEncryptableItem, isLastEncryptionStep, setCofheDebugInterceptors, 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 };