@cofhe/sdk 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/CHANGELOG.md +43 -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
package/dist/core.cjs CHANGED
@@ -16,58 +16,78 @@ var nacl__default = /*#__PURE__*/_interopDefault(nacl);
16
16
  // core/client.ts
17
17
 
18
18
  // core/error.ts
19
- var CofheErrorCode = /* @__PURE__ */ ((CofheErrorCode3) => {
20
- CofheErrorCode3["InternalError"] = "INTERNAL_ERROR";
21
- CofheErrorCode3["UnknownEnvironment"] = "UNKNOWN_ENVIRONMENT";
22
- CofheErrorCode3["InitTfheFailed"] = "INIT_TFHE_FAILED";
23
- CofheErrorCode3["InitViemFailed"] = "INIT_VIEM_FAILED";
24
- CofheErrorCode3["InitEthersFailed"] = "INIT_ETHERS_FAILED";
25
- CofheErrorCode3["NotConnected"] = "NOT_CONNECTED";
26
- CofheErrorCode3["MissingPublicClient"] = "MISSING_PUBLIC_CLIENT";
27
- CofheErrorCode3["MissingWalletClient"] = "MISSING_WALLET_CLIENT";
28
- CofheErrorCode3["MissingProviderParam"] = "MISSING_PROVIDER_PARAM";
29
- CofheErrorCode3["EmptySecurityZonesParam"] = "EMPTY_SECURITY_ZONES_PARAM";
30
- CofheErrorCode3["InvalidPermitData"] = "INVALID_PERMIT_DATA";
31
- CofheErrorCode3["InvalidPermitDomain"] = "INVALID_PERMIT_DOMAIN";
32
- CofheErrorCode3["PermitNotFound"] = "PERMIT_NOT_FOUND";
33
- CofheErrorCode3["CannotRemoveLastPermit"] = "CANNOT_REMOVE_LAST_PERMIT";
34
- CofheErrorCode3["AccountUninitialized"] = "ACCOUNT_UNINITIALIZED";
35
- CofheErrorCode3["ChainIdUninitialized"] = "CHAIN_ID_UNINITIALIZED";
36
- CofheErrorCode3["SealOutputFailed"] = "SEAL_OUTPUT_FAILED";
37
- CofheErrorCode3["SealOutputReturnedNull"] = "SEAL_OUTPUT_RETURNED_NULL";
38
- CofheErrorCode3["InvalidUtype"] = "INVALID_UTYPE";
39
- CofheErrorCode3["DecryptFailed"] = "DECRYPT_FAILED";
40
- CofheErrorCode3["DecryptReturnedNull"] = "DECRYPT_RETURNED_NULL";
41
- CofheErrorCode3["ZkMocksInsertCtHashesFailed"] = "ZK_MOCKS_INSERT_CT_HASHES_FAILED";
42
- CofheErrorCode3["ZkMocksCalcCtHashesFailed"] = "ZK_MOCKS_CALC_CT_HASHES_FAILED";
43
- CofheErrorCode3["ZkMocksVerifySignFailed"] = "ZK_MOCKS_VERIFY_SIGN_FAILED";
44
- CofheErrorCode3["ZkMocksCreateProofSignatureFailed"] = "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED";
45
- CofheErrorCode3["ZkVerifyFailed"] = "ZK_VERIFY_FAILED";
46
- CofheErrorCode3["ZkPackFailed"] = "ZK_PACK_FAILED";
47
- CofheErrorCode3["ZkProveFailed"] = "ZK_PROVE_FAILED";
48
- CofheErrorCode3["EncryptRemainingInItems"] = "ENCRYPT_REMAINING_IN_ITEMS";
49
- CofheErrorCode3["ZkUninitialized"] = "ZK_UNINITIALIZED";
50
- CofheErrorCode3["ZkVerifierUrlUninitialized"] = "ZK_VERIFIER_URL_UNINITIALIZED";
51
- CofheErrorCode3["ThresholdNetworkUrlUninitialized"] = "THRESHOLD_NETWORK_URL_UNINITIALIZED";
52
- CofheErrorCode3["MissingConfig"] = "MISSING_CONFIG";
53
- CofheErrorCode3["UnsupportedChain"] = "UNSUPPORTED_CHAIN";
54
- CofheErrorCode3["MissingZkBuilderAndCrsGenerator"] = "MISSING_ZK_BUILDER_AND_CRS_GENERATOR";
55
- CofheErrorCode3["MissingTfhePublicKeyDeserializer"] = "MISSING_TFHE_PUBLIC_KEY_DESERIALIZER";
56
- CofheErrorCode3["MissingCompactPkeCrsDeserializer"] = "MISSING_COMPACT_PKE_CRS_DESERIALIZER";
57
- CofheErrorCode3["MissingFheKey"] = "MISSING_FHE_KEY";
58
- CofheErrorCode3["MissingCrs"] = "MISSING_CRS";
59
- CofheErrorCode3["FetchKeysFailed"] = "FETCH_KEYS_FAILED";
60
- CofheErrorCode3["PublicWalletGetChainIdFailed"] = "PUBLIC_WALLET_GET_CHAIN_ID_FAILED";
61
- CofheErrorCode3["PublicWalletGetAddressesFailed"] = "PUBLIC_WALLET_GET_ADDRESSES_FAILED";
62
- CofheErrorCode3["RehydrateKeysStoreFailed"] = "REHYDRATE_KEYS_STORE_FAILED";
63
- return CofheErrorCode3;
19
+ var CofheErrorCode = /* @__PURE__ */ ((CofheErrorCode2) => {
20
+ CofheErrorCode2["InternalError"] = "INTERNAL_ERROR";
21
+ CofheErrorCode2["UnknownEnvironment"] = "UNKNOWN_ENVIRONMENT";
22
+ CofheErrorCode2["InitTfheFailed"] = "INIT_TFHE_FAILED";
23
+ CofheErrorCode2["InitViemFailed"] = "INIT_VIEM_FAILED";
24
+ CofheErrorCode2["InitEthersFailed"] = "INIT_ETHERS_FAILED";
25
+ CofheErrorCode2["NotConnected"] = "NOT_CONNECTED";
26
+ CofheErrorCode2["MissingPublicClient"] = "MISSING_PUBLIC_CLIENT";
27
+ CofheErrorCode2["MissingWalletClient"] = "MISSING_WALLET_CLIENT";
28
+ CofheErrorCode2["MissingProviderParam"] = "MISSING_PROVIDER_PARAM";
29
+ CofheErrorCode2["EmptySecurityZonesParam"] = "EMPTY_SECURITY_ZONES_PARAM";
30
+ CofheErrorCode2["InvalidACPData"] = "INVALID_ACP_DATA";
31
+ CofheErrorCode2["InvalidACPDomain"] = "INVALID_ACP_DOMAIN";
32
+ CofheErrorCode2["ACPNotFound"] = "ACP_NOT_FOUND";
33
+ CofheErrorCode2["CannotRemoveLastACP"] = "CANNOT_REMOVE_LAST_ACP";
34
+ CofheErrorCode2["AccountUninitialized"] = "ACCOUNT_UNINITIALIZED";
35
+ CofheErrorCode2["ChainIdUninitialized"] = "CHAIN_ID_UNINITIALIZED";
36
+ CofheErrorCode2["ConsumingContractUninitialized"] = "CONSUMING_CONTRACT_UNINITIALIZED";
37
+ CofheErrorCode2["SealOutputFailed"] = "SEAL_OUTPUT_FAILED";
38
+ CofheErrorCode2["SealOutputReturnedNull"] = "SEAL_OUTPUT_RETURNED_NULL";
39
+ CofheErrorCode2["InvalidUtype"] = "INVALID_UTYPE";
40
+ CofheErrorCode2["DecryptFailed"] = "DECRYPT_FAILED";
41
+ CofheErrorCode2["DecryptReturnedNull"] = "DECRYPT_RETURNED_NULL";
42
+ CofheErrorCode2["ZkMocksInsertCtHashesFailed"] = "ZK_MOCKS_INSERT_CT_HASHES_FAILED";
43
+ CofheErrorCode2["ZkMocksCalcCtHashesFailed"] = "ZK_MOCKS_CALC_CT_HASHES_FAILED";
44
+ CofheErrorCode2["ZkMocksVerifySignFailed"] = "ZK_MOCKS_VERIFY_SIGN_FAILED";
45
+ CofheErrorCode2["ZkMocksCreateProofSignatureFailed"] = "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED";
46
+ CofheErrorCode2["ZkVerifyFailed"] = "ZK_VERIFY_FAILED";
47
+ CofheErrorCode2["ZkPackFailed"] = "ZK_PACK_FAILED";
48
+ CofheErrorCode2["ZkProveFailed"] = "ZK_PROVE_FAILED";
49
+ CofheErrorCode2["EncryptRemainingInItems"] = "ENCRYPT_REMAINING_IN_ITEMS";
50
+ CofheErrorCode2["ZkUninitialized"] = "ZK_UNINITIALIZED";
51
+ CofheErrorCode2["ZkVerifierUrlUninitialized"] = "ZK_VERIFIER_URL_UNINITIALIZED";
52
+ CofheErrorCode2["ThresholdNetworkUrlUninitialized"] = "THRESHOLD_NETWORK_URL_UNINITIALIZED";
53
+ CofheErrorCode2["MissingConfig"] = "MISSING_CONFIG";
54
+ CofheErrorCode2["UnsupportedChain"] = "UNSUPPORTED_CHAIN";
55
+ CofheErrorCode2["MissingZkBuilderAndCrsGenerator"] = "MISSING_ZK_BUILDER_AND_CRS_GENERATOR";
56
+ CofheErrorCode2["MissingTfhePublicKeyDeserializer"] = "MISSING_TFHE_PUBLIC_KEY_DESERIALIZER";
57
+ CofheErrorCode2["MissingCompactPkeCrsDeserializer"] = "MISSING_COMPACT_PKE_CRS_DESERIALIZER";
58
+ CofheErrorCode2["MissingFheKey"] = "MISSING_FHE_KEY";
59
+ CofheErrorCode2["MissingCrs"] = "MISSING_CRS";
60
+ CofheErrorCode2["FetchKeysFailed"] = "FETCH_KEYS_FAILED";
61
+ CofheErrorCode2["PublicWalletGetChainIdFailed"] = "PUBLIC_WALLET_GET_CHAIN_ID_FAILED";
62
+ CofheErrorCode2["PublicWalletGetAddressesFailed"] = "PUBLIC_WALLET_GET_ADDRESSES_FAILED";
63
+ CofheErrorCode2["RehydrateKeysStoreFailed"] = "REHYDRATE_KEYS_STORE_FAILED";
64
+ CofheErrorCode2["BadRequest"] = "BAD_REQUEST";
65
+ CofheErrorCode2["UnknownChain"] = "UNKNOWN_CHAIN";
66
+ CofheErrorCode2["ACPMalformed"] = "ACP_MALFORMED";
67
+ CofheErrorCode2["ACPDenied"] = "ACP_DENIED";
68
+ CofheErrorCode2["ACPExpired"] = "ACP_EXPIRED";
69
+ CofheErrorCode2["ACPInvalid"] = "ACP_INVALID";
70
+ CofheErrorCode2["ACPRevoked"] = "ACP_REVOKED";
71
+ CofheErrorCode2["NotPubliclyAllowed"] = "NOT_PUBLICLY_ALLOWED";
72
+ CofheErrorCode2["CtNotFound"] = "CT_NOT_FOUND";
73
+ CofheErrorCode2["UnsupportedSecurityZone"] = "UNSUPPORTED_SECURITY_ZONE";
74
+ CofheErrorCode2["UnsupportedType"] = "UNSUPPORTED_TYPE";
75
+ CofheErrorCode2["SigningFailed"] = "SIGNING_FAILED";
76
+ CofheErrorCode2["CtSourceError"] = "CT_SOURCE_ERROR";
77
+ CofheErrorCode2["ACPVerifierError"] = "ACP_VERIFIER_ERROR";
78
+ CofheErrorCode2["CtSourceTimeout"] = "CT_SOURCE_TIMEOUT";
79
+ CofheErrorCode2["ACPVerifierTimeout"] = "ACP_VERIFIER_TIMEOUT";
80
+ CofheErrorCode2["ACPRequired"] = "ACP_REQUIRED";
81
+ CofheErrorCode2["SealFailed"] = "SEAL_FAILED";
82
+ return CofheErrorCode2;
64
83
  })(CofheErrorCode || {});
65
84
  var CofheError = class _CofheError extends Error {
66
85
  code;
67
86
  cause;
68
87
  hint;
69
88
  context;
70
- constructor({ code, message, cause, hint, context }) {
89
+ apiErrorCode;
90
+ constructor({ code, message, cause, hint, context, apiErrorCode }) {
71
91
  const fullMessage = cause ? `${message} | Caused by: ${cause.message}` : message;
72
92
  super(fullMessage);
73
93
  this.name = "CofheError";
@@ -75,6 +95,7 @@ var CofheError = class _CofheError extends Error {
75
95
  this.cause = cause;
76
96
  this.hint = hint;
77
97
  this.context = context;
98
+ this.apiErrorCode = apiErrorCode;
78
99
  if (Error.captureStackTrace) {
79
100
  Error.captureStackTrace(this, _CofheError);
80
101
  }
@@ -93,6 +114,7 @@ var CofheError = class _CofheError extends Error {
93
114
  message: wrapperError?.message ?? "An internal error occurred",
94
115
  hint: wrapperError?.hint,
95
116
  context: wrapperError?.context,
117
+ apiErrorCode: wrapperError?.apiErrorCode,
96
118
  cause
97
119
  });
98
120
  }
@@ -106,6 +128,7 @@ var CofheError = class _CofheError extends Error {
106
128
  message: this.message,
107
129
  hint: this.hint,
108
130
  context: this.context,
131
+ apiErrorCode: this.apiErrorCode,
109
132
  cause: this.cause ? {
110
133
  name: this.cause.name,
111
134
  message: this.cause.message,
@@ -118,7 +141,8 @@ var CofheError = class _CofheError extends Error {
118
141
  * Returns a human-readable string representation of the error
119
142
  */
120
143
  toString() {
121
- const parts = [`${this.name} [${this.code}]: ${this.message}`];
144
+ const codeSuffix = this.apiErrorCode ? ` (api: ${this.apiErrorCode})` : "";
145
+ const parts = [`${this.name} [${this.code}]${codeSuffix}: ${this.message}`];
122
146
  if (this.hint) {
123
147
  parts.push(`Hint: ${this.hint}`);
124
148
  }
@@ -215,10 +239,6 @@ var FheAllUTypes = [
215
239
  // FheTypes.Uint256,
216
240
  7 /* Uint160 */
217
241
  ];
218
- function assertCorrectEncryptedItemInput(input) {
219
- if (!input.signature.startsWith("0x"))
220
- throw new Error("Signature must be a hex string starting with 0x");
221
- }
222
242
  var EncryptableFactoriesImpl = {
223
243
  bool: (data, securityZone = 0) => ({ data, securityZone, utype: 0 /* Bool */ }),
224
244
  address: (data, securityZone = 0) => ({ data, securityZone, utype: 7 /* Uint160 */ }),
@@ -498,18 +518,19 @@ var constructZkPoKMetadata = (accountAddr, securityZone, chainId) => {
498
518
  metadata.set(chainIdBytes, 1 + accountBytes.length);
499
519
  return metadata;
500
520
  };
501
- var zkVerify = async (verifierUrl, serializedBytes, address, securityZone, chainId) => {
521
+ var zkVerifyBatch = async (verifierUrl, serializedBytes, address, securityZone, chainId, consumingContract) => {
502
522
  const packed_list = toHexString(serializedBytes);
503
523
  const sz_byte = new Uint8Array([securityZone]);
504
524
  const payload = {
505
525
  packed_list,
506
526
  account_addr: address,
507
527
  security_zone: sz_byte[0],
508
- chain_id: chainId
528
+ chain_id: chainId,
529
+ contract_address: consumingContract
509
530
  };
510
531
  const body = JSON.stringify(payload);
511
532
  try {
512
- const response = await fetch(`${verifierUrl}/verify`, {
533
+ const response = await fetch(`${verifierUrl}/verifyBatch`, {
513
534
  method: "POST",
514
535
  headers: {
515
536
  "Content-Type": "application/json"
@@ -520,26 +541,25 @@ var zkVerify = async (verifierUrl, serializedBytes, address, securityZone, chain
520
541
  const errorBody = await response.text();
521
542
  throw new CofheError({
522
543
  code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
523
- message: `HTTP error! ZK proof verification failed - ${errorBody}`
544
+ message: `HTTP error! ZK batch proof verification failed - ${errorBody}`
524
545
  });
525
546
  }
526
547
  const json = await response.json();
527
548
  if (json.status !== "success") {
528
549
  throw new CofheError({
529
550
  code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
530
- message: `ZK proof verification response malformed - ${json.error}`
551
+ message: `ZK batch proof verification response malformed - ${json.error}`
531
552
  });
532
553
  }
533
- return json.data.map(({ ct_hash, signature, recid }) => {
534
- return {
535
- ct_hash,
536
- signature: concatSigRecid(signature, recid)
537
- };
538
- });
554
+ const { ciphertexts, signature, recid } = json.data;
555
+ return {
556
+ outputs: ciphertexts,
557
+ signature: concatSigRecid(signature, recid)
558
+ };
539
559
  } catch (e) {
540
560
  throw new CofheError({
541
561
  code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
542
- message: `ZK proof verification failed`,
562
+ message: `ZK batch proof verification failed`,
543
563
  cause: e instanceof Error ? e : void 0
544
564
  });
545
565
  }
@@ -784,67 +804,59 @@ async function insertCtHashes(items, walletClient) {
784
804
  });
785
805
  }
786
806
  }
787
- async function createProofSignatures(items, securityZone, account) {
788
- let signatures = [];
789
- let encInputSignerClient;
807
+ async function createBatchProofSignature(items, securityZone, account, consumingContract) {
790
808
  try {
791
- encInputSignerClient = createMockZkVerifierSigner();
792
- } catch (err) {
793
- throw new CofheError({
794
- code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
795
- message: `mockZkVerifySign createProofSignatures failed while creating wallet client`,
796
- cause: err instanceof Error ? err : void 0,
797
- context: {
798
- MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY
799
- }
809
+ const itemHashes = items.map(
810
+ (item) => viem.keccak256(
811
+ viem.encodePacked(
812
+ ["uint256", "uint8", "uint8", "address", "uint256", "address"],
813
+ [
814
+ BigInt(item.ctHash),
815
+ item.utype,
816
+ securityZone,
817
+ account,
818
+ BigInt(chains.hardhat.id),
819
+ consumingContract
820
+ ]
821
+ )
822
+ )
823
+ );
824
+ const batchDigest = viem.keccak256(
825
+ viem.encodePacked(
826
+ itemHashes.map(() => "bytes32"),
827
+ itemHashes
828
+ )
829
+ );
830
+ return await accounts.sign({
831
+ hash: batchDigest,
832
+ privateKey: MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY,
833
+ to: "hex"
800
834
  });
801
- }
802
- try {
803
- for (const item of items) {
804
- const packedData = viem.encodePacked(
805
- ["uint256", "uint8", "uint8", "address", "uint256"],
806
- [BigInt(item.ctHash), item.utype, securityZone, account, BigInt(chains.hardhat.id)]
807
- );
808
- const messageHash = viem.keccak256(packedData);
809
- const signature = await accounts.sign({
810
- hash: messageHash,
811
- privateKey: MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY,
812
- to: "hex"
813
- });
814
- signatures.push(signature);
815
- }
816
835
  } catch (err) {
817
836
  throw new CofheError({
818
837
  code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
819
- message: `mockZkVerifySign createProofSignatures failed while calling signMessage`,
838
+ message: `mockZkVerifySign createBatchProofSignature failed while signing the batch digest`,
820
839
  cause: err instanceof Error ? err : void 0,
821
840
  context: {
822
841
  items,
823
- securityZone
824
- }
825
- });
826
- }
827
- if (signatures.length !== items.length) {
828
- throw new CofheError({
829
- code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
830
- message: `mockZkVerifySign createProofSignatures returned incorrect number of signatures`,
831
- context: {
832
- items,
833
- securityZone
842
+ securityZone,
843
+ consumingContract
834
844
  }
835
845
  });
836
846
  }
837
- return signatures;
838
847
  }
839
- async function cofheMocksZkVerifySign(items, account, securityZone, publicClient, walletClient, zkvWalletClient) {
848
+ async function cofheMocksZkVerifySign(items, account, securityZone, consumingContract, publicClient, walletClient, zkvWalletClient) {
840
849
  const _walletClient = zkvWalletClient ?? createMockZkVerifierSigner();
841
850
  const encryptableItems = await calcCtHashes(items, account, securityZone, publicClient);
842
851
  await insertCtHashes(encryptableItems, _walletClient);
843
- const signatures = await createProofSignatures(encryptableItems, securityZone, account);
844
- return encryptableItems.map((item, index) => ({
845
- ct_hash: item.ctHash.toString(),
846
- signature: signatures[index]
847
- }));
852
+ const signature = await createBatchProofSignature(encryptableItems, securityZone, account, consumingContract);
853
+ return {
854
+ outputs: encryptableItems.map((item) => ({
855
+ ct_hash: item.ctHash.toString(),
856
+ ct_type: item.utype
857
+ })),
858
+ signature
859
+ };
848
860
  }
849
861
  var EnvironmentSchema = zod.z.enum(["MOCK", "TESTNET", "MAINNET"]);
850
862
  var CofheChainSchema = zod.z.object({
@@ -887,8 +899,8 @@ var CofheConfigSchema = zod.z.object({
887
899
  environment: zod.z.enum(["node", "hardhat", "web", "react"]).optional().default("node"),
888
900
  /** List of supported chain configurations */
889
901
  supportedChains: zod.z.array(zod.z.custom()),
890
- /** Default permit expiration in seconds, default is 30 days */
891
- defaultPermitExpiration: zod.z.number().optional().default(60 * 60 * 24 * 30),
902
+ /** Default acp expiration in seconds, default is 30 days */
903
+ defaultACPExpiration: zod.z.number().optional().default(60 * 60 * 24 * 30),
892
904
  /** Storage method for fhe keys (defaults to indexedDB on web, filesystem on node) */
893
905
  fheKeyStorage: zod.z.object({
894
906
  getItem: zod.z.custom((val) => typeof val === "function", {
@@ -903,6 +915,12 @@ var CofheConfigSchema = zod.z.object({
903
915
  }).or(zod.z.null()).default(null),
904
916
  /** Whether to use Web Workers for ZK proof generation (web platform only) */
905
917
  useWorkers: zod.z.boolean().optional().default(true),
918
+ /** ACP acp defaults */
919
+ acp: zod.z.object({
920
+ defaultRevoker: zod.z.custom().optional(),
921
+ defaultContractScopes: zod.z.custom().optional(),
922
+ sharingRegistry: zod.z.custom().optional()
923
+ }).optional().default({}),
906
924
  /** Mocks configs */
907
925
  mocks: zod.z.object({
908
926
  decryptDelay: zod.z.number().optional().default(0),
@@ -913,8 +931,19 @@ var CofheConfigSchema = zod.z.object({
913
931
  zkvWalletClient: zod.z.any().optional()
914
932
  }).optional()
915
933
  });
934
+ var RENAMED_COFHE_CONFIG_KEYS = {
935
+ defaultPermitExpiration: "defaultACPExpiration"
936
+ };
937
+ function assertNoRenamedConfigKeys(config, renamedKeys, label) {
938
+ const stale = Object.keys(config).filter((key) => key in renamedKeys);
939
+ if (stale.length === 0)
940
+ return;
941
+ const renames = stale.map((key) => `\`${key}\` is now \`${renamedKeys[key]}\``).join("; ");
942
+ throw new Error(`Invalid ${label}: ${renames}. See the v0.7.0 migration guide.`);
943
+ }
916
944
  function createCofheConfigBase(config) {
917
- const result = CofheConfigSchema.safeParse(config);
945
+ assertNoRenamedConfigKeys(config, RENAMED_COFHE_CONFIG_KEYS, "cofhe configuration");
946
+ const result = CofheConfigSchema.strict().safeParse(config);
918
947
  if (!result.success) {
919
948
  throw new Error(`Invalid cofhe configuration: ${zod.z.prettifyError(result.error)}`, { cause: result.error });
920
949
  }
@@ -1266,9 +1295,9 @@ var BaseBuilder = class {
1266
1295
  // core/encrypt/encryptInputsBuilder.ts
1267
1296
  var EncryptInputsBuilder = class extends BaseBuilder {
1268
1297
  securityZone;
1298
+ consumingContract;
1269
1299
  stepCallback;
1270
1300
  inputItems;
1271
- hpp = false;
1272
1301
  zkvWalletClient;
1273
1302
  tfhePublicKeyDeserializer;
1274
1303
  compactPkeCrsDeserializer;
@@ -1335,20 +1364,6 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1335
1364
  this.keysStorage = params.keysStorage;
1336
1365
  this.useWorker = params.config?.useWorkers ?? true;
1337
1366
  }
1338
- /**
1339
- * @param account - Account that will create the tx using the encrypted inputs.
1340
- *
1341
- * If not provided, the account will be fetched from the connected walletClient.
1342
- *
1343
- * Example:
1344
- * ```typescript
1345
- * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1346
- * .setAccount("0x123")
1347
- * .execute();
1348
- * ```
1349
- *
1350
- * @returns The chainable EncryptInputsBuilder instance.
1351
- */
1352
1367
  setAccount(account) {
1353
1368
  this.account = account;
1354
1369
  return this;
@@ -1356,20 +1371,6 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1356
1371
  getAccount() {
1357
1372
  return this.account;
1358
1373
  }
1359
- /**
1360
- * @param chainId - Chain that will consume the encrypted inputs.
1361
- *
1362
- * If not provided, the chainId will be fetched from the connected publicClient.
1363
- *
1364
- * Example:
1365
- * ```typescript
1366
- * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1367
- * .setChainId(11155111)
1368
- * .execute();
1369
- * ```
1370
- *
1371
- * @returns The chainable EncryptInputsBuilder instance.
1372
- */
1373
1374
  setChainId(chainId) {
1374
1375
  this.chainId = chainId;
1375
1376
  return this;
@@ -1377,20 +1378,6 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1377
1378
  getChainId() {
1378
1379
  return this.chainId;
1379
1380
  }
1380
- /**
1381
- * @param securityZone - Security zone to encrypt the inputs for.
1382
- *
1383
- * If not provided, the default securityZone 0 will be used.
1384
- *
1385
- * Example:
1386
- * ```typescript
1387
- * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1388
- * .setSecurityZone(1)
1389
- * .execute();
1390
- * ```
1391
- *
1392
- * @returns The chainable EncryptInputsBuilder instance.
1393
- */
1394
1381
  setSecurityZone(securityZone) {
1395
1382
  this.securityZone = securityZone;
1396
1383
  return this;
@@ -1399,33 +1386,44 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1399
1386
  return this.securityZone;
1400
1387
  }
1401
1388
  /**
1389
+ * @param address - The contract that will consume the resulting hashes+signature (i.e. the
1390
+ * contract that will call `FHE.asEuint*`/`FHE.asEuint*s` with them).
1391
+ *
1392
+ * Required before `execute()` - the verifier binds this address into the signed digest, so a
1393
+ * batch signed for one contract cannot be replayed into another.
1394
+ *
1402
1395
  * Example:
1403
1396
  * ```typescript
1404
1397
  * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1405
- * .asHashPlusProof()
1398
+ * .setConsumingContract("0x123...890")
1406
1399
  * .execute();
1407
1400
  * ```
1408
1401
  *
1409
- * @returns Chainable EncryptInputsBuilder instance that will return a HashPlusProofResult instead of an array of EncryptedItemInputs.
1402
+ * @returns The chainable EncryptInputsBuilder instance.
1410
1403
  */
1411
- asHashPlusProof() {
1412
- this.hpp = true;
1404
+ setConsumingContract(address) {
1405
+ this.consumingContract = address;
1413
1406
  return this;
1414
1407
  }
1408
+ getConsumingContract() {
1409
+ return this.consumingContract;
1410
+ }
1415
1411
  /**
1416
- * @param useWorker - Whether to use Web Workers for ZK proof generation.
1417
- *
1418
- * Overrides the config-level useWorkers setting for this specific encryption.
1419
- *
1420
- * Example:
1421
- * ```typescript
1422
- * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1423
- * .setUseWorker(false)
1424
- * .execute();
1425
- * ```
1426
- *
1427
- * @returns The chainable EncryptInputsBuilder instance.
1412
+ * Asserts that this.consumingContract is populated
1413
+ * @throws {CofheError} If consumingContract is not set
1428
1414
  */
1415
+ assertConsumingContract() {
1416
+ if (this.consumingContract)
1417
+ return;
1418
+ throw new CofheError({
1419
+ code: "CONSUMING_CONTRACT_UNINITIALIZED" /* ConsumingContractUninitialized */,
1420
+ message: "Consuming contract is not set",
1421
+ hint: "Use setConsumingContract(...) to set the contract that will consume the encrypted inputs.",
1422
+ context: {
1423
+ consumingContract: this.consumingContract
1424
+ }
1425
+ });
1426
+ }
1429
1427
  setUseWorker(useWorker) {
1430
1428
  this.useWorker = useWorker;
1431
1429
  return this;
@@ -1446,21 +1444,6 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1446
1444
  getUseWorker() {
1447
1445
  return this.useWorker;
1448
1446
  }
1449
- /**
1450
- * @param callback - Function to be called with the encryption step.
1451
- *
1452
- * Useful for debugging and tracking the progress of the encryption process.
1453
- * Useful for a UI element that shows the progress of the encryption process.
1454
- *
1455
- * Example:
1456
- * ```typescript
1457
- * const encrypted = await encryptInputs([Encryptable.uint128(10n)])
1458
- * .onStep((step: EncryptStep) => console.log(step))
1459
- * .execute();
1460
- * ```
1461
- *
1462
- * @returns The EncryptInputsBuilder instance.
1463
- */
1464
1447
  onStep(callback) {
1465
1448
  this.stepCallback = callback;
1466
1449
  return this;
@@ -1599,6 +1582,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1599
1582
  this.assertAccount();
1600
1583
  this.assertPublicClient();
1601
1584
  this.assertWalletClient();
1585
+ this.assertConsumingContract();
1602
1586
  const [initTfheDelay, fetchKeysDelay, packDelay, proveDelay, verifyDelay] = this.resolveEncryptDelays();
1603
1587
  this.fireStepStart("initTfhe" /* InitTfhe */);
1604
1588
  await sleep(initTfheDelay);
@@ -1624,22 +1608,17 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1624
1608
  this.fireStepEnd("prove" /* Prove */, { isMocks: true, mockSleep: proveDelay });
1625
1609
  this.fireStepStart("verify" /* Verify */);
1626
1610
  await sleep(verifyDelay);
1627
- const signedResults = await cofheMocksZkVerifySign(
1611
+ const result = await cofheMocksZkVerifySign(
1628
1612
  this.inputItems,
1629
1613
  this.account,
1630
1614
  this.securityZone,
1615
+ this.consumingContract,
1631
1616
  this.publicClient,
1632
1617
  this.walletClient,
1633
1618
  this.zkvWalletClient
1634
1619
  );
1635
- const encryptedInputs = signedResults.map(({ ct_hash, signature }, index) => ({
1636
- ctHash: BigInt(ct_hash),
1637
- securityZone: this.securityZone,
1638
- utype: this.inputItems[index].utype,
1639
- signature
1640
- }));
1641
1620
  this.fireStepEnd("verify" /* Verify */, { isMocks: true, mockSleep: verifyDelay });
1642
- return encryptedInputs;
1621
+ return result;
1643
1622
  }
1644
1623
  /**
1645
1624
  * In the production context, perform a true encryption with the CoFHE coprocessor.
@@ -1647,6 +1626,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1647
1626
  async productionExecute() {
1648
1627
  this.assertAccount();
1649
1628
  this.assertChainId();
1629
+ this.assertConsumingContract();
1650
1630
  this.fireStepStart("initTfhe" /* InitTfhe */);
1651
1631
  const tfheInitializationExecuted = await this.initTfheOrThrow();
1652
1632
  this.fireStepEnd("initTfhe" /* InitTfhe */, { tfheInitializationExecuted });
@@ -1681,26 +1661,24 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1681
1661
  });
1682
1662
  this.fireStepStart("verify" /* Verify */);
1683
1663
  const zkVerifierUrl = await this.getZkVerifierUrl();
1684
- const verifyResults = await zkVerify(zkVerifierUrl, proof, this.account, this.securityZone, this.chainId);
1685
- const encryptedInputs = verifyResults.map(
1686
- ({ ct_hash, signature }, index) => ({
1687
- ctHash: BigInt(ct_hash),
1688
- securityZone: this.securityZone,
1689
- utype: this.inputItems[index].utype,
1690
- signature
1691
- })
1664
+ const result = await zkVerifyBatch(
1665
+ zkVerifierUrl,
1666
+ proof,
1667
+ this.account,
1668
+ this.securityZone,
1669
+ this.chainId,
1670
+ this.consumingContract
1692
1671
  );
1693
1672
  this.fireStepEnd("verify" /* Verify */);
1694
- return encryptedInputs;
1695
- }
1696
- structsToHashPlusProof(inItems) {
1697
- let hashes = [];
1698
- let proof = "";
1699
- for (const item of inItems) {
1700
- hashes.push("0x" + item.ctHash.toString(16).padStart(64, "0"));
1701
- proof += item.signature;
1702
- }
1703
- return [...hashes, proof];
1673
+ return result;
1674
+ }
1675
+ /**
1676
+ * Converts a batch-verified result (per-item ctHash/ctType + one shared signature) into the
1677
+ * tuple returned by `execute()`: per-item hashes in input order, followed by the single signature.
1678
+ */
1679
+ buildBatchResult(result) {
1680
+ const hashes = result.outputs.map((output) => "0x" + BigInt(output.ct_hash).toString(16).padStart(64, "0"));
1681
+ return [...hashes, result.signature];
1704
1682
  }
1705
1683
  /**
1706
1684
  * Final step of the encryption process. MUST BE CALLED LAST IN THE CHAIN.
@@ -1722,18 +1700,16 @@ var EncryptInputsBuilder = class extends BaseBuilder {
1722
1700
  * @returns The encrypted inputs.
1723
1701
  */
1724
1702
  async execute() {
1725
- let items;
1703
+ let result;
1726
1704
  if (this.chainId === chains.hardhat.id)
1727
- items = await this.mocksExecute();
1705
+ result = await this.mocksExecute();
1728
1706
  else
1729
- items = await this.productionExecute();
1730
- if (this.hpp)
1731
- return this.structsToHashPlusProof(items);
1732
- return items;
1707
+ result = await this.productionExecute();
1708
+ return this.buildBatchResult(result);
1733
1709
  }
1734
1710
  };
1735
1711
 
1736
- // permits/utils.ts
1712
+ // acps/utils.ts
1737
1713
  var fromHexString = (hexString) => {
1738
1714
  const cleanString = hexString.length % 2 === 1 ? `0${hexString}` : hexString;
1739
1715
  const arr = cleanString.replace(/^0x/, "").match(/.{1,2}/g);
@@ -1753,120 +1729,33 @@ function toBigInt(value) {
1753
1729
  return value;
1754
1730
  }
1755
1731
  }
1756
- function toBeArray(value) {
1757
- const bigIntValue = typeof value === "number" ? BigInt(value) : value;
1758
- const hex = bigIntValue.toString(16);
1759
- const paddedHex = hex.length % 2 === 0 ? hex : "0" + hex;
1760
- return fromHexString(paddedHex);
1761
- }
1762
- function isString(value) {
1763
- if (typeof value !== "string") {
1764
- throw new Error(`Expected value which is \`string\`, received value of type \`${typeof value}\`.`);
1765
- }
1766
- }
1767
- function isNumber(value) {
1768
- const is = typeof value === "number" && !Number.isNaN(value);
1769
- if (!is) {
1770
- throw new Error(`Expected value which is \`number\`, received value of type \`${typeof value}\`.`);
1771
- }
1772
- }
1773
- function isBigIntOrNumber(value) {
1774
- const is = typeof value === "bigint";
1775
- if (!is) {
1776
- try {
1777
- isNumber(value);
1778
- } catch (e) {
1779
- throw new Error(`Value ${value} is not a number or bigint: ${typeof value}`);
1780
- }
1781
- }
1782
- }
1783
1732
 
1784
- // permits/sealing.ts
1785
- var PRIVATE_KEY_LENGTH = 64;
1786
- var PUBLIC_KEY_LENGTH = 64;
1787
- var SealingKey = class _SealingKey {
1788
- /**
1789
- * The private key used for decryption.
1790
- */
1791
- privateKey;
1792
- /**
1793
- * The public key used for encryption.
1794
- */
1795
- publicKey;
1796
- /**
1797
- * Constructs a SealingKey instance with the given private and public keys.
1798
- *
1799
- * @param {string} privateKey - The private key used for decryption.
1800
- * @param {string} publicKey - The public key used for encryption.
1801
- * @throws Will throw an error if the provided keys lengths do not match
1802
- * the required lengths for private and public keys.
1803
- */
1804
- constructor(privateKey, publicKey) {
1805
- if (privateKey.length !== PRIVATE_KEY_LENGTH) {
1806
- throw new Error(`Private key must be of length ${PRIVATE_KEY_LENGTH}`);
1807
- }
1808
- if (publicKey.length !== PUBLIC_KEY_LENGTH) {
1809
- throw new Error(`Public key must be of length ${PUBLIC_KEY_LENGTH}`);
1810
- }
1811
- this.privateKey = privateKey;
1812
- this.publicKey = publicKey;
1813
- }
1814
- unseal = (parsedData) => {
1815
- const nonce = parsedData.nonce instanceof Uint8Array ? parsedData.nonce : new Uint8Array(parsedData.nonce);
1816
- const ephemPublicKey = parsedData.public_key instanceof Uint8Array ? parsedData.public_key : new Uint8Array(parsedData.public_key);
1817
- const dataToDecrypt = parsedData.data instanceof Uint8Array ? parsedData.data : new Uint8Array(parsedData.data);
1818
- const privateKeyBytes = fromHexString(this.privateKey);
1819
- const decryptedMessage = nacl__default.default.box.open(dataToDecrypt, nonce, ephemPublicKey, privateKeyBytes);
1820
- if (!decryptedMessage) {
1821
- throw new Error("Failed to decrypt message");
1822
- }
1823
- return toBigInt(decryptedMessage);
1824
- };
1825
- /**
1826
- * Serializes the SealingKey to a JSON object.
1827
- */
1828
- serialize = () => {
1829
- return {
1830
- privateKey: this.privateKey,
1831
- publicKey: this.publicKey
1832
- };
1833
- };
1834
- /**
1835
- * Deserializes the SealingKey from a JSON object.
1836
- */
1837
- static deserialize = (privateKey, publicKey) => {
1838
- return new _SealingKey(privateKey, publicKey);
1839
- };
1840
- /**
1841
- * Seals (encrypts) the provided message for a receiver with the specified public key.
1842
- *
1843
- * @param {bigint | number} value - The message to be encrypted.
1844
- * @param {string} publicKey - The public key of the intended recipient.
1845
- * @returns string - The encrypted message in hexadecimal format.
1846
- * @static
1847
- * @throws Will throw if the provided publicKey or value do not meet defined preconditions.
1848
- */
1849
- static seal = (value, publicKey) => {
1850
- isString(publicKey);
1851
- isBigIntOrNumber(value);
1852
- const ephemeralKeyPair = nacl__default.default.box.keyPair();
1853
- const nonce = nacl__default.default.randomBytes(nacl__default.default.box.nonceLength);
1854
- const encryptedMessage = nacl__default.default.box(toBeArray(value), nonce, fromHexString(publicKey), ephemeralKeyPair.secretKey);
1855
- return {
1856
- data: encryptedMessage,
1857
- public_key: ephemeralKeyPair.publicKey,
1858
- nonce
1859
- };
1860
- };
1861
- };
1733
+ // acps/sealing.ts
1734
+ var KEY_HEX_LENGTH = 64;
1862
1735
  var GenerateSealingKey = () => {
1863
1736
  const sodiumKeypair = nacl__default.default.box.keyPair();
1864
- return new SealingKey(toHexString2(sodiumKeypair.secretKey), toHexString2(sodiumKeypair.publicKey));
1737
+ return {
1738
+ privateKey: `0x${toHexString2(sodiumKeypair.secretKey)}`,
1739
+ publicKey: `0x${toHexString2(sodiumKeypair.publicKey)}`
1740
+ };
1741
+ };
1742
+ var unsealWithPrivateKey = (privateKey, parsedData) => {
1743
+ assertKeyLength(privateKey, "Private");
1744
+ const nonce = parsedData.nonce instanceof Uint8Array ? parsedData.nonce : new Uint8Array(parsedData.nonce);
1745
+ const ephemPublicKey = parsedData.public_key instanceof Uint8Array ? parsedData.public_key : new Uint8Array(parsedData.public_key);
1746
+ const dataToDecrypt = parsedData.data instanceof Uint8Array ? parsedData.data : new Uint8Array(parsedData.data);
1747
+ const decryptedMessage = nacl__default.default.box.open(dataToDecrypt, nonce, ephemPublicKey, fromHexString(privateKey));
1748
+ if (!decryptedMessage) {
1749
+ throw new Error("Failed to decrypt message");
1750
+ }
1751
+ return toBigInt(decryptedMessage);
1752
+ };
1753
+ var assertKeyLength = (key, kind) => {
1754
+ const bare = key.startsWith("0x") ? key.slice(2) : key;
1755
+ if (bare.length !== KEY_HEX_LENGTH) {
1756
+ throw new Error(`${kind} key must be of length ${KEY_HEX_LENGTH}`);
1757
+ }
1865
1758
  };
1866
- var SerializedSealingPair = zod.z.object({
1867
- privateKey: zod.z.string(),
1868
- publicKey: zod.z.string()
1869
- });
1870
1759
  var addressSchema = zod.z.string().refine((val) => viem.isAddress(val), {
1871
1760
  error: "Invalid address"
1872
1761
  }).transform((val) => viem.getAddress(val));
@@ -1885,46 +1774,70 @@ var bytesNotEmptySchema = bytesSchema.refine((val) => val !== "0x", {
1885
1774
  error: "Must not be empty"
1886
1775
  });
1887
1776
  var DEFAULT_EXPIRATION_FN = () => Math.round(Date.now() / 1e3) + 7 * 24 * 60 * 60;
1888
- var zPermitWithDefaults = zod.z.object({
1889
- name: zod.z.string().optional().default("Unnamed Permit"),
1777
+ var handlesSchema = zod.z.array(zod.z.string().regex(/^0x[0-9a-fA-F]{64}$/, "Invalid handle: expected 32-byte hex")).optional().default([]);
1778
+ var contractsSchema = zod.z.array(addressSchema).optional().default([]);
1779
+ var SCOPE_GLOBAL = 0;
1780
+ var SCOPE_CONTRACT = 1;
1781
+ var SCOPE_HANDLES = 2;
1782
+ var ScopeConsistencyRefinement = [
1783
+ (data) => data.scope === SCOPE_GLOBAL && data.contracts.length === 0 && data.handles.length === 0 || data.scope === SCOPE_CONTRACT && data.contracts.length > 0 && data.handles.length === 0 || data.scope === SCOPE_HANDLES && data.handles.length > 0 && data.contracts.length === 0,
1784
+ {
1785
+ error: "ACP scope :: arrays must match the scope mode (Global: both empty; Contract: contracts only; Handles: handles only)",
1786
+ path: ["scope"]
1787
+ }
1788
+ ];
1789
+ var withDerivedScope = (data) => ({
1790
+ ...data,
1791
+ scope: data.scope ?? (data.contracts.length > 0 ? SCOPE_CONTRACT : data.handles.length > 0 ? SCOPE_HANDLES : SCOPE_GLOBAL)
1792
+ });
1793
+ var zACPWithDefaults = zod.z.object({
1794
+ name: zod.z.string().optional().default("Unnamed ACP"),
1890
1795
  type: zod.z.enum(["self", "sharing", "recipient"]),
1891
1796
  issuer: addressNotZeroSchema,
1892
1797
  expiration: zod.z.int().optional().default(DEFAULT_EXPIRATION_FN),
1893
1798
  recipient: addressSchema.optional().default(viem.zeroAddress),
1894
- validatorId: zod.z.int().optional().default(0),
1895
- validatorContract: addressSchema.optional().default(viem.zeroAddress),
1799
+ revokerData: zod.z.int().optional().default(0),
1800
+ revokerContract: addressSchema.optional().default(viem.zeroAddress),
1801
+ scope: zod.z.int().min(0).max(2).optional().default(0),
1802
+ contracts: contractsSchema,
1803
+ handles: handlesSchema,
1896
1804
  issuerSignature: bytesSchema.optional().default("0x"),
1897
1805
  recipientSignature: bytesSchema.optional().default("0x")
1898
1806
  });
1899
- var zPermitWithSealingPair = zPermitWithDefaults.extend({
1900
- sealingPair: SerializedSealingPair.optional()
1807
+ var zACPWithSealingKeys = zACPWithDefaults.extend({
1808
+ /** X25519 private key, 0x-prefixed 32-byte hex; never leaves the client */
1809
+ sealingPrivateKey: zod.z.string().regex(/^0x[0-9a-fA-F]{64}$/, "Invalid sealing private key").optional(),
1810
+ sealingKey: zod.z.string().regex(/^0x[0-9a-fA-F]{64}$/, "Invalid sealing key").optional()
1901
1811
  });
1902
1812
  var ExternalValidatorRefinement = [
1903
- (data) => data.validatorId !== 0 && data.validatorContract !== viem.zeroAddress || data.validatorId === 0 && data.validatorContract === viem.zeroAddress,
1813
+ (data) => data.revokerData !== 0 && data.revokerContract !== viem.zeroAddress || data.revokerData === 0 && data.revokerContract === viem.zeroAddress,
1904
1814
  {
1905
- error: "Permit external validator :: validatorId and validatorContract must either both be set or both be unset.",
1906
- path: ["validatorId", "validatorContract"]
1815
+ error: "ACP external revoker :: revokerData and revokerContract must either both be set or both be unset.",
1816
+ path: ["revokerData", "revokerContract"]
1907
1817
  }
1908
1818
  ];
1909
1819
  var RecipientRefinement = [
1910
1820
  (data) => data.issuer !== data.recipient,
1911
1821
  {
1912
- error: "Sharing permit :: issuer and recipient must not be the same",
1822
+ error: "Sharing acp :: issuer and recipient must not be the same",
1913
1823
  path: ["issuer", "recipient"]
1914
1824
  }
1915
1825
  ];
1916
- var SelfPermitOptionsValidator = zod.z.object({
1826
+ var SelfACPOptionsValidator = zod.z.object({
1917
1827
  type: zod.z.literal("self").optional().default("self"),
1918
1828
  issuer: addressNotZeroSchema,
1919
- name: zod.z.string().optional().default("Unnamed Permit"),
1829
+ name: zod.z.string().optional().default("Unnamed ACP"),
1920
1830
  expiration: zod.z.int().optional().default(DEFAULT_EXPIRATION_FN),
1921
1831
  recipient: addressSchema.optional().default(viem.zeroAddress),
1922
- validatorId: zod.z.int().optional().default(0),
1923
- validatorContract: addressSchema.optional().default(viem.zeroAddress),
1832
+ revokerData: zod.z.int().optional().default(0),
1833
+ revokerContract: addressSchema.optional().default(viem.zeroAddress),
1834
+ scope: zod.z.int().min(0).max(2).optional(),
1835
+ contracts: contractsSchema,
1836
+ handles: handlesSchema,
1924
1837
  issuerSignature: bytesSchema.optional().default("0x"),
1925
1838
  recipientSignature: bytesSchema.optional().default("0x")
1926
- }).refine(...ExternalValidatorRefinement);
1927
- var SelfPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "self", {
1839
+ }).refine(...ExternalValidatorRefinement).transform(withDerivedScope).refine(...ScopeConsistencyRefinement);
1840
+ var SelfACPValidator = zACPWithSealingKeys.refine((data) => data.type === "self", {
1928
1841
  error: "Type must be 'self'"
1929
1842
  }).refine((data) => data.recipient === viem.zeroAddress, {
1930
1843
  error: "Recipient must be zeroAddress"
@@ -1933,18 +1846,21 @@ var SelfPermitValidator = zPermitWithSealingPair.refine((data) => data.type ===
1933
1846
  }).refine((data) => data.recipientSignature === "0x", {
1934
1847
  error: "RecipientSignature must be empty"
1935
1848
  }).refine(...ExternalValidatorRefinement);
1936
- var SharingPermitOptionsValidator = zod.z.object({
1849
+ var SharingACPOptionsValidator = zod.z.object({
1937
1850
  type: zod.z.literal("sharing").optional().default("sharing"),
1938
1851
  issuer: addressNotZeroSchema,
1939
1852
  recipient: addressNotZeroSchema,
1940
- name: zod.z.string().optional().default("Unnamed Permit"),
1853
+ name: zod.z.string().optional().default("Unnamed ACP"),
1941
1854
  expiration: zod.z.int().optional().default(DEFAULT_EXPIRATION_FN),
1942
- validatorId: zod.z.int().optional().default(0),
1943
- validatorContract: addressSchema.optional().default(viem.zeroAddress),
1855
+ revokerData: zod.z.int().optional().default(0),
1856
+ revokerContract: addressSchema.optional().default(viem.zeroAddress),
1857
+ scope: zod.z.int().min(0).max(2).optional(),
1858
+ contracts: contractsSchema,
1859
+ handles: handlesSchema,
1944
1860
  issuerSignature: bytesSchema.optional().default("0x"),
1945
1861
  recipientSignature: bytesSchema.optional().default("0x")
1946
- }).refine(...RecipientRefinement).refine(...ExternalValidatorRefinement);
1947
- var SharingPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "sharing", {
1862
+ }).refine(...RecipientRefinement).refine(...ExternalValidatorRefinement).transform(withDerivedScope).refine(...ScopeConsistencyRefinement);
1863
+ var SharingACPValidator = zACPWithSealingKeys.refine((data) => data.type === "sharing", {
1948
1864
  error: "Type must be 'sharing'"
1949
1865
  }).refine((data) => data.recipient !== viem.zeroAddress, {
1950
1866
  error: "Recipient must not be zeroAddress"
@@ -1953,18 +1869,21 @@ var SharingPermitValidator = zPermitWithSealingPair.refine((data) => data.type =
1953
1869
  }).refine((data) => data.recipientSignature === "0x", {
1954
1870
  error: "RecipientSignature must be empty"
1955
1871
  }).refine(...ExternalValidatorRefinement);
1956
- var ImportPermitOptionsValidator = zod.z.object({
1872
+ var ImportACPOptionsValidator = zod.z.object({
1957
1873
  type: zod.z.literal("recipient").optional().default("recipient"),
1958
1874
  issuer: addressNotZeroSchema,
1959
1875
  recipient: addressNotZeroSchema,
1960
- name: zod.z.string().optional().default("Unnamed Permit"),
1876
+ name: zod.z.string().optional().default("Unnamed ACP"),
1961
1877
  expiration: zod.z.int(),
1962
- validatorId: zod.z.int().optional().default(0),
1963
- validatorContract: addressSchema.optional().default(viem.zeroAddress),
1878
+ revokerData: zod.z.int().optional().default(0),
1879
+ revokerContract: addressSchema.optional().default(viem.zeroAddress),
1880
+ scope: zod.z.int().min(0).max(2).optional(),
1881
+ contracts: contractsSchema,
1882
+ handles: handlesSchema,
1964
1883
  issuerSignature: bytesNotEmptySchema,
1965
1884
  recipientSignature: bytesSchema.optional().default("0x")
1966
- }).refine(...ExternalValidatorRefinement);
1967
- var ImportPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "recipient", {
1885
+ }).refine(...ExternalValidatorRefinement).transform(withDerivedScope).refine(...ScopeConsistencyRefinement);
1886
+ var ImportACPValidator = zACPWithSealingKeys.refine((data) => data.type === "recipient", {
1968
1887
  error: "Type must be 'recipient'"
1969
1888
  }).refine((data) => data.recipient !== viem.zeroAddress, {
1970
1889
  error: "Recipient must not be zeroAddress"
@@ -1980,116 +1899,125 @@ var safeParseAndThrowFormatted = (schema, data, message) => {
1980
1899
  }
1981
1900
  return result.data;
1982
1901
  };
1983
- var validateSelfPermitOptions = (options) => {
1984
- return safeParseAndThrowFormatted(SelfPermitOptionsValidator, options, "Invalid self permit options");
1902
+ var validateSelfACPOptions = (options) => {
1903
+ return safeParseAndThrowFormatted(SelfACPOptionsValidator, options, "Invalid self acp options");
1985
1904
  };
1986
- var validateSharingPermitOptions = (options) => {
1987
- return safeParseAndThrowFormatted(SharingPermitOptionsValidator, options, "Invalid sharing permit options");
1905
+ var validateSharingACPOptions = (options) => {
1906
+ return safeParseAndThrowFormatted(SharingACPOptionsValidator, options, "Invalid sharing acp options");
1988
1907
  };
1989
- var validateImportPermitOptions = (options) => {
1990
- return safeParseAndThrowFormatted(ImportPermitOptionsValidator, options, "Invalid import permit options");
1908
+ var validateImportACPOptions = (options) => {
1909
+ return safeParseAndThrowFormatted(ImportACPOptionsValidator, options, "Invalid import acp options");
1991
1910
  };
1992
- var validateSelfPermit = (permit) => {
1993
- return safeParseAndThrowFormatted(SelfPermitValidator, permit, "Invalid self permit");
1911
+ var validateSelfACP = (acp) => {
1912
+ return safeParseAndThrowFormatted(SelfACPValidator, acp, "Invalid self acp");
1994
1913
  };
1995
- var validateSharingPermit = (permit) => {
1996
- return safeParseAndThrowFormatted(SharingPermitValidator, permit, "Invalid sharing permit");
1914
+ var validateSharingACP = (acp) => {
1915
+ return safeParseAndThrowFormatted(SharingACPValidator, acp, "Invalid sharing acp");
1997
1916
  };
1998
- var validateImportPermit = (permit) => {
1999
- return safeParseAndThrowFormatted(ImportPermitValidator, permit, "Invalid import permit");
1917
+ var validateImportACP = (acp) => {
1918
+ return safeParseAndThrowFormatted(ImportACPValidator, acp, "Invalid import acp");
2000
1919
  };
2001
1920
  var ValidationUtils = {
2002
1921
  /**
2003
- * Check if permit is expired
1922
+ * Check if acp is expired
2004
1923
  */
2005
- isExpired: (permit) => {
2006
- return permit.expiration < Math.floor(Date.now() / 1e3);
1924
+ isExpired: (acp) => {
1925
+ return acp.expiration < Math.floor(Date.now() / 1e3);
2007
1926
  },
2008
1927
  /**
2009
- * Check if permit is signed by the active party
1928
+ * Check if acp is signed by the active party
2010
1929
  */
2011
- isSigned: (permit) => {
2012
- if (permit.type === "self" || permit.type === "sharing") {
2013
- return permit.issuerSignature !== "0x";
1930
+ isSigned: (acp) => {
1931
+ if (acp.type === "self" || acp.type === "sharing") {
1932
+ return acp.issuerSignature !== "0x";
2014
1933
  }
2015
- if (permit.type === "recipient") {
2016
- return permit.recipientSignature !== "0x";
1934
+ if (acp.type === "recipient") {
1935
+ return acp.recipientSignature !== "0x";
2017
1936
  }
2018
1937
  return false;
2019
1938
  },
2020
1939
  /**
2021
- * Checks that a permit is signed and not expired.
1940
+ * Checks that an ACP is signed and not expired.
2022
1941
  */
2023
- isSignedAndNotExpired: (permit) => {
2024
- if (ValidationUtils.isExpired(permit)) {
1942
+ isSignedAndNotExpired: (acp) => {
1943
+ if (ValidationUtils.isExpired(acp)) {
2025
1944
  return { valid: false, error: "expired" };
2026
1945
  }
2027
- if (!ValidationUtils.isSigned(permit)) {
1946
+ if (!ValidationUtils.isSigned(acp)) {
2028
1947
  return { valid: false, error: "not-signed" };
2029
1948
  }
2030
1949
  return { valid: true, error: null };
2031
1950
  },
2032
1951
  /**
2033
- * Asserts that a permit is signed and not expired.
1952
+ * Asserts that an ACP is signed and not expired.
2034
1953
  *
2035
1954
  * Throws `Error` with message:
2036
- * - `Permit is expired`
2037
- * - `Permit is not signed`
1955
+ * - `ACP is expired`
1956
+ * - `ACP is not signed`
2038
1957
  */
2039
- assertSignedAndNotExpired: (permit) => {
2040
- const result = ValidationUtils.isSignedAndNotExpired(permit);
1958
+ assertSignedAndNotExpired: (acp) => {
1959
+ const result = ValidationUtils.isSignedAndNotExpired(acp);
2041
1960
  if (result.valid)
2042
1961
  return;
2043
1962
  if (result.error === "expired") {
2044
- throw new Error("Permit is expired");
1963
+ throw new Error("ACP is expired");
2045
1964
  }
2046
1965
  if (result.error === "not-signed") {
2047
- throw new Error("Permit is not signed");
1966
+ throw new Error("ACP is not signed");
2048
1967
  }
2049
- throw new Error("Permit is invalid");
1968
+ throw new Error("ACP is invalid");
2050
1969
  },
2051
- isValid: (permit) => {
2052
- const schema = permit.type === "self" ? SelfPermitValidator : permit.type === "sharing" ? SharingPermitValidator : permit.type === "recipient" ? ImportPermitValidator : null;
1970
+ isValid: (acp) => {
1971
+ const schema = acp.type === "self" ? SelfACPValidator : acp.type === "sharing" ? SharingACPValidator : acp.type === "recipient" ? ImportACPValidator : null;
2053
1972
  if (schema == null)
2054
1973
  return { valid: false, error: "invalid-schema" };
2055
- const schemaResult = schema.safeParse(permit);
1974
+ const schemaResult = schema.safeParse(acp);
2056
1975
  if (!schemaResult.success)
2057
1976
  return { valid: false, error: "invalid-schema" };
2058
- return ValidationUtils.isSignedAndNotExpired(permit);
1977
+ return ValidationUtils.isSignedAndNotExpired(acp);
2059
1978
  }
2060
1979
  };
2061
1980
 
2062
- // permits/signature.ts
2063
- var PermitSignatureAllFields = [
1981
+ // acps/signature.ts
1982
+ var ACPSignatureAllFields = [
2064
1983
  { name: "issuer", type: "address" },
2065
1984
  { name: "expiration", type: "uint64" },
2066
1985
  { name: "recipient", type: "address" },
2067
- { name: "validatorId", type: "uint256" },
2068
- { name: "validatorContract", type: "address" },
1986
+ { name: "revokerData", type: "uint256" },
1987
+ { name: "revokerContract", type: "address" },
1988
+ { name: "scope", type: "uint8" },
1989
+ { name: "contracts", type: "address[]" },
1990
+ { name: "handles", type: "bytes32[]" },
2069
1991
  { name: "sealingKey", type: "bytes32" },
2070
1992
  { name: "issuerSignature", type: "bytes" }
2071
1993
  ];
2072
1994
  var SignatureTypes = {
2073
- PermissionedV2IssuerSelf: [
1995
+ ACPIssuerSelf: [
2074
1996
  "issuer",
2075
1997
  "expiration",
2076
1998
  "recipient",
2077
- "validatorId",
2078
- "validatorContract",
1999
+ "revokerData",
2000
+ "revokerContract",
2001
+ "scope",
2002
+ "contracts",
2003
+ "handles",
2079
2004
  "sealingKey"
2080
2005
  ],
2081
- PermissionedV2IssuerShared: [
2006
+ ACPIssuerShared: [
2082
2007
  "issuer",
2083
2008
  "expiration",
2084
2009
  "recipient",
2085
- "validatorId",
2086
- "validatorContract"
2010
+ "revokerData",
2011
+ "revokerContract",
2012
+ "scope",
2013
+ "contracts",
2014
+ "handles"
2087
2015
  ],
2088
- PermissionedV2Recipient: ["sealingKey", "issuerSignature"]
2016
+ ACPRecipient: ["sealingKey", "issuerSignature"]
2089
2017
  };
2090
2018
  var getSignatureTypesAndMessage = (primaryType, fields, values) => {
2091
2019
  const types = {
2092
- [primaryType]: PermitSignatureAllFields.filter((fieldType) => fields.includes(fieldType.name))
2020
+ [primaryType]: ACPSignatureAllFields.filter((fieldType) => fields.includes(fieldType.name))
2093
2021
  };
2094
2022
  const message = {};
2095
2023
  fields.forEach((field) => {
@@ -2101,22 +2029,22 @@ var getSignatureTypesAndMessage = (primaryType, fields, values) => {
2101
2029
  };
2102
2030
  var SignatureUtils = {
2103
2031
  /**
2104
- * Get signature parameters for a permit
2032
+ * Get signature parameters for an ACP
2105
2033
  */
2106
- getSignatureParams: (permit, primaryType) => {
2107
- return getSignatureTypesAndMessage(primaryType, SignatureTypes[primaryType], permit);
2034
+ getSignatureParams: (acp, primaryType) => {
2035
+ return getSignatureTypesAndMessage(primaryType, SignatureTypes[primaryType], acp);
2108
2036
  },
2109
2037
  /**
2110
- * Determine the required signature type based on permit type
2038
+ * Determine the required signature type based on acp type
2111
2039
  */
2112
- getPrimaryType: (permitType) => {
2113
- if (permitType === "self")
2114
- return "PermissionedV2IssuerSelf";
2115
- if (permitType === "sharing")
2116
- return "PermissionedV2IssuerShared";
2117
- if (permitType === "recipient")
2118
- return "PermissionedV2Recipient";
2119
- throw new Error(`Unknown permit type: ${permitType}`);
2040
+ getPrimaryType: (acpType) => {
2041
+ if (acpType === "self")
2042
+ return "ACPIssuerSelf";
2043
+ if (acpType === "sharing")
2044
+ return "ACPIssuerShared";
2045
+ if (acpType === "recipient")
2046
+ return "ACPRecipient";
2047
+ throw new Error(`Unknown acp type: ${acpType}`);
2120
2048
  }
2121
2049
  };
2122
2050
  var getAclAddress = async (publicClient) => {
@@ -2138,6 +2066,11 @@ var getAclEIP712Domain = async (publicClient) => {
2138
2066
  functionName: "eip712Domain"
2139
2067
  });
2140
2068
  const [_fields, name, version, chainId, verifyingContract, _salt, _extensions] = domain;
2069
+ if (version !== "2") {
2070
+ throw new Error(
2071
+ `Chain ${chainId}'s ACL serves EIP-712 domain version "${version}" \u2014 this SDK requires the upgraded (ACP-era) ACL, which signs as version "2". Pre-upgrade (V2 Permission) chains are not supported.`
2072
+ );
2073
+ }
2141
2074
  return {
2142
2075
  name,
2143
2076
  version,
@@ -2145,23 +2078,26 @@ var getAclEIP712Domain = async (publicClient) => {
2145
2078
  verifyingContract
2146
2079
  };
2147
2080
  };
2148
- var checkPermitValidityOnChain = async (permission, publicClient) => {
2081
+ var checkACPValidityOnChain = async (acp, publicClient) => {
2149
2082
  const aclAddress = await getAclAddress(publicClient);
2150
2083
  try {
2151
2084
  await publicClient.simulateContract({
2152
2085
  address: aclAddress,
2153
- abi: checkPermitValidityAbi,
2154
- functionName: "checkPermitValidity",
2086
+ abi: checkACPValidityAbi,
2087
+ functionName: "checkPermissionValidity",
2155
2088
  args: [
2156
2089
  {
2157
- issuer: permission.issuer,
2158
- expiration: BigInt(permission.expiration),
2159
- recipient: permission.recipient,
2160
- validatorId: BigInt(permission.validatorId),
2161
- validatorContract: permission.validatorContract,
2162
- sealingKey: permission.sealingKey,
2163
- issuerSignature: permission.issuerSignature,
2164
- recipientSignature: permission.recipientSignature
2090
+ issuer: acp.issuer,
2091
+ expiration: BigInt(acp.expiration),
2092
+ recipient: acp.recipient,
2093
+ revokerData: BigInt(acp.revokerData),
2094
+ revokerContract: acp.revokerContract,
2095
+ scope: acp.scope,
2096
+ contracts: acp.contracts,
2097
+ handles: acp.handles,
2098
+ sealingKey: acp.sealingKey,
2099
+ issuerSignature: acp.issuerSignature,
2100
+ recipientSignature: acp.recipientSignature
2165
2101
  }
2166
2102
  ]
2167
2103
  });
@@ -2174,14 +2110,14 @@ var checkPermitValidityOnChain = async (permission, publicClient) => {
2174
2110
  throw new Error(errorName);
2175
2111
  }
2176
2112
  }
2177
- const customErrorName = extractCustomErrorFromDetails(err, checkPermitValidityAbi);
2113
+ const customErrorName = extractCustomErrorFromDetails(err, checkACPValidityAbi);
2178
2114
  if (customErrorName) {
2179
2115
  throw new Error(customErrorName);
2180
2116
  }
2181
2117
  const hhDetailsData = extractReturnData(err);
2182
2118
  if (hhDetailsData != null) {
2183
2119
  const decoded = viem.decodeErrorResult({
2184
- abi: checkPermitValidityAbi,
2120
+ abi: checkACPValidityAbi,
2185
2121
  data: hhDetailsData
2186
2122
  });
2187
2123
  throw new Error(decoded.errorName);
@@ -2209,15 +2145,15 @@ function extractReturnData(err) {
2209
2145
  const s = anyErr?.details ?? anyErr?.cause?.details ?? anyErr?.shortMessage ?? anyErr?.message ?? String(err);
2210
2146
  return s.match(/return data:\s*(0x[a-fA-F0-9]+)/)?.[1];
2211
2147
  }
2212
- var checkPermitValidityAbi = [
2148
+ var checkACPValidityAbi = [
2213
2149
  {
2214
2150
  type: "function",
2215
- name: "checkPermitValidity",
2151
+ name: "checkPermissionValidity",
2216
2152
  inputs: [
2217
2153
  {
2218
- name: "permission",
2154
+ name: "acp",
2219
2155
  type: "tuple",
2220
- internalType: "struct Permission",
2156
+ internalType: "struct ACP",
2221
2157
  components: [
2222
2158
  {
2223
2159
  name: "issuer",
@@ -2235,15 +2171,30 @@ var checkPermitValidityAbi = [
2235
2171
  internalType: "address"
2236
2172
  },
2237
2173
  {
2238
- name: "validatorId",
2174
+ name: "revokerData",
2239
2175
  type: "uint256",
2240
2176
  internalType: "uint256"
2241
2177
  },
2242
2178
  {
2243
- name: "validatorContract",
2179
+ name: "revokerContract",
2244
2180
  type: "address",
2245
2181
  internalType: "address"
2246
2182
  },
2183
+ {
2184
+ name: "scope",
2185
+ type: "uint8",
2186
+ internalType: "uint8"
2187
+ },
2188
+ {
2189
+ name: "contracts",
2190
+ type: "address[]",
2191
+ internalType: "address[]"
2192
+ },
2193
+ {
2194
+ name: "handles",
2195
+ type: "bytes32[]",
2196
+ internalType: "bytes32[]"
2197
+ },
2247
2198
  {
2248
2199
  name: "sealingKey",
2249
2200
  type: "bytes32",
@@ -2293,38 +2244,40 @@ var checkPermitValidityAbi = [
2293
2244
  }
2294
2245
  ];
2295
2246
 
2296
- // permits/permit.ts
2297
- var PermitUtils = {
2247
+ // acps/acp.ts
2248
+ var ACPUtils = {
2298
2249
  /**
2299
- * Create a self permit for personal use
2250
+ * Create a self acp for personal use
2300
2251
  */
2301
2252
  createSelf: (options) => {
2302
- const validation = validateSelfPermitOptions(options);
2253
+ const validation = validateSelfACPOptions(options);
2303
2254
  const sealingPair = GenerateSealingKey();
2304
- const permit = {
2305
- hash: PermitUtils.getHash(validation),
2255
+ const acp = {
2256
+ hash: ACPUtils.getHash(validation),
2306
2257
  ...validation,
2307
- sealingPair,
2258
+ sealingPrivateKey: sealingPair.privateKey,
2259
+ sealingKey: sealingPair.publicKey,
2308
2260
  _signedDomain: void 0
2309
2261
  };
2310
- return permit;
2262
+ return acp;
2311
2263
  },
2312
2264
  /**
2313
- * Create a sharing permit to be shared with another user
2265
+ * Create a sharing acp to be shared with another user
2314
2266
  */
2315
2267
  createSharing: (options) => {
2316
- const validation = validateSharingPermitOptions(options);
2268
+ const validation = validateSharingACPOptions(options);
2317
2269
  const sealingPair = GenerateSealingKey();
2318
- const permit = {
2319
- hash: PermitUtils.getHash(validation),
2270
+ const acp = {
2271
+ hash: ACPUtils.getHash(validation),
2320
2272
  ...validation,
2321
- sealingPair,
2273
+ sealingPrivateKey: sealingPair.privateKey,
2274
+ sealingKey: sealingPair.publicKey,
2322
2275
  _signedDomain: void 0
2323
2276
  };
2324
- return permit;
2277
+ return acp;
2325
2278
  },
2326
2279
  /**
2327
- * Import a shared permit from various input formats
2280
+ * Import a shared acp from various input formats
2328
2281
  */
2329
2282
  importShared: (options) => {
2330
2283
  let parsedOptions;
@@ -2337,33 +2290,34 @@ var PermitUtils = {
2337
2290
  } else if (typeof options === "object" && options !== null) {
2338
2291
  parsedOptions = options;
2339
2292
  } else {
2340
- throw new Error("Invalid input type, expected ImportSharedPermitOptions, object, or string");
2293
+ throw new Error("Invalid input type, expected ImportSharedACPOptions, object, or string");
2341
2294
  }
2342
2295
  if (parsedOptions.type != null && parsedOptions.type !== "sharing") {
2343
- throw new Error(`Invalid permit type <${parsedOptions.type}>, must be "sharing"`);
2296
+ throw new Error(`Invalid acp type <${parsedOptions.type}>, must be "sharing"`);
2344
2297
  }
2345
- const validation = validateImportPermitOptions({ ...parsedOptions, type: "recipient" });
2298
+ const validation = validateImportACPOptions({ ...parsedOptions, type: "recipient" });
2346
2299
  const sealingPair = GenerateSealingKey();
2347
- const permit = {
2348
- hash: PermitUtils.getHash(validation),
2300
+ const acp = {
2301
+ hash: ACPUtils.getHash(validation),
2349
2302
  ...validation,
2350
- sealingPair,
2303
+ sealingPrivateKey: sealingPair.privateKey,
2304
+ sealingKey: sealingPair.publicKey,
2351
2305
  _signedDomain: void 0
2352
2306
  };
2353
- return permit;
2307
+ return acp;
2354
2308
  },
2355
2309
  /**
2356
- * Sign a permit with the provided wallet client
2310
+ * Sign an ACP with the provided wallet client
2357
2311
  */
2358
- sign: async (permit, publicClient, walletClient) => {
2312
+ sign: async (acp, publicClient, walletClient) => {
2359
2313
  if (walletClient == null || walletClient.account == null) {
2360
2314
  throw new Error(
2361
- "Missing walletClient, you must pass in a `walletClient` for the connected user to create a permit signature"
2315
+ "Missing walletClient, you must pass in a `walletClient` for the connected user to create an ACP signature"
2362
2316
  );
2363
2317
  }
2364
- const primaryType = SignatureUtils.getPrimaryType(permit.type);
2318
+ const primaryType = SignatureUtils.getPrimaryType(acp.type);
2365
2319
  const domain = await getAclEIP712Domain(publicClient);
2366
- const { types, message } = SignatureUtils.getSignatureParams(PermitUtils.getPermission(permit, true), primaryType);
2320
+ const { types, message } = SignatureUtils.getSignatureParams(ACPUtils.getPublic(acp, true), primaryType);
2367
2321
  const signature = await walletClient.signTypedData({
2368
2322
  domain,
2369
2323
  types,
@@ -2371,190 +2325,209 @@ var PermitUtils = {
2371
2325
  message,
2372
2326
  account: walletClient.account
2373
2327
  });
2374
- let updatedPermit;
2375
- if (permit.type === "self" || permit.type === "sharing") {
2376
- updatedPermit = {
2377
- ...permit,
2328
+ let updatedACP;
2329
+ if (acp.type === "self" || acp.type === "sharing") {
2330
+ updatedACP = {
2331
+ ...acp,
2378
2332
  issuerSignature: signature,
2379
2333
  _signedDomain: domain
2380
2334
  };
2381
2335
  } else {
2382
- updatedPermit = {
2383
- ...permit,
2336
+ updatedACP = {
2337
+ ...acp,
2384
2338
  recipientSignature: signature,
2385
2339
  _signedDomain: domain
2386
2340
  };
2387
2341
  }
2388
- return updatedPermit;
2342
+ return updatedACP;
2389
2343
  },
2390
2344
  /**
2391
- * Create and sign a self permit in one operation
2345
+ * Create and sign a self acp in one operation
2392
2346
  */
2393
2347
  createSelfAndSign: async (options, publicClient, walletClient) => {
2394
- const permit = PermitUtils.createSelf(options);
2395
- return PermitUtils.sign(permit, publicClient, walletClient);
2348
+ const acp = ACPUtils.createSelf(options);
2349
+ return ACPUtils.sign(acp, publicClient, walletClient);
2396
2350
  },
2397
2351
  /**
2398
- * Create and sign a sharing permit in one operation
2352
+ * Create and sign a sharing acp in one operation
2399
2353
  */
2400
2354
  createSharingAndSign: async (options, publicClient, walletClient) => {
2401
- const permit = PermitUtils.createSharing(options);
2402
- return PermitUtils.sign(permit, publicClient, walletClient);
2355
+ const acp = ACPUtils.createSharing(options);
2356
+ return ACPUtils.sign(acp, publicClient, walletClient);
2403
2357
  },
2404
2358
  /**
2405
- * Import and sign a shared permit in one operation from various input formats
2359
+ * Import and sign a shared acp in one operation from various input formats
2406
2360
  */
2407
2361
  importSharedAndSign: async (options, publicClient, walletClient) => {
2408
- const permit = PermitUtils.importShared(options);
2409
- return PermitUtils.sign(permit, publicClient, walletClient);
2362
+ const acp = ACPUtils.importShared(options);
2363
+ return ACPUtils.sign(acp, publicClient, walletClient);
2410
2364
  },
2411
2365
  /**
2412
- * Deserialize a permit from serialized data
2366
+ * Deserialize an ACP from serialized data
2413
2367
  */
2414
2368
  deserialize: (data) => {
2415
- return {
2416
- ...data,
2417
- sealingPair: SealingKey.deserialize(data.sealingPair.privateKey, data.sealingPair.publicKey)
2418
- };
2369
+ return { ...data };
2419
2370
  },
2420
2371
  /**
2421
- * Serialize a permit for storage
2372
+ * Serialize an ACP for storage
2422
2373
  */
2423
- serialize: (permit) => {
2374
+ serialize: (acp) => {
2424
2375
  return {
2425
- hash: permit.hash,
2426
- name: permit.name,
2427
- type: permit.type,
2428
- issuer: permit.issuer,
2429
- expiration: permit.expiration,
2430
- recipient: permit.recipient,
2431
- validatorId: permit.validatorId,
2432
- validatorContract: permit.validatorContract,
2433
- issuerSignature: permit.issuerSignature,
2434
- recipientSignature: permit.recipientSignature,
2435
- _signedDomain: permit._signedDomain,
2436
- sealingPair: permit.sealingPair.serialize()
2376
+ hash: acp.hash,
2377
+ name: acp.name,
2378
+ type: acp.type,
2379
+ issuer: acp.issuer,
2380
+ expiration: acp.expiration,
2381
+ recipient: acp.recipient,
2382
+ revokerData: acp.revokerData,
2383
+ revokerContract: acp.revokerContract,
2384
+ scope: acp.scope,
2385
+ contracts: acp.contracts,
2386
+ handles: acp.handles,
2387
+ sealingKey: acp.sealingKey,
2388
+ issuerSignature: acp.issuerSignature,
2389
+ recipientSignature: acp.recipientSignature,
2390
+ _signedDomain: acp._signedDomain,
2391
+ sealingPrivateKey: acp.sealingPrivateKey
2437
2392
  };
2438
2393
  },
2439
2394
  /**
2440
- * Validate a permit (schema-level validation)
2395
+ * Validate an ACP (schema-level validation)
2441
2396
  */
2442
- validateSchema: (permit) => {
2443
- if (permit.type === "self") {
2444
- return validateSelfPermit(permit);
2445
- } else if (permit.type === "sharing") {
2446
- return validateSharingPermit(permit);
2447
- } else if (permit.type === "recipient") {
2448
- return validateImportPermit(permit);
2397
+ validateSchema: (acp) => {
2398
+ if (acp.type === "self") {
2399
+ return validateSelfACP(acp);
2400
+ } else if (acp.type === "sharing") {
2401
+ return validateSharingACP(acp);
2402
+ } else if (acp.type === "recipient") {
2403
+ return validateImportACP(acp);
2449
2404
  } else {
2450
- throw new Error("Invalid permit type");
2405
+ throw new Error("Invalid ACP type");
2451
2406
  }
2452
2407
  },
2453
2408
  /**
2454
- * Validate a permit (holistic validation).
2409
+ * Validate an ACP (holistic validation).
2455
2410
  *
2456
2411
  * This validates:
2457
- * - Permit schema (shape + invariants)
2458
- * - Permit is signed
2459
- * - Permit is not expired
2412
+ * - ACP schema (shape + invariants)
2413
+ * - ACP is signed
2414
+ * - ACP is not expired
2460
2415
  *
2461
- * For schema-only validation, use `validateSchema(permit)`.
2416
+ * For schema-only validation, use `validateSchema(acp)`.
2462
2417
  */
2463
- validate: (permit) => {
2464
- const validated = PermitUtils.validateSchema(permit);
2418
+ validate: (acp) => {
2419
+ const validated = ACPUtils.validateSchema(acp);
2465
2420
  ValidationUtils.assertSignedAndNotExpired(validated);
2466
2421
  return validated;
2467
2422
  },
2468
2423
  /**
2469
- * Get the permission object from a permit (for use in contracts)
2424
+ * Get the public component of an ACP the signed struct sent on-chain / to the decryption backend.
2425
+ * Strips the private component (hash, name, type, sealing pair).
2470
2426
  */
2471
- getPermission: (permit, skipValidation = false) => {
2427
+ getPublic: (acp, skipValidation = false) => {
2472
2428
  if (!skipValidation) {
2473
- PermitUtils.validateSchema(permit);
2429
+ ACPUtils.validateSchema(acp);
2474
2430
  }
2475
2431
  return {
2476
- issuer: permit.issuer,
2477
- expiration: permit.expiration,
2478
- recipient: permit.recipient,
2479
- validatorId: permit.validatorId,
2480
- validatorContract: permit.validatorContract,
2481
- sealingKey: `0x${permit.sealingPair.publicKey}`,
2482
- issuerSignature: permit.issuerSignature,
2483
- recipientSignature: permit.recipientSignature
2432
+ issuer: acp.issuer,
2433
+ expiration: acp.expiration,
2434
+ recipient: acp.recipient,
2435
+ revokerData: acp.revokerData,
2436
+ revokerContract: acp.revokerContract,
2437
+ scope: acp.scope,
2438
+ contracts: acp.contracts,
2439
+ handles: acp.handles,
2440
+ sealingKey: acp.sealingKey,
2441
+ issuerSignature: acp.issuerSignature,
2442
+ recipientSignature: acp.recipientSignature
2484
2443
  };
2485
2444
  },
2486
2445
  /**
2487
- * Get a stable hash for the permit (used as key in storage)
2446
+ * Get a stable hash for the acp (used as key in storage)
2488
2447
  */
2489
- getHash: (permit) => {
2448
+ getHash: (acp) => {
2490
2449
  const data = JSON.stringify({
2491
- type: permit.type,
2492
- issuer: permit.issuer,
2493
- expiration: permit.expiration,
2494
- recipient: permit.recipient,
2495
- validatorId: permit.validatorId,
2496
- validatorContract: permit.validatorContract
2450
+ type: acp.type,
2451
+ issuer: acp.issuer,
2452
+ expiration: acp.expiration,
2453
+ recipient: acp.recipient,
2454
+ revokerData: acp.revokerData,
2455
+ revokerContract: acp.revokerContract,
2456
+ scope: acp.scope,
2457
+ contracts: acp.contracts,
2458
+ handles: acp.handles
2497
2459
  });
2498
2460
  return viem.keccak256(viem.toHex(data));
2499
2461
  },
2500
2462
  /**
2501
- * Export permit data for sharing (removes sensitive fields)
2463
+ * Export acp data for sharing (strips the private component).
2464
+ * Fixed `SharedACP` shape — every field always present, aligned with
2465
+ * `ACPPublic` and the on-chain sharing payload.
2502
2466
  */
2503
- export: (permit) => {
2504
- const cleanedPermit = {
2505
- name: permit.name,
2506
- type: permit.type,
2507
- issuer: permit.issuer,
2508
- expiration: permit.expiration
2467
+ export: (acp) => {
2468
+ if (acp.type !== "sharing") {
2469
+ throw new Error(
2470
+ `Cannot export a '${acp.type}' ACP \u2014 only 'sharing' ACPs are exportable. The export includes the issuer signature.`
2471
+ );
2472
+ }
2473
+ if (acp.issuerSignature === "0x") {
2474
+ throw new Error(
2475
+ "Cannot export an unsigned sharing ACP \u2014 sign it first (the recipient needs the issuer signature)."
2476
+ );
2477
+ }
2478
+ const shared = {
2479
+ name: acp.name,
2480
+ type: acp.type,
2481
+ issuer: acp.issuer,
2482
+ expiration: acp.expiration,
2483
+ recipient: acp.recipient,
2484
+ revokerData: acp.revokerData,
2485
+ revokerContract: acp.revokerContract,
2486
+ scope: acp.scope,
2487
+ contracts: acp.contracts,
2488
+ handles: acp.handles,
2489
+ issuerSignature: acp.issuerSignature
2509
2490
  };
2510
- if (permit.recipient !== viem.zeroAddress)
2511
- cleanedPermit.recipient = permit.recipient;
2512
- if (permit.validatorId !== 0)
2513
- cleanedPermit.validatorId = permit.validatorId;
2514
- if (permit.validatorContract !== viem.zeroAddress)
2515
- cleanedPermit.validatorContract = permit.validatorContract;
2516
- if (permit.type === "sharing" && permit.issuerSignature !== "0x")
2517
- cleanedPermit.issuerSignature = permit.issuerSignature;
2518
- return JSON.stringify(cleanedPermit, void 0, 2);
2491
+ return JSON.stringify(shared, void 0, 2);
2519
2492
  },
2520
2493
  /**
2521
- * Unseal encrypted data using the permit's sealing key
2494
+ * Unseal encrypted data using the acp's sealing key
2522
2495
  */
2523
- unseal: (permit, ciphertext) => {
2524
- return permit.sealingPair.unseal(ciphertext);
2496
+ unseal: (acp, ciphertext) => {
2497
+ return unsealWithPrivateKey(acp.sealingPrivateKey, ciphertext);
2525
2498
  },
2526
2499
  /**
2527
- * Check if permit is expired
2500
+ * Check if acp is expired
2528
2501
  */
2529
- isExpired: (permit) => {
2530
- return ValidationUtils.isExpired(permit);
2502
+ isExpired: (acp) => {
2503
+ return ValidationUtils.isExpired(acp);
2531
2504
  },
2532
2505
  /**
2533
- * Check if permit is signed
2506
+ * Check if acp is signed
2534
2507
  */
2535
- isSigned: (permit) => {
2536
- return ValidationUtils.isSigned(permit);
2508
+ isSigned: (acp) => {
2509
+ return ValidationUtils.isSigned(acp);
2537
2510
  },
2538
2511
  /**
2539
- * Check if permit is signed and not expired
2512
+ * Check if acp is signed and not expired
2540
2513
  */
2541
- isSignedAndNotExpired: (permit) => {
2542
- return ValidationUtils.isSignedAndNotExpired(permit);
2514
+ isSignedAndNotExpired: (acp) => {
2515
+ return ValidationUtils.isSignedAndNotExpired(acp);
2543
2516
  },
2544
2517
  /**
2545
- * Assert that permit is signed and not expired
2518
+ * Assert that acp is signed and not expired
2546
2519
  */
2547
- assertSignedAndNotExpired: (permit) => {
2548
- return ValidationUtils.assertSignedAndNotExpired(permit);
2520
+ assertSignedAndNotExpired: (acp) => {
2521
+ return ValidationUtils.assertSignedAndNotExpired(acp);
2549
2522
  },
2550
- isValid: (permit) => {
2551
- return ValidationUtils.isValid(permit);
2523
+ isValid: (acp) => {
2524
+ return ValidationUtils.isValid(acp);
2552
2525
  },
2553
2526
  /**
2554
- * Update permit name (returns new permit instance)
2527
+ * Update acp name (returns new acp instance)
2555
2528
  */
2556
- updateName: (permit, name) => {
2557
- return { ...permit, name };
2529
+ updateName: (acp, name) => {
2530
+ return { ...acp, name };
2558
2531
  },
2559
2532
  /**
2560
2533
  * Fetch EIP712 domain from the blockchain
@@ -2563,230 +2536,468 @@ var PermitUtils = {
2563
2536
  return getAclEIP712Domain(publicClient);
2564
2537
  },
2565
2538
  /**
2566
- * Check if permit's signed domain matches the provided domain
2539
+ * Check if acp's signed domain matches the provided domain
2567
2540
  */
2568
- matchesDomain: (permit, domain) => {
2569
- return permit._signedDomain?.name === domain.name && permit._signedDomain?.version === domain.version && permit._signedDomain?.verifyingContract === domain.verifyingContract && permit._signedDomain?.chainId === domain.chainId;
2541
+ matchesDomain: (acp, domain) => {
2542
+ return acp._signedDomain?.name === domain.name && acp._signedDomain?.version === domain.version && acp._signedDomain?.verifyingContract === domain.verifyingContract && acp._signedDomain?.chainId === domain.chainId;
2570
2543
  },
2571
2544
  /**
2572
- * Check if permit's signed domain is valid for the current chain
2545
+ * Check if acp's signed domain is valid for the current chain
2573
2546
  */
2574
- checkSignedDomainValid: async (permit, publicClient) => {
2575
- if (permit._signedDomain == null)
2547
+ checkSignedDomainValid: async (acp, publicClient) => {
2548
+ if (acp._signedDomain == null)
2576
2549
  return false;
2577
2550
  const domain = await getAclEIP712Domain(publicClient);
2578
- return PermitUtils.matchesDomain(permit, domain);
2551
+ return ACPUtils.matchesDomain(acp, domain);
2579
2552
  },
2580
2553
  /**
2581
- * Check if permit passes the on-chain validation
2554
+ * Check if acp passes the on-chain validation
2582
2555
  */
2583
- checkValidityOnChain: async (permit, publicClient) => {
2584
- const permission = PermitUtils.getPermission(permit);
2585
- return checkPermitValidityOnChain(permission, publicClient);
2556
+ checkValidityOnChain: async (acp, publicClient) => {
2557
+ const publicAcp = ACPUtils.getPublic(acp);
2558
+ return checkACPValidityOnChain(publicAcp, publicClient);
2586
2559
  }
2587
2560
  };
2588
- var PERMIT_STORE_DEFAULTS = {
2589
- permits: {},
2590
- activePermitHash: {}
2561
+ var ACP_STORE_DEFAULTS = {
2562
+ acps: {},
2563
+ activeACPHash: {}
2591
2564
  };
2592
- var _permitStore = vanilla.createStore()(
2593
- middleware.persist(() => PERMIT_STORE_DEFAULTS, { name: "cofhesdk-permits" })
2565
+ var ACP_STORE_VERSION = 3;
2566
+ var _acpStore = vanilla.createStore()(
2567
+ middleware.persist(() => ACP_STORE_DEFAULTS, {
2568
+ name: "cofhesdk-acps",
2569
+ version: ACP_STORE_VERSION,
2570
+ migrate: (persistedState, version) => {
2571
+ if (version < ACP_STORE_VERSION)
2572
+ return ACP_STORE_DEFAULTS;
2573
+ return persistedState;
2574
+ }
2575
+ })
2594
2576
  );
2595
2577
  var clearStaleStore = () => {
2596
- const state = _permitStore.getState();
2597
- const hasExpectedStructure = state && typeof state === "object" && "permits" in state && "activePermitHash" in state && typeof state.permits === "object" && typeof state.activePermitHash === "object";
2578
+ const state = _acpStore.getState();
2579
+ const hasExpectedStructure = state && typeof state === "object" && "acps" in state && "activeACPHash" in state && typeof state.acps === "object" && typeof state.activeACPHash === "object";
2598
2580
  if (hasExpectedStructure)
2599
2581
  return;
2600
- _permitStore.setState({ permits: {}, activePermitHash: {} });
2582
+ _acpStore.setState({ acps: {}, activeACPHash: {} });
2601
2583
  };
2602
- var getPermit = (chainId, account, hash) => {
2584
+ var getACP = (chainId, account, hash) => {
2603
2585
  clearStaleStore();
2604
2586
  if (chainId == null || account == null || hash == null)
2605
2587
  return;
2606
- const savedPermit = _permitStore.getState().permits[chainId]?.[account]?.[hash];
2607
- if (savedPermit == null)
2588
+ const savedACP = _acpStore.getState().acps[chainId]?.[account]?.[hash];
2589
+ if (savedACP == null)
2608
2590
  return;
2609
- return PermitUtils.deserialize(savedPermit);
2591
+ return ACPUtils.deserialize(savedACP);
2610
2592
  };
2611
- var getActivePermit = (chainId, account) => {
2593
+ var getActiveACP = (chainId, account) => {
2612
2594
  clearStaleStore();
2613
2595
  if (chainId == null || account == null)
2614
2596
  return;
2615
- const activePermitHash = _permitStore.getState().activePermitHash[chainId]?.[account];
2616
- return getPermit(chainId, account, activePermitHash);
2597
+ const activeACPHash = _acpStore.getState().activeACPHash[chainId]?.[account];
2598
+ return getACP(chainId, account, activeACPHash);
2617
2599
  };
2618
- var getPermits = (chainId, account) => {
2600
+ var getACPs = (chainId, account) => {
2619
2601
  clearStaleStore();
2620
2602
  if (chainId == null || account == null)
2621
2603
  return {};
2622
- return Object.entries(_permitStore.getState().permits[chainId]?.[account] ?? {}).reduce(
2623
- (acc, [hash, permit]) => {
2624
- if (permit == void 0)
2604
+ return Object.entries(_acpStore.getState().acps[chainId]?.[account] ?? {}).reduce(
2605
+ (acc, [hash, acp]) => {
2606
+ if (acp == void 0)
2625
2607
  return acc;
2626
- return { ...acc, [hash]: PermitUtils.deserialize(permit) };
2608
+ return { ...acc, [hash]: ACPUtils.deserialize(acp) };
2627
2609
  },
2628
2610
  {}
2629
2611
  );
2630
2612
  };
2631
- var setPermit = (chainId, account, permit) => {
2613
+ var setACP = (chainId, account, acp) => {
2632
2614
  clearStaleStore();
2633
- _permitStore.setState(
2615
+ _acpStore.setState(
2634
2616
  immer.produce((state) => {
2635
- if (state.permits[chainId] == null)
2636
- state.permits[chainId] = {};
2637
- if (state.permits[chainId][account] == null)
2638
- state.permits[chainId][account] = {};
2639
- state.permits[chainId][account][permit.hash] = PermitUtils.serialize(permit);
2617
+ if (state.acps[chainId] == null)
2618
+ state.acps[chainId] = {};
2619
+ if (state.acps[chainId][account] == null)
2620
+ state.acps[chainId][account] = {};
2621
+ state.acps[chainId][account][acp.hash] = ACPUtils.serialize(acp);
2640
2622
  })
2641
2623
  );
2642
2624
  };
2643
- var removePermit = (chainId, account, hash) => {
2625
+ var removeACP = (chainId, account, hash) => {
2644
2626
  clearStaleStore();
2645
- _permitStore.setState(
2627
+ _acpStore.setState(
2646
2628
  immer.produce((state) => {
2647
- if (state.permits[chainId] == null)
2648
- state.permits[chainId] = {};
2649
- if (state.activePermitHash[chainId] == null)
2650
- state.activePermitHash[chainId] = {};
2651
- const accountPermits = state.permits[chainId][account];
2652
- if (accountPermits == null)
2629
+ if (state.acps[chainId] == null)
2630
+ state.acps[chainId] = {};
2631
+ if (state.activeACPHash[chainId] == null)
2632
+ state.activeACPHash[chainId] = {};
2633
+ const accountACPs = state.acps[chainId][account];
2634
+ if (accountACPs == null)
2653
2635
  return;
2654
- if (accountPermits[hash] == null)
2636
+ if (accountACPs[hash] == null)
2655
2637
  return;
2656
- if (state.activePermitHash[chainId][account] === hash) {
2657
- state.activePermitHash[chainId][account] = void 0;
2638
+ if (state.activeACPHash[chainId][account] === hash) {
2639
+ state.activeACPHash[chainId][account] = void 0;
2658
2640
  }
2659
- accountPermits[hash] = void 0;
2641
+ accountACPs[hash] = void 0;
2660
2642
  })
2661
2643
  );
2662
2644
  };
2663
- var getActivePermitHash = (chainId, account) => {
2645
+ var getActiveACPHash = (chainId, account) => {
2664
2646
  clearStaleStore();
2665
2647
  if (chainId == null || account == null)
2666
2648
  return void 0;
2667
- return _permitStore.getState().activePermitHash[chainId]?.[account];
2649
+ return _acpStore.getState().activeACPHash[chainId]?.[account];
2668
2650
  };
2669
- var setActivePermitHash = (chainId, account, hash) => {
2651
+ var setActiveACPHash = (chainId, account, hash) => {
2670
2652
  clearStaleStore();
2671
- _permitStore.setState(
2653
+ _acpStore.setState(
2672
2654
  immer.produce((state) => {
2673
- if (state.activePermitHash[chainId] == null)
2674
- state.activePermitHash[chainId] = {};
2675
- state.activePermitHash[chainId][account] = hash;
2655
+ if (state.activeACPHash[chainId] == null)
2656
+ state.activeACPHash[chainId] = {};
2657
+ state.activeACPHash[chainId][account] = hash;
2676
2658
  })
2677
2659
  );
2678
2660
  };
2679
- var removeActivePermitHash = (chainId, account) => {
2661
+ var removeActiveACPHash = (chainId, account) => {
2680
2662
  clearStaleStore();
2681
- _permitStore.setState(
2663
+ _acpStore.setState(
2682
2664
  immer.produce((state) => {
2683
- if (state.activePermitHash[chainId])
2684
- state.activePermitHash[chainId][account] = void 0;
2665
+ if (state.activeACPHash[chainId])
2666
+ state.activeACPHash[chainId][account] = void 0;
2685
2667
  })
2686
2668
  );
2687
2669
  };
2688
2670
  var resetStore = () => {
2689
2671
  clearStaleStore();
2690
- _permitStore.setState({ permits: {}, activePermitHash: {} });
2672
+ _acpStore.setState({ acps: {}, activeACPHash: {} });
2691
2673
  };
2692
- var permitStore = {
2693
- store: _permitStore,
2694
- getPermit,
2695
- getActivePermit,
2696
- getPermits,
2697
- setPermit,
2698
- removePermit,
2699
- getActivePermitHash,
2700
- setActivePermitHash,
2701
- removeActivePermitHash,
2674
+ var acpStore = {
2675
+ store: _acpStore,
2676
+ getACP,
2677
+ getActiveACP,
2678
+ getACPs,
2679
+ setACP,
2680
+ removeACP,
2681
+ getActiveACPHash,
2682
+ setActiveACPHash,
2683
+ removeActiveACPHash,
2702
2684
  resetStore
2703
2685
  };
2704
- var storeActivePermit = async (permit, publicClient, walletClient) => {
2686
+ var ACP_VALIDATOR_ABI = viem.parseAbi([
2687
+ "function revokeSingle(uint256 id)",
2688
+ "function revokeAllExisting()",
2689
+ "function disabled(address issuer, uint256 id) view returns (bool)"
2690
+ ]);
2691
+ var storeACP = async (acp, publicClient, walletClient) => {
2692
+ const chainId = await publicClient.getChainId();
2693
+ const account = walletClient.account.address;
2694
+ acpStore.setACP(chainId, account, acp);
2695
+ };
2696
+ var storeActiveACP = async (acp, publicClient, walletClient) => {
2697
+ await storeACP(acp, publicClient, walletClient);
2705
2698
  const chainId = await publicClient.getChainId();
2706
2699
  const account = walletClient.account.address;
2707
- permitStore.setPermit(chainId, account, permit);
2708
- permitStore.setActivePermitHash(chainId, account, permit.hash);
2700
+ acpStore.setActiveACPHash(chainId, account, acp.hash);
2709
2701
  };
2710
- var createPermitWithSign = async (options, publicClient, walletClient, permitMethod) => {
2711
- const permit = await permitMethod(options, publicClient, walletClient);
2712
- await storeActivePermit(permit, publicClient, walletClient);
2713
- return permit;
2702
+ var createACPWithSign = async (options, publicClient, walletClient, acpMethod, activate = true) => {
2703
+ const acp = await acpMethod(options, publicClient, walletClient);
2704
+ if (activate) {
2705
+ await storeActiveACP(acp, publicClient, walletClient);
2706
+ } else {
2707
+ await storeACP(acp, publicClient, walletClient);
2708
+ }
2709
+ return acp;
2714
2710
  };
2715
2711
  var createSelf = async (options, publicClient, walletClient) => {
2716
- return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSelfAndSign);
2712
+ return createACPWithSign(options, publicClient, walletClient, ACPUtils.createSelfAndSign);
2717
2713
  };
2718
2714
  var createSharing = async (options, publicClient, walletClient) => {
2719
- return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSharingAndSign);
2715
+ return createACPWithSign(options, publicClient, walletClient, ACPUtils.createSharingAndSign, false);
2720
2716
  };
2721
2717
  var importShared = async (options, publicClient, walletClient) => {
2722
- return createPermitWithSign(options, publicClient, walletClient, PermitUtils.importSharedAndSign);
2718
+ return createACPWithSign(options, publicClient, walletClient, ACPUtils.importSharedAndSign);
2723
2719
  };
2724
- var getHash = (permit) => {
2725
- return PermitUtils.getHash(permit);
2720
+ var getHash = (acp) => {
2721
+ return ACPUtils.getHash(acp);
2726
2722
  };
2727
- var exportShared = (permit) => {
2728
- return PermitUtils.export(permit);
2723
+ var exportShared = (acp) => {
2724
+ return ACPUtils.export(acp);
2729
2725
  };
2730
- var serialize = (permit) => {
2731
- return PermitUtils.serialize(permit);
2726
+ var serialize = (acp) => {
2727
+ return ACPUtils.serialize(acp);
2732
2728
  };
2733
2729
  var deserialize = (serialized) => {
2734
- return PermitUtils.deserialize(serialized);
2730
+ return ACPUtils.deserialize(serialized);
2735
2731
  };
2736
- var getPermit2 = (chainId, account, hash) => {
2737
- return permitStore.getPermit(chainId, account, hash);
2732
+ var getACP2 = (chainId, account, hash) => {
2733
+ return acpStore.getACP(chainId, account, hash);
2738
2734
  };
2739
- var getPermits2 = (chainId, account) => {
2740
- return permitStore.getPermits(chainId, account);
2735
+ var getACPs2 = (chainId, account) => {
2736
+ return acpStore.getACPs(chainId, account);
2741
2737
  };
2742
- var getActivePermit2 = (chainId, account) => {
2743
- return permitStore.getActivePermit(chainId, account);
2738
+ var getActiveACP2 = (chainId, account) => {
2739
+ return acpStore.getActiveACP(chainId, account);
2744
2740
  };
2745
- var getActivePermitHash2 = (chainId, account) => {
2746
- return permitStore.getActivePermitHash(chainId, account);
2741
+ var getActiveACPHash2 = (chainId, account) => {
2742
+ return acpStore.getActiveACPHash(chainId, account);
2747
2743
  };
2748
- var selectActivePermit = (chainId, account, hash) => {
2749
- permitStore.setActivePermitHash(chainId, account, hash);
2744
+ var selectActiveACP = (chainId, account, hash) => {
2745
+ acpStore.setActiveACPHash(chainId, account, hash);
2750
2746
  };
2751
- var getOrCreateSelfPermit = async (publicClient, walletClient, chainId, account, options) => {
2747
+ var getOrCreateSelfACP = async (publicClient, walletClient, chainId, account, options) => {
2752
2748
  const _chainId = chainId ?? await publicClient.getChainId();
2753
2749
  const _account = account ?? walletClient.account.address;
2754
- const activePermit = await getActivePermit2(_chainId, _account);
2755
- if (activePermit && activePermit.type === "self" && PermitUtils.isValid(activePermit).valid) {
2756
- return activePermit;
2750
+ const activeACP = await getActiveACP2(_chainId, _account);
2751
+ if (activeACP && activeACP.type === "self" && ACPUtils.isValid(activeACP).valid) {
2752
+ return activeACP;
2757
2753
  }
2758
- return createSelf(options ?? { issuer: _account, name: "Autogenerated Self Permit" }, publicClient, walletClient);
2754
+ return createSelf(options ?? { issuer: _account, name: "Autogenerated Self ACP" }, publicClient, walletClient);
2759
2755
  };
2760
- var getOrCreateSharingPermit = async (publicClient, walletClient, options, chainId, account) => {
2756
+ var getOrCreateSharingACP = async (publicClient, walletClient, options, chainId, account) => {
2761
2757
  const _chainId = chainId ?? await publicClient.getChainId();
2762
2758
  const _account = account ?? walletClient.account.address;
2763
- const activePermit = await getActivePermit2(_chainId, _account);
2764
- if (activePermit && activePermit.type === "sharing" && PermitUtils.isValid(activePermit).valid) {
2765
- return activePermit;
2759
+ const activeACP = await getActiveACP2(_chainId, _account);
2760
+ if (activeACP && activeACP.type === "sharing" && ACPUtils.isValid(activeACP).valid) {
2761
+ return activeACP;
2766
2762
  }
2767
2763
  return createSharing(options, publicClient, walletClient);
2768
2764
  };
2769
- var removePermit2 = async (chainId, account, hash) => permitStore.removePermit(chainId, account, hash);
2770
- var removeActivePermit = async (chainId, account) => permitStore.removeActivePermitHash(chainId, account);
2771
- var permits = {
2772
- getSnapshot: permitStore.store.getState,
2773
- subscribe: permitStore.store.subscribe,
2765
+ var applyACPDefaults = (options, acpConfig, chainId) => {
2766
+ const result = { ...options };
2767
+ const defaultRevoker = acpConfig?.defaultRevoker?.[chainId];
2768
+ const hasValidatorOptions = options.revokerData != null || options.revokerContract != null;
2769
+ if (defaultRevoker != null && !hasValidatorOptions) {
2770
+ result.revokerContract = defaultRevoker;
2771
+ result.revokerData = Math.round(Date.now() / 1e3) - 60;
2772
+ }
2773
+ const defaultContracts = acpConfig?.defaultContractScopes?.[chainId];
2774
+ const hasScopeOptions = options.scope != null || options.contracts != null || options.handles != null;
2775
+ if (defaultContracts != null && defaultContracts.length > 0 && !hasScopeOptions) {
2776
+ result.contracts = defaultContracts;
2777
+ }
2778
+ return result;
2779
+ };
2780
+ var ACL_SERVED_ADDRESSES_ABI = viem.parseAbi([
2781
+ "function acl() view returns (address)",
2782
+ "function defaultRevokerContract() view returns (address)",
2783
+ "function shareRegistry() view returns (address)"
2784
+ ]);
2785
+ var aclServedAddressesCache = /* @__PURE__ */ new Map();
2786
+ var clearAclServedAddresses = () => aclServedAddressesCache.clear();
2787
+ var getAclServedAddresses = async (publicClient, chainId) => {
2788
+ const cached = aclServedAddressesCache.get(chainId);
2789
+ if (cached != null)
2790
+ return cached;
2791
+ let aclAddress;
2792
+ try {
2793
+ aclAddress = await publicClient.readContract({
2794
+ address: TASK_MANAGER_ADDRESS,
2795
+ abi: ACL_SERVED_ADDRESSES_ABI,
2796
+ functionName: "acl"
2797
+ });
2798
+ } catch {
2799
+ return {};
2800
+ }
2801
+ const [defaultRevoker, shareRegistry] = await Promise.all([
2802
+ publicClient.readContract({ address: aclAddress, abi: ACL_SERVED_ADDRESSES_ABI, functionName: "defaultRevokerContract" }).catch(() => void 0),
2803
+ publicClient.readContract({ address: aclAddress, abi: ACL_SERVED_ADDRESSES_ABI, functionName: "shareRegistry" }).catch(() => void 0)
2804
+ ]);
2805
+ const resolved = {
2806
+ defaultRevoker: defaultRevoker != null && defaultRevoker !== viem.zeroAddress ? defaultRevoker : void 0,
2807
+ shareRegistry: shareRegistry != null && shareRegistry !== viem.zeroAddress ? shareRegistry : void 0
2808
+ };
2809
+ aclServedAddressesCache.set(chainId, resolved);
2810
+ return resolved;
2811
+ };
2812
+ var applyACPDefaultsFromChain = async (options, acpConfig, publicClient, chainId) => {
2813
+ const hasExplicitRevoker = acpConfig?.defaultRevoker?.[chainId] != null || options.revokerData != null || options.revokerContract != null;
2814
+ if (hasExplicitRevoker)
2815
+ return applyACPDefaults(options, acpConfig, chainId);
2816
+ const served = await getAclServedAddresses(publicClient, chainId);
2817
+ const effectiveConfig = served.defaultRevoker != null ? { ...acpConfig, defaultRevoker: { ...acpConfig?.defaultRevoker, [chainId]: served.defaultRevoker } } : acpConfig;
2818
+ return applyACPDefaults(options, effectiveConfig, chainId);
2819
+ };
2820
+ var revokeACP = async (acp, walletClient) => {
2821
+ if (acp.revokerContract === viem.zeroAddress || acp.revokerData === 0) {
2822
+ throw new Error("ACP is not revocable: it has no revoker (revokerContract/revokerData unset)");
2823
+ }
2824
+ if (walletClient.account == null)
2825
+ throw new Error("Missing walletClient account");
2826
+ if (walletClient.account.address.toLowerCase() !== acp.issuer.toLowerCase()) {
2827
+ throw new Error("Only the acp issuer can revoke it");
2828
+ }
2829
+ return walletClient.writeContract({
2830
+ address: acp.revokerContract,
2831
+ abi: ACP_VALIDATOR_ABI,
2832
+ functionName: "revokeSingle",
2833
+ args: [BigInt(acp.revokerData)],
2834
+ account: walletClient.account,
2835
+ chain: walletClient.chain
2836
+ });
2837
+ };
2838
+ var revokeAllACPs = async (walletClient, publicClient, revokerContract) => {
2839
+ if (walletClient.account == null)
2840
+ throw new Error("Missing walletClient account");
2841
+ let revoker = revokerContract;
2842
+ if (revoker == null) {
2843
+ const chainId = await publicClient.getChainId();
2844
+ const active = getActiveACP2(chainId, walletClient.account.address);
2845
+ revoker = active?.revokerContract;
2846
+ }
2847
+ if (revoker == null || revoker === viem.zeroAddress) {
2848
+ throw new Error("No revoker contract: pass `revokerContract` or activate a revocable acp first");
2849
+ }
2850
+ return walletClient.writeContract({
2851
+ address: revoker,
2852
+ abi: ACP_VALIDATOR_ABI,
2853
+ functionName: "revokeAllExisting",
2854
+ args: [],
2855
+ account: walletClient.account,
2856
+ chain: walletClient.chain
2857
+ });
2858
+ };
2859
+ var isACPRevoked = async (acp, publicClient) => {
2860
+ if (acp.revokerContract === viem.zeroAddress || acp.revokerData === 0)
2861
+ return false;
2862
+ return publicClient.readContract({
2863
+ address: acp.revokerContract,
2864
+ abi: ACP_VALIDATOR_ABI,
2865
+ functionName: "disabled",
2866
+ args: [acp.issuer, BigInt(acp.revokerData)]
2867
+ });
2868
+ };
2869
+ var ACP_SHARE_REGISTRY_ABI = viem.parseAbi([
2870
+ "struct ACP { address issuer; uint64 expiration; address recipient; uint256 revokerData; address revokerContract; uint8 scope; address[] contracts; bytes32[] handles; bytes32 sealingKey; bytes issuerSignature; bytes recipientSignature; }",
2871
+ "function share(ACP calldata acp) external returns (bytes32)",
2872
+ "function removeShare(bytes32 shareId) external",
2873
+ "function sharesFor(address recipient) external view returns (ACP[] memory)",
2874
+ "function getShare(bytes32 shareId) external view returns (ACP memory)",
2875
+ "function isShareValid(bytes32 shareId) external view returns (bool)"
2876
+ ]);
2877
+ var ACP_TUPLE = [
2878
+ {
2879
+ type: "tuple",
2880
+ components: [
2881
+ { name: "issuer", type: "address" },
2882
+ { name: "expiration", type: "uint64" },
2883
+ { name: "recipient", type: "address" },
2884
+ { name: "revokerData", type: "uint256" },
2885
+ { name: "revokerContract", type: "address" },
2886
+ { name: "scope", type: "uint8" },
2887
+ { name: "contracts", type: "address[]" },
2888
+ { name: "handles", type: "bytes32[]" },
2889
+ { name: "sealingKey", type: "bytes32" },
2890
+ { name: "issuerSignature", type: "bytes" },
2891
+ { name: "recipientSignature", type: "bytes" }
2892
+ ]
2893
+ }
2894
+ ];
2895
+ var ZERO_BYTES32 = `0x${"0".repeat(64)}`;
2896
+ var toChainShare = (acp) => {
2897
+ const pub = ACPUtils.getPublic(acp, true);
2898
+ return {
2899
+ ...pub,
2900
+ expiration: BigInt(pub.expiration),
2901
+ revokerData: BigInt(pub.revokerData),
2902
+ sealingKey: ZERO_BYTES32,
2903
+ recipientSignature: "0x"
2904
+ };
2905
+ };
2906
+ var computeShareId = (acp) => {
2907
+ const p = toChainShare(acp);
2908
+ return viem.keccak256(viem.encodeAbiParameters(ACP_TUPLE, [p]));
2909
+ };
2910
+ var shareOnChain = async (acp, walletClient, registry) => {
2911
+ if (acp.type !== "sharing") {
2912
+ throw new Error(`Cannot share a '${acp.type}' ACP on-chain \u2014 only 'sharing' ACPs are shareable.`);
2913
+ }
2914
+ if (acp.issuerSignature === "0x") {
2915
+ throw new Error("Cannot share an unsigned sharing ACP \u2014 sign it first.");
2916
+ }
2917
+ if (walletClient.account == null)
2918
+ throw new Error("Missing walletClient account");
2919
+ if (walletClient.account.address.toLowerCase() !== acp.issuer.toLowerCase()) {
2920
+ throw new Error("Only the ACP issuer can share it on-chain");
2921
+ }
2922
+ const txHash = await walletClient.writeContract({
2923
+ address: registry,
2924
+ abi: ACP_SHARE_REGISTRY_ABI,
2925
+ functionName: "share",
2926
+ args: [toChainShare(acp)],
2927
+ account: walletClient.account,
2928
+ chain: walletClient.chain ?? null
2929
+ });
2930
+ return { txHash, shareId: computeShareId(acp) };
2931
+ };
2932
+ var getIncomingShares = async (publicClient, registry, recipient) => {
2933
+ const raw = await publicClient.readContract({
2934
+ address: registry,
2935
+ abi: ACP_SHARE_REGISTRY_ABI,
2936
+ functionName: "sharesFor",
2937
+ args: [recipient]
2938
+ });
2939
+ return raw.map((s) => ({
2940
+ shareId: viem.keccak256(viem.encodeAbiParameters(ACP_TUPLE, [s])),
2941
+ issuer: s.issuer,
2942
+ expiration: Number(s.expiration),
2943
+ recipient: s.recipient,
2944
+ revokerData: Number(s.revokerData),
2945
+ revokerContract: s.revokerContract,
2946
+ scope: Number(s.scope),
2947
+ contracts: [...s.contracts],
2948
+ handles: [...s.handles],
2949
+ issuerSignature: s.issuerSignature
2950
+ }));
2951
+ };
2952
+ var importFromChain = async (share, publicClient, walletClient) => {
2953
+ const { shareId: _shareId, ...options } = share;
2954
+ return importShared({ ...options, type: "sharing" }, publicClient, walletClient);
2955
+ };
2956
+ var removeShareOnChain = async (shareId, walletClient, registry) => {
2957
+ if (walletClient.account == null)
2958
+ throw new Error("Missing walletClient account");
2959
+ return walletClient.writeContract({
2960
+ address: registry,
2961
+ abi: ACP_SHARE_REGISTRY_ABI,
2962
+ functionName: "removeShare",
2963
+ args: [shareId],
2964
+ account: walletClient.account,
2965
+ chain: walletClient.chain ?? null
2966
+ });
2967
+ };
2968
+ var removeACP2 = async (chainId, account, hash) => acpStore.removeACP(chainId, account, hash);
2969
+ var removeActiveACP = async (chainId, account) => acpStore.removeActiveACPHash(chainId, account);
2970
+ var acps = {
2971
+ getSnapshot: acpStore.store.getState,
2972
+ subscribe: acpStore.store.subscribe,
2774
2973
  createSelf,
2775
2974
  createSharing,
2776
2975
  importShared,
2777
- getOrCreateSelfPermit,
2778
- getOrCreateSharingPermit,
2976
+ getOrCreateSelfACP,
2977
+ getOrCreateSharingACP,
2779
2978
  getHash,
2780
2979
  export: exportShared,
2781
2980
  serialize,
2782
2981
  deserialize,
2783
- getPermit: getPermit2,
2784
- getPermits: getPermits2,
2785
- getActivePermit: getActivePermit2,
2786
- getActivePermitHash: getActivePermitHash2,
2787
- removePermit: removePermit2,
2788
- selectActivePermit,
2789
- removeActivePermit
2982
+ getACP: getACP2,
2983
+ getACPs: getACPs2,
2984
+ getActiveACP: getActiveACP2,
2985
+ getActiveACPHash: getActiveACPHash2,
2986
+ removeACP: removeACP2,
2987
+ selectActiveACP,
2988
+ removeActiveACP,
2989
+ revokeACP,
2990
+ revokeAllACPs,
2991
+ isACPRevoked,
2992
+ shareOnChain,
2993
+ getIncomingShares,
2994
+ importFromChain,
2995
+ removeShareOnChain,
2996
+ computeShareId,
2997
+ applyACPDefaults,
2998
+ applyACPDefaultsFromChain,
2999
+ getAclServedAddresses,
3000
+ clearAclServedAddresses
2790
3001
  };
2791
3002
  function uint160ToAddress(uint160) {
2792
3003
  const hexStr = uint160.toString(16).padStart(40, "0");
@@ -2849,13 +3060,16 @@ var MockThresholdNetworkAbi = [
2849
3060
  {
2850
3061
  name: "permission",
2851
3062
  type: "tuple",
2852
- internalType: "struct Permission",
3063
+ internalType: "struct ACPermission",
2853
3064
  components: [
2854
3065
  { name: "issuer", type: "address", internalType: "address" },
2855
3066
  { name: "expiration", type: "uint64", internalType: "uint64" },
2856
3067
  { name: "recipient", type: "address", internalType: "address" },
2857
- { name: "validatorId", type: "uint256", internalType: "uint256" },
2858
- { name: "validatorContract", type: "address", internalType: "address" },
3068
+ { name: "revokerData", type: "uint256", internalType: "uint256" },
3069
+ { name: "revokerContract", type: "address", internalType: "address" },
3070
+ { name: "scope", type: "uint8", internalType: "uint8" },
3071
+ { name: "contracts", type: "address[]", internalType: "address[]" },
3072
+ { name: "handles", type: "bytes32[]", internalType: "bytes32[]" },
2859
3073
  { name: "sealingKey", type: "bytes32", internalType: "bytes32" },
2860
3074
  { name: "issuerSignature", type: "bytes", internalType: "bytes" },
2861
3075
  { name: "recipientSignature", type: "bytes", internalType: "bytes" }
@@ -2878,13 +3092,16 @@ var MockThresholdNetworkAbi = [
2878
3092
  {
2879
3093
  name: "permission",
2880
3094
  type: "tuple",
2881
- internalType: "struct Permission",
3095
+ internalType: "struct ACPermission",
2882
3096
  components: [
2883
3097
  { name: "issuer", type: "address", internalType: "address" },
2884
3098
  { name: "expiration", type: "uint64", internalType: "uint64" },
2885
3099
  { name: "recipient", type: "address", internalType: "address" },
2886
- { name: "validatorId", type: "uint256", internalType: "uint256" },
2887
- { name: "validatorContract", type: "address", internalType: "address" },
3100
+ { name: "revokerData", type: "uint256", internalType: "uint256" },
3101
+ { name: "revokerContract", type: "address", internalType: "address" },
3102
+ { name: "scope", type: "uint8", internalType: "uint8" },
3103
+ { name: "contracts", type: "address[]", internalType: "address[]" },
3104
+ { name: "handles", type: "bytes32[]", internalType: "bytes32[]" },
2888
3105
  { name: "sealingKey", type: "bytes32", internalType: "bytes32" },
2889
3106
  { name: "issuerSignature", type: "bytes", internalType: "bytes" },
2890
3107
  { name: "recipientSignature", type: "bytes", internalType: "bytes" }
@@ -2949,19 +3166,22 @@ var MockThresholdNetworkAbi = [
2949
3166
  },
2950
3167
  {
2951
3168
  type: "function",
2952
- name: "decryptForTxWithPermit",
3169
+ name: "decryptForTxWithACP",
2953
3170
  inputs: [
2954
3171
  { name: "ctHash", type: "uint256", internalType: "uint256" },
2955
3172
  {
2956
3173
  name: "permission",
2957
3174
  type: "tuple",
2958
- internalType: "struct Permission",
3175
+ internalType: "struct ACPermission",
2959
3176
  components: [
2960
3177
  { name: "issuer", type: "address", internalType: "address" },
2961
3178
  { name: "expiration", type: "uint64", internalType: "uint64" },
2962
3179
  { name: "recipient", type: "address", internalType: "address" },
2963
- { name: "validatorId", type: "uint256", internalType: "uint256" },
2964
- { name: "validatorContract", type: "address", internalType: "address" },
3180
+ { name: "revokerData", type: "uint256", internalType: "uint256" },
3181
+ { name: "revokerContract", type: "address", internalType: "address" },
3182
+ { name: "scope", type: "uint8", internalType: "uint8" },
3183
+ { name: "contracts", type: "address[]", internalType: "address[]" },
3184
+ { name: "handles", type: "bytes32[]", internalType: "bytes32[]" },
2965
3185
  { name: "sealingKey", type: "bytes32", internalType: "bytes32" },
2966
3186
  { name: "issuerSignature", type: "bytes", internalType: "bytes" },
2967
3187
  { name: "recipientSignature", type: "bytes", internalType: "bytes" }
@@ -2977,7 +3197,7 @@ var MockThresholdNetworkAbi = [
2977
3197
  },
2978
3198
  {
2979
3199
  type: "function",
2980
- name: "decryptForTxWithoutPermit",
3200
+ name: "decryptForTxWithoutACP",
2981
3201
  inputs: [{ name: "ctHash", type: "uint256", internalType: "uint256" }],
2982
3202
  outputs: [
2983
3203
  { name: "allowed", type: "bool", internalType: "bool" },
@@ -2989,12 +3209,12 @@ var MockThresholdNetworkAbi = [
2989
3209
  ];
2990
3210
 
2991
3211
  // core/decrypt/cofheMocksDecryptForView.ts
2992
- async function cofheMocksDecryptForView(ctHash, utype, permit, publicClient) {
2993
- const permission = PermitUtils.getPermission(permit, true);
3212
+ async function cofheMocksDecryptForView(ctHash, utype, acp, publicClient) {
3213
+ const wireAcp = ACPUtils.getPublic(acp, true);
2994
3214
  const permissionWithBigInts = {
2995
- ...permission,
2996
- expiration: BigInt(permission.expiration),
2997
- validatorId: BigInt(permission.validatorId)
3215
+ ...wireAcp,
3216
+ expiration: BigInt(wireAcp.expiration),
3217
+ revokerData: BigInt(wireAcp.revokerData)
2998
3218
  };
2999
3219
  const [allowed, error, result] = await publicClient.readContract({
3000
3220
  address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
@@ -3015,7 +3235,7 @@ async function cofheMocksDecryptForView(ctHash, utype, permit, publicClient) {
3015
3235
  });
3016
3236
  }
3017
3237
  const sealedBigInt = BigInt(result);
3018
- const sealingKeyBigInt = BigInt(permission.sealingKey);
3238
+ const sealingKeyBigInt = BigInt(acp.sealingKey);
3019
3239
  const unsealed = sealedBigInt ^ sealingKeyBigInt;
3020
3240
  return unsealed;
3021
3241
  }
@@ -3058,11 +3278,61 @@ function computeMinuteRampPollIntervalMs(elapsedMs, params) {
3058
3278
  return Math.min(params.maxIntervalMs, Math.max(params.minIntervalMs, intervalMs));
3059
3279
  }
3060
3280
 
3281
+ // core/decrypt/apiError.ts
3282
+ var BACKEND_ERROR_CODE_TO_COFHE_ERROR_CODE = {
3283
+ bad_request: "BAD_REQUEST" /* BadRequest */,
3284
+ unknown_chain: "UNKNOWN_CHAIN" /* UnknownChain */,
3285
+ acp_malformed: "ACP_MALFORMED" /* ACPMalformed */,
3286
+ acp_denied: "ACP_DENIED" /* ACPDenied */,
3287
+ // ACP-era backends fold revoked into denied
3288
+ acp_expired: "ACP_EXPIRED" /* ACPExpired */,
3289
+ acp_invalid: "ACP_INVALID" /* ACPInvalid */,
3290
+ acp_required: "ACP_REQUIRED" /* ACPRequired */,
3291
+ acp_verifier_error: "ACP_VERIFIER_ERROR" /* ACPVerifierError */,
3292
+ acp_verifier_timeout: "ACP_VERIFIER_TIMEOUT" /* ACPVerifierTimeout */,
3293
+ not_publicly_allowed: "NOT_PUBLICLY_ALLOWED" /* NotPubliclyAllowed */,
3294
+ ct_not_found: "CT_NOT_FOUND" /* CtNotFound */,
3295
+ unsupported_security_zone: "UNSUPPORTED_SECURITY_ZONE" /* UnsupportedSecurityZone */,
3296
+ unsupported_type: "UNSUPPORTED_TYPE" /* UnsupportedType */,
3297
+ internal_error: "INTERNAL_ERROR" /* InternalError */,
3298
+ signing_failed: "SIGNING_FAILED" /* SigningFailed */,
3299
+ ct_source_error: "CT_SOURCE_ERROR" /* CtSourceError */,
3300
+ ct_source_timeout: "CT_SOURCE_TIMEOUT" /* CtSourceTimeout */,
3301
+ seal_failed: "SEAL_FAILED" /* SealFailed */
3302
+ };
3303
+ function isBackendApiErrorCode(value) {
3304
+ return value in BACKEND_ERROR_CODE_TO_COFHE_ERROR_CODE;
3305
+ }
3306
+ async function parseApiErrorResponseBody(response) {
3307
+ let errorMessage = `HTTP ${response.status}`;
3308
+ let apiErrorCode;
3309
+ try {
3310
+ const body = await response.json();
3311
+ if (body && typeof body === "object") {
3312
+ const record = body;
3313
+ if (typeof record.error === "string" && record.error.length > 0) {
3314
+ apiErrorCode = record.error;
3315
+ }
3316
+ if (typeof record.error_message === "string" && record.error_message.length > 0) {
3317
+ errorMessage = record.error_message;
3318
+ } else if (typeof record.message === "string" && record.message.length > 0) {
3319
+ errorMessage = record.message;
3320
+ }
3321
+ }
3322
+ } catch {
3323
+ errorMessage = response.statusText || errorMessage;
3324
+ }
3325
+ return { apiErrorCode, errorMessage };
3326
+ }
3327
+ function mapApiErrorCodeToCofheErrorCode(apiErrorCode, fallback) {
3328
+ if (apiErrorCode && isBackendApiErrorCode(apiErrorCode)) {
3329
+ return BACKEND_ERROR_CODE_TO_COFHE_ERROR_CODE[apiErrorCode];
3330
+ }
3331
+ return fallback;
3332
+ }
3333
+
3061
3334
  // core/decrypt/submitRetry.ts
3062
3335
  var DEFAULT_404_RETRY_TIMEOUT_MS = 1e4;
3063
- function isRetryableSubmitStatus(status) {
3064
- return status === 204 || status === 404;
3065
- }
3066
3336
  function normalize404RetryTimeoutMs(params) {
3067
3337
  const { timeoutMs, operationLabel, errorCode } = params;
3068
3338
  if (timeoutMs === void 0)
@@ -3079,32 +3349,24 @@ function normalize404RetryTimeoutMs(params) {
3079
3349
  return timeoutMs;
3080
3350
  }
3081
3351
  async function classifySubmitResponse(params) {
3082
- const { response, extractErrorMessage } = params;
3083
- if (isRetryableSubmitStatus(response.status)) {
3084
- return { kind: "retryable", status: response.status };
3352
+ const { response, fallbackErrorCode } = params;
3353
+ if (response.status === 204) {
3354
+ return { kind: "retryable", status: 204 };
3085
3355
  }
3086
3356
  if (response.ok) {
3087
3357
  return { kind: "parse-json" };
3088
3358
  }
3089
- let errorMessage = `HTTP ${response.status}`;
3090
- try {
3091
- const errorBody = await response.json();
3092
- const maybeErrorMessage = extractErrorMessage?.(errorBody);
3093
- if (typeof maybeErrorMessage === "string" && maybeErrorMessage.length > 0) {
3094
- errorMessage = maybeErrorMessage;
3095
- } else if (errorBody && typeof errorBody === "object") {
3096
- const defaultMessage = errorBody.error_message;
3097
- const fallbackMessage = errorBody.message;
3098
- if (typeof defaultMessage === "string" && defaultMessage.length > 0) {
3099
- errorMessage = defaultMessage;
3100
- } else if (typeof fallbackMessage === "string" && fallbackMessage.length > 0) {
3101
- errorMessage = fallbackMessage;
3102
- }
3103
- }
3104
- } catch {
3105
- errorMessage = response.statusText || errorMessage;
3359
+ const { apiErrorCode, errorMessage } = await parseApiErrorResponseBody(response);
3360
+ if (response.status === 404) {
3361
+ return { kind: "retryable", status: 404, apiErrorMessage: errorMessage };
3106
3362
  }
3107
- return { kind: "fatal-http", errorMessage };
3363
+ return {
3364
+ kind: "fatal-http",
3365
+ status: response.status,
3366
+ cofheErrorCode: mapApiErrorCodeToCofheErrorCode(apiErrorCode, fallbackErrorCode),
3367
+ apiErrorCode,
3368
+ errorMessage
3369
+ };
3108
3370
  }
3109
3371
  function throwIfSubmitRetryTimedOut(params) {
3110
3372
  const {
@@ -3116,12 +3378,14 @@ function throwIfSubmitRetryTimedOut(params) {
3116
3378
  overallTimeoutMs,
3117
3379
  thresholdNetworkUrl,
3118
3380
  body,
3119
- attemptIndex
3381
+ attemptIndex,
3382
+ lastKnownErrorMessage
3120
3383
  } = params;
3121
3384
  if (status === 404 && elapsedMs > retry404TimeoutMs) {
3122
3385
  throw new CofheError({
3123
- code: errorCode,
3124
- message: `${operationLabel} submit retried 404 responses without receiving request_id for ${retry404TimeoutMs}ms`,
3386
+ code: "CT_NOT_FOUND" /* CtNotFound */,
3387
+ apiErrorCode: "ct_not_found",
3388
+ message: `${operationLabel} ciphertext not found after retrying for ${retry404TimeoutMs}ms` + (lastKnownErrorMessage ? `: ${lastKnownErrorMessage}` : ""),
3125
3389
  hint: "The ciphertext may not be indexed yet. Increase set404RetryTimeout(...) if the backend is slow to index ciphertexts.",
3126
3390
  context: {
3127
3391
  thresholdNetworkUrl,
@@ -3147,6 +3411,62 @@ function throwIfSubmitRetryTimedOut(params) {
3147
3411
  });
3148
3412
  }
3149
3413
  }
3414
+ function normalizeTnSignature(signature) {
3415
+ if (typeof signature !== "string") {
3416
+ throw new CofheError({
3417
+ code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
3418
+ message: "decrypt response missing signature",
3419
+ context: {
3420
+ signature
3421
+ }
3422
+ });
3423
+ }
3424
+ const trimmed = signature.trim();
3425
+ if (trimmed.length === 0) {
3426
+ throw new CofheError({
3427
+ code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
3428
+ message: "decrypt response returned empty signature"
3429
+ });
3430
+ }
3431
+ const prefixed = trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
3432
+ const parsed = viem.parseSignature(prefixed);
3433
+ return viem.serializeSignature(parsed);
3434
+ }
3435
+ function parseDecryptedBytesToBigInt(decrypted) {
3436
+ if (!Array.isArray(decrypted)) {
3437
+ throw new CofheError({
3438
+ code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
3439
+ message: "decrypt response field <decrypted> must be a byte array",
3440
+ context: {
3441
+ decrypted
3442
+ }
3443
+ });
3444
+ }
3445
+ if (decrypted.length === 0) {
3446
+ throw new CofheError({
3447
+ code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
3448
+ message: "decrypt response field <decrypted> was an empty byte array",
3449
+ context: {
3450
+ decrypted
3451
+ }
3452
+ });
3453
+ }
3454
+ let hex = "";
3455
+ for (const b of decrypted) {
3456
+ if (typeof b !== "number" || !Number.isInteger(b) || b < 0 || b > 255) {
3457
+ throw new CofheError({
3458
+ code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
3459
+ message: "decrypt response field <decrypted> contained a non-byte value",
3460
+ context: {
3461
+ badElement: b,
3462
+ decrypted
3463
+ }
3464
+ });
3465
+ }
3466
+ hex += b.toString(16).padStart(2, "0");
3467
+ }
3468
+ return BigInt(`0x${hex}`);
3469
+ }
3150
3470
 
3151
3471
  // core/decrypt/tnSealOutputV2.ts
3152
3472
  var POLL_INTERVAL_MS = 1e3;
@@ -3209,13 +3529,14 @@ function parseCompletedSealOutputResponse(params) {
3209
3529
  }
3210
3530
  return convertSealedData(sealed);
3211
3531
  }
3212
- async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission, overallStartTime, retry404TimeoutMs, onPoll) {
3532
+ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, acp, overallStartTime, retry404TimeoutMs, onPoll) {
3213
3533
  const body = {
3214
3534
  ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
3215
3535
  host_chain_id: chainId,
3216
- permit: permission
3536
+ acp
3217
3537
  };
3218
3538
  let attemptIndex = 0;
3539
+ let last404ApiErrorMessage;
3219
3540
  for (; ; ) {
3220
3541
  let response;
3221
3542
  try {
@@ -3243,16 +3564,19 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
3243
3564
  }
3244
3565
  });
3245
3566
  }
3246
- const responseClassification = await classifySubmitResponse({ response });
3567
+ const responseClassification = await classifySubmitResponse({
3568
+ response,
3569
+ fallbackErrorCode: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */
3570
+ });
3247
3571
  if (responseClassification.kind === "fatal-http") {
3248
3572
  throw new CofheError({
3249
- code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
3573
+ code: responseClassification.cofheErrorCode,
3574
+ apiErrorCode: responseClassification.apiErrorCode,
3250
3575
  message: `sealOutput request failed: ${responseClassification.errorMessage}`,
3251
3576
  hint: "Check the threshold network URL and request parameters.",
3252
3577
  context: {
3253
3578
  thresholdNetworkUrl,
3254
- status: response.status,
3255
- statusText: response.statusText,
3579
+ status: responseClassification.status,
3256
3580
  body,
3257
3581
  attemptIndex
3258
3582
  }
@@ -3298,6 +3622,9 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
3298
3622
  }
3299
3623
  });
3300
3624
  }
3625
+ if (responseClassification.status === 404) {
3626
+ last404ApiErrorMessage = responseClassification.apiErrorMessage;
3627
+ }
3301
3628
  const elapsedMs = Date.now() - overallStartTime;
3302
3629
  throwIfSubmitRetryTimedOut({
3303
3630
  operationLabel: "sealOutput",
@@ -3308,7 +3635,8 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
3308
3635
  overallTimeoutMs: SEAL_OUTPUT_TIMEOUT_MS,
3309
3636
  thresholdNetworkUrl,
3310
3637
  body,
3311
- attemptIndex
3638
+ attemptIndex,
3639
+ lastKnownErrorMessage: last404ApiErrorMessage
3312
3640
  });
3313
3641
  onPoll?.({
3314
3642
  operation: "sealoutput",
@@ -3386,15 +3714,10 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId, overallStart
3386
3714
  });
3387
3715
  }
3388
3716
  if (!response.ok) {
3389
- let errorMessage = `HTTP ${response.status}`;
3390
- try {
3391
- const errorBody = await response.json();
3392
- errorMessage = errorBody.error_message || errorBody.message || errorMessage;
3393
- } catch {
3394
- errorMessage = response.statusText || errorMessage;
3395
- }
3717
+ const { apiErrorCode, errorMessage } = await parseApiErrorResponseBody(response);
3396
3718
  throw new CofheError({
3397
- code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
3719
+ code: mapApiErrorCodeToCofheErrorCode(apiErrorCode, "SEAL_OUTPUT_FAILED" /* SealOutputFailed */),
3720
+ apiErrorCode,
3398
3721
  message: `sealOutput status poll failed: ${errorMessage}`,
3399
3722
  context: {
3400
3723
  thresholdNetworkUrl,
@@ -3438,7 +3761,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId, overallStart
3438
3761
  });
3439
3762
  }
3440
3763
  async function tnSealOutputV2(params) {
3441
- const { thresholdNetworkUrl, ctHash, chainId, permission, retry404TimeoutMs, onPoll } = params;
3764
+ const { thresholdNetworkUrl, ctHash, chainId, acp, retry404TimeoutMs, onPoll } = params;
3442
3765
  const normalized404RetryTimeoutMs = normalize404RetryTimeoutMs({
3443
3766
  timeoutMs: retry404TimeoutMs,
3444
3767
  operationLabel: "sealOutput",
@@ -3449,7 +3772,7 @@ async function tnSealOutputV2(params) {
3449
3772
  thresholdNetworkUrl,
3450
3773
  ctHash,
3451
3774
  chainId,
3452
- permission,
3775
+ acp,
3453
3776
  overallStartTime,
3454
3777
  normalized404RetryTimeoutMs,
3455
3778
  onPoll
@@ -3465,8 +3788,8 @@ var DEFAULT_404_RETRY_TIMEOUT_MS2 = 1e4;
3465
3788
  var DecryptForViewBuilder = class extends BaseBuilder {
3466
3789
  ctHash;
3467
3790
  utype;
3468
- permitHash;
3469
- permit;
3791
+ acpHash;
3792
+ acp;
3470
3793
  pollCallback;
3471
3794
  retry404TimeoutMs = DEFAULT_404_RETRY_TIMEOUT_MS2;
3472
3795
  constructor(params) {
@@ -3480,11 +3803,11 @@ var DecryptForViewBuilder = class extends BaseBuilder {
3480
3803
  });
3481
3804
  this.ctHash = params.ctHash;
3482
3805
  this.utype = params.utype;
3483
- this.permitHash = params.permitHash;
3484
- this.permit = params.permit;
3806
+ this.acpHash = params.acpHash;
3807
+ this.acp = params.acp;
3485
3808
  }
3486
3809
  /**
3487
- * @param chainId - Chain to decrypt values from. Used to fetch the threshold network URL and use the correct permit.
3810
+ * @param chainId - Chain to decrypt values from. Used to fetch the threshold network URL and use the correct acp.
3488
3811
  *
3489
3812
  * If not provided, the chainId will be fetched from the connected publicClient.
3490
3813
  *
@@ -3505,7 +3828,7 @@ var DecryptForViewBuilder = class extends BaseBuilder {
3505
3828
  return this.chainId;
3506
3829
  }
3507
3830
  /**
3508
- * @param account - Account to decrypt values from. Used to fetch the correct permit.
3831
+ * @param account - Account to decrypt values from. Used to fetch the correct acp.
3509
3832
  *
3510
3833
  * If not provided, the account will be fetched from the connected walletClient.
3511
3834
  *
@@ -3542,61 +3865,61 @@ var DecryptForViewBuilder = class extends BaseBuilder {
3542
3865
  this.retry404TimeoutMs = timeoutMs;
3543
3866
  return this;
3544
3867
  }
3545
- withPermit(permitOrPermitHash) {
3546
- if (typeof permitOrPermitHash === "string") {
3547
- this.permitHash = permitOrPermitHash;
3548
- this.permit = void 0;
3549
- } else if (permitOrPermitHash === void 0) {
3550
- this.permitHash = void 0;
3551
- this.permit = void 0;
3868
+ withACP(acpOrACPHash) {
3869
+ if (typeof acpOrACPHash === "string") {
3870
+ this.acpHash = acpOrACPHash;
3871
+ this.acp = void 0;
3872
+ } else if (acpOrACPHash === void 0) {
3873
+ this.acpHash = void 0;
3874
+ this.acp = void 0;
3552
3875
  } else {
3553
- this.permit = permitOrPermitHash;
3554
- this.permitHash = void 0;
3876
+ this.acp = acpOrACPHash;
3877
+ this.acpHash = void 0;
3555
3878
  }
3556
3879
  return this;
3557
3880
  }
3558
3881
  /**
3559
- * @param permitHash - Permit hash to decrypt values from. Used to fetch the correct permit.
3882
+ * @param acpHash - ACP hash to decrypt values from. Used to fetch the correct acp.
3560
3883
  *
3561
- * If not provided, the active permit for the chainId and account will be used.
3562
- * If `setPermit()` is called, it will be used regardless of chainId, account, or permitHash.
3884
+ * If not provided, the active acp for the chainId and account will be used.
3885
+ * If `setACP()` is called, it will be used regardless of chainId, account, or acpHash.
3563
3886
  *
3564
3887
  * Example:
3565
3888
  * ```typescript
3566
3889
  * const unsealed = await client.decryptForView(ctHash, utype)
3567
- * .setPermitHash('0x1234567890123456789012345678901234567890')
3890
+ * .setACPHash('0x1234567890123456789012345678901234567890')
3568
3891
  * .execute();
3569
3892
  * ```
3570
3893
  *
3571
3894
  * @returns The chainable DecryptForViewBuilder instance.
3572
3895
  */
3573
- /** @deprecated Use `withPermit(permitHash)` instead. */
3574
- setPermitHash(permitHash) {
3575
- return this.withPermit(permitHash);
3896
+ /** @deprecated Use `withACP(acpHash)` instead. */
3897
+ setACPHash(acpHash) {
3898
+ return this.withACP(acpHash);
3576
3899
  }
3577
- getPermitHash() {
3578
- return this.permitHash;
3900
+ getACPHash() {
3901
+ return this.acpHash;
3579
3902
  }
3580
3903
  /**
3581
- * @param permit - Permit to decrypt values with. If provided, it will be used regardless of chainId, account, or permitHash.
3904
+ * @param acp - ACP to decrypt values with. If provided, it will be used regardless of chainId, account, or acpHash.
3582
3905
  *
3583
- * If not provided, the permit will be determined by chainId, account, and permitHash.
3906
+ * If not provided, the acp will be determined by chainId, account, and acpHash.
3584
3907
  *
3585
3908
  * Example:
3586
3909
  * ```typescript
3587
3910
  * const unsealed = await client.decryptForView(ctHash, utype)
3588
- * .setPermit(permit)
3911
+ * .setACP(acp)
3589
3912
  * .execute();
3590
3913
  * ```
3591
3914
  *
3592
3915
  * @returns The chainable DecryptForViewBuilder instance.
3593
3916
  */
3594
- /** @deprecated Use `withPermit(permit)` instead. */
3595
- setPermit(permit) {
3596
- return this.withPermit(permit);
3917
+ /** @deprecated Use `withACP(acp)` instead. */
3918
+ setACP(acp) {
3919
+ return this.withACP(acp);
3597
3920
  }
3598
- getPermit() {
3599
- return this.permit;
3921
+ getACP() {
3922
+ return this.acp;
3600
3923
  }
3601
3924
  async getThresholdNetworkUrl() {
3602
3925
  this.assertChainId();
@@ -3612,77 +3935,77 @@ var DecryptForViewBuilder = class extends BaseBuilder {
3612
3935
  }
3613
3936
  });
3614
3937
  }
3615
- async getResolvedPermit() {
3616
- if (this.permit)
3617
- return this.permit;
3938
+ async getResolvedACP() {
3939
+ if (this.acp)
3940
+ return this.acp;
3618
3941
  this.assertChainId();
3619
3942
  this.assertAccount();
3620
- if (this.permitHash) {
3621
- const permit2 = await permits.getPermit(this.chainId, this.account, this.permitHash);
3622
- if (!permit2) {
3943
+ if (this.acpHash) {
3944
+ const acp2 = await acps.getACP(this.chainId, this.account, this.acpHash);
3945
+ if (!acp2) {
3623
3946
  throw new CofheError({
3624
- code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
3625
- message: `Permit with hash <${this.permitHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
3626
- hint: "Ensure the permit exists and is valid.",
3947
+ code: "ACP_NOT_FOUND" /* ACPNotFound */,
3948
+ message: `ACP with hash <${this.acpHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
3949
+ hint: "Ensure the acp exists and is valid.",
3627
3950
  context: {
3628
3951
  chainId: this.chainId,
3629
3952
  account: this.account,
3630
- permitHash: this.permitHash
3953
+ acpHash: this.acpHash
3631
3954
  }
3632
3955
  });
3633
3956
  }
3634
- return permit2;
3957
+ return acp2;
3635
3958
  }
3636
- const permit = await permits.getActivePermit(this.chainId, this.account);
3637
- if (!permit) {
3959
+ const acp = await acps.getActiveACP(this.chainId, this.account);
3960
+ if (!acp) {
3638
3961
  throw new CofheError({
3639
- code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
3640
- message: `Active permit not found for chainId <${this.chainId}> and account <${this.account}>`,
3641
- hint: "Ensure a permit exists for this account on this chain.",
3962
+ code: "ACP_NOT_FOUND" /* ACPNotFound */,
3963
+ message: `Active acp not found for chainId <${this.chainId}> and account <${this.account}>`,
3964
+ hint: "Ensure an ACP exists for this account on this chain.",
3642
3965
  context: {
3643
3966
  chainId: this.chainId,
3644
3967
  account: this.account
3645
3968
  }
3646
3969
  });
3647
3970
  }
3648
- return permit;
3971
+ return acp;
3649
3972
  }
3650
3973
  /**
3651
3974
  * On hardhat, interact with MockZkVerifier contract instead of CoFHE
3652
3975
  */
3653
- async mocksSealOutput(permit) {
3976
+ async mocksSealOutput(acp) {
3654
3977
  this.assertPublicClient();
3655
3978
  const mocksDecryptDelay = this.config.mocks.decryptDelay;
3656
3979
  if (mocksDecryptDelay > 0)
3657
3980
  await sleep(mocksDecryptDelay);
3658
- return cofheMocksDecryptForView(this.ctHash, this.utype, permit, this.publicClient);
3981
+ return cofheMocksDecryptForView(this.ctHash, this.utype, acp, this.publicClient);
3659
3982
  }
3660
3983
  /**
3661
3984
  * In the production context, perform a true decryption with the CoFHE coprocessor.
3662
3985
  */
3663
- async productionSealOutput(permit) {
3986
+ async productionSealOutput(acp) {
3664
3987
  this.assertChainId();
3665
3988
  this.assertPublicClient();
3666
3989
  const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
3667
- const permission = PermitUtils.getPermission(permit, true);
3990
+ const wireAcp = ACPUtils.getPublic(acp, true);
3668
3991
  const sealed = await tnSealOutputV2({
3669
3992
  ctHash: this.ctHash,
3670
3993
  chainId: this.chainId,
3671
- permission,
3994
+ acp: wireAcp,
3672
3995
  thresholdNetworkUrl,
3673
3996
  retry404TimeoutMs: this.retry404TimeoutMs,
3674
3997
  onPoll: this.pollCallback
3675
3998
  });
3676
- return PermitUtils.unseal(permit, sealed);
3999
+ return ACPUtils.unseal(acp, sealed);
3677
4000
  }
3678
4001
  /**
3679
4002
  * Final step of the decryption process. MUST BE CALLED LAST IN THE CHAIN.
3680
4003
  *
3681
4004
  * This will:
3682
- * - Use a permit based on provided permit OR chainId + account + permitHash
3683
- * - Check permit validity
3684
- * - Call CoFHE `/sealoutput` with the permit, which returns a sealed (encrypted) item
3685
- * - Unseal the sealed item with the permit
4005
+ * - Use an ACP based on provided acp OR chainId + account + acpHash
4006
+ * - Check acp validity
4007
+ * - Call CoFHE `/sealoutput` with the acp, which returns a sealed (encrypted) item
4008
+ * - Unseal the sealed item with the acp
3686
4009
  * - Return the unsealed item
3687
4010
  *
3688
4011
  * Example:
@@ -3690,7 +4013,7 @@ var DecryptForViewBuilder = class extends BaseBuilder {
3690
4013
  * const unsealed = await client.decryptForView(ctHash, utype)
3691
4014
  * .setChainId(11155111) // optional
3692
4015
  * .setAccount('0x123...890') // optional
3693
- * .withPermit() // optional
4016
+ * .withACP() // optional
3694
4017
  * .execute(); // execute
3695
4018
  * ```
3696
4019
  *
@@ -3698,14 +4021,14 @@ var DecryptForViewBuilder = class extends BaseBuilder {
3698
4021
  */
3699
4022
  async execute() {
3700
4023
  this.validateUtypeOrThrow();
3701
- const permit = await this.getResolvedPermit();
3702
- PermitUtils.validate(permit);
3703
- const chainId = permit._signedDomain.chainId;
4024
+ const acp = await this.getResolvedACP();
4025
+ ACPUtils.validate(acp);
4026
+ const chainId = acp._signedDomain.chainId;
3704
4027
  let unsealed;
3705
4028
  if (chainId === hardhat2.id) {
3706
- unsealed = await this.mocksSealOutput(permit);
4029
+ unsealed = await this.mocksSealOutput(acp);
3707
4030
  } else {
3708
- unsealed = await this.productionSealOutput(permit);
4031
+ unsealed = await this.productionSealOutput(acp);
3709
4032
  }
3710
4033
  return convertViaUtype(this.utype, unsealed);
3711
4034
  }
@@ -3713,28 +4036,28 @@ var DecryptForViewBuilder = class extends BaseBuilder {
3713
4036
  var UINT_TYPE_MASK = 0x7fn;
3714
4037
  var TYPE_BYTE_OFFSET = 8n;
3715
4038
  var getEncryptionTypeFromCtHash = (ctHash) => Number(ctHash >> TYPE_BYTE_OFFSET & UINT_TYPE_MASK);
3716
- async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient) {
4039
+ async function cofheMocksDecryptForTx(ctHash, utype, acp, publicClient) {
3717
4040
  let allowed;
3718
4041
  let error;
3719
4042
  let decryptedValue;
3720
- if (permit !== null) {
3721
- let permission = PermitUtils.getPermission(permit, true);
4043
+ if (acp !== null) {
4044
+ const wireAcp = ACPUtils.getPublic(acp, true);
3722
4045
  const permissionWithBigInts = {
3723
- ...permission,
3724
- expiration: BigInt(permission.expiration),
3725
- validatorId: BigInt(permission.validatorId)
4046
+ ...wireAcp,
4047
+ expiration: BigInt(wireAcp.expiration),
4048
+ revokerData: BigInt(wireAcp.revokerData)
3726
4049
  };
3727
4050
  [allowed, error, decryptedValue] = await publicClient.readContract({
3728
4051
  address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
3729
4052
  abi: MockThresholdNetworkAbi,
3730
- functionName: "decryptForTxWithPermit",
4053
+ functionName: "decryptForTxWithACP",
3731
4054
  args: [BigInt(ctHash), permissionWithBigInts]
3732
4055
  });
3733
4056
  } else {
3734
4057
  [allowed, error, decryptedValue] = await publicClient.readContract({
3735
4058
  address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
3736
4059
  abi: MockThresholdNetworkAbi,
3737
- functionName: "decryptForTxWithoutPermit",
4060
+ functionName: "decryptForTxWithoutACP",
3738
4061
  args: [BigInt(ctHash)]
3739
4062
  });
3740
4063
  }
@@ -3769,62 +4092,6 @@ async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient) {
3769
4092
  signature
3770
4093
  };
3771
4094
  }
3772
- function normalizeTnSignature(signature) {
3773
- if (typeof signature !== "string") {
3774
- throw new CofheError({
3775
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
3776
- message: "decrypt response missing signature",
3777
- context: {
3778
- signature
3779
- }
3780
- });
3781
- }
3782
- const trimmed = signature.trim();
3783
- if (trimmed.length === 0) {
3784
- throw new CofheError({
3785
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
3786
- message: "decrypt response returned empty signature"
3787
- });
3788
- }
3789
- const prefixed = trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
3790
- const parsed = viem.parseSignature(prefixed);
3791
- return viem.serializeSignature(parsed);
3792
- }
3793
- function parseDecryptedBytesToBigInt(decrypted) {
3794
- if (!Array.isArray(decrypted)) {
3795
- throw new CofheError({
3796
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
3797
- message: "decrypt response field <decrypted> must be a byte array",
3798
- context: {
3799
- decrypted
3800
- }
3801
- });
3802
- }
3803
- if (decrypted.length === 0) {
3804
- throw new CofheError({
3805
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
3806
- message: "decrypt response field <decrypted> was an empty byte array",
3807
- context: {
3808
- decrypted
3809
- }
3810
- });
3811
- }
3812
- let hex = "";
3813
- for (const b of decrypted) {
3814
- if (typeof b !== "number" || !Number.isInteger(b) || b < 0 || b > 255) {
3815
- throw new CofheError({
3816
- code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
3817
- message: "decrypt response field <decrypted> contained a non-byte value",
3818
- context: {
3819
- badElement: b,
3820
- decrypted
3821
- }
3822
- });
3823
- }
3824
- hex += b.toString(16).padStart(2, "0");
3825
- }
3826
- return BigInt(`0x${hex}`);
3827
- }
3828
4095
 
3829
4096
  // core/decrypt/tnDecryptV2.ts
3830
4097
  var POLL_INTERVAL_MS2 = 1e3;
@@ -3946,15 +4213,16 @@ function assertDecryptStatusResponseV2(value) {
3946
4213
  }
3947
4214
  return value;
3948
4215
  }
3949
- async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, permission, overallStartTime, retry404TimeoutMs, onPoll) {
4216
+ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, acp, overallStartTime, retry404TimeoutMs, onPoll) {
3950
4217
  const body = {
3951
4218
  ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
3952
4219
  host_chain_id: chainId
3953
4220
  };
3954
- if (permission) {
3955
- body.permit = permission;
4221
+ if (acp) {
4222
+ body.acp = acp;
3956
4223
  }
3957
4224
  let attemptIndex = 0;
4225
+ let last404ApiErrorMessage;
3958
4226
  for (; ; ) {
3959
4227
  let response;
3960
4228
  try {
@@ -3982,16 +4250,19 @@ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, perm
3982
4250
  }
3983
4251
  });
3984
4252
  }
3985
- const responseClassification = await classifySubmitResponse({ response });
4253
+ const responseClassification = await classifySubmitResponse({
4254
+ response,
4255
+ fallbackErrorCode: "DECRYPT_FAILED" /* DecryptFailed */
4256
+ });
3986
4257
  if (responseClassification.kind === "fatal-http") {
3987
4258
  throw new CofheError({
3988
- code: "DECRYPT_FAILED" /* DecryptFailed */,
4259
+ code: responseClassification.cofheErrorCode,
4260
+ apiErrorCode: responseClassification.apiErrorCode,
3989
4261
  message: `decrypt request failed: ${responseClassification.errorMessage}`,
3990
4262
  hint: "Check the threshold network URL and request parameters.",
3991
4263
  context: {
3992
4264
  thresholdNetworkUrl,
3993
- status: response.status,
3994
- statusText: response.statusText,
4265
+ status: responseClassification.status,
3995
4266
  body,
3996
4267
  attemptIndex
3997
4268
  }
@@ -4039,6 +4310,9 @@ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, perm
4039
4310
  }
4040
4311
  });
4041
4312
  }
4313
+ if (responseClassification.status === 404) {
4314
+ last404ApiErrorMessage = responseClassification.apiErrorMessage;
4315
+ }
4042
4316
  const elapsedMs = Date.now() - overallStartTime;
4043
4317
  throwIfSubmitRetryTimedOut({
4044
4318
  operationLabel: "decrypt",
@@ -4049,7 +4323,8 @@ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, perm
4049
4323
  overallTimeoutMs: DECRYPT_TIMEOUT_MS,
4050
4324
  thresholdNetworkUrl,
4051
4325
  body,
4052
- attemptIndex
4326
+ attemptIndex,
4327
+ lastKnownErrorMessage: last404ApiErrorMessage
4053
4328
  });
4054
4329
  onPoll?.({
4055
4330
  operation: "decrypt",
@@ -4127,17 +4402,10 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId, overallStartT
4127
4402
  });
4128
4403
  }
4129
4404
  if (!response.ok) {
4130
- let errorMessage = `HTTP ${response.status}`;
4131
- try {
4132
- const errorBody = await response.json();
4133
- const maybeMessage = errorBody.error_message || errorBody.message;
4134
- if (typeof maybeMessage === "string" && maybeMessage.length > 0)
4135
- errorMessage = maybeMessage;
4136
- } catch {
4137
- errorMessage = response.statusText || errorMessage;
4138
- }
4405
+ const { apiErrorCode, errorMessage } = await parseApiErrorResponseBody(response);
4139
4406
  throw new CofheError({
4140
- code: "DECRYPT_FAILED" /* DecryptFailed */,
4407
+ code: mapApiErrorCodeToCofheErrorCode(apiErrorCode, "DECRYPT_FAILED" /* DecryptFailed */),
4408
+ apiErrorCode,
4141
4409
  message: `decrypt status poll failed: ${errorMessage}`,
4142
4410
  context: {
4143
4411
  thresholdNetworkUrl,
@@ -4182,7 +4450,7 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId, overallStartT
4182
4450
  });
4183
4451
  }
4184
4452
  async function tnDecryptV2(params) {
4185
- const { thresholdNetworkUrl, ctHash, chainId, permission, retry404TimeoutMs, onPoll } = params;
4453
+ const { thresholdNetworkUrl, ctHash, chainId, acp, retry404TimeoutMs, onPoll } = params;
4186
4454
  const normalized404RetryTimeoutMs = normalize404RetryTimeoutMs({
4187
4455
  timeoutMs: retry404TimeoutMs,
4188
4456
  operationLabel: "decrypt",
@@ -4193,7 +4461,7 @@ async function tnDecryptV2(params) {
4193
4461
  thresholdNetworkUrl,
4194
4462
  ctHash,
4195
4463
  chainId,
4196
- permission,
4464
+ acp,
4197
4465
  overallStartTime,
4198
4466
  normalized404RetryTimeoutMs,
4199
4467
  onPoll
@@ -4208,9 +4476,9 @@ async function tnDecryptV2(params) {
4208
4476
  var DEFAULT_404_RETRY_TIMEOUT_MS3 = 1e4;
4209
4477
  var DecryptForTxBuilder = class extends BaseBuilder {
4210
4478
  ctHash;
4211
- permitHash;
4212
- permit;
4213
- permitSelection = "unset";
4479
+ acpHash;
4480
+ acp;
4481
+ acpSelection = "unset";
4214
4482
  pollCallback;
4215
4483
  retry404TimeoutMs = DEFAULT_404_RETRY_TIMEOUT_MS3;
4216
4484
  constructor(params) {
@@ -4255,137 +4523,137 @@ var DecryptForTxBuilder = class extends BaseBuilder {
4255
4523
  this.retry404TimeoutMs = timeoutMs;
4256
4524
  return this;
4257
4525
  }
4258
- withPermit(permitOrPermitHash) {
4259
- if (this.permitSelection === "with-permit") {
4526
+ withACP(acpOrACPHash) {
4527
+ if (this.acpSelection === "with-acp") {
4260
4528
  throw new CofheError({
4261
4529
  code: "INTERNAL_ERROR" /* InternalError */,
4262
- message: "decryptForTx: withPermit() can only be selected once.",
4263
- hint: "Choose the permit mode once. If you need a different permit, start a new decryptForTx() builder chain."
4530
+ message: "decryptForTx: withACP() can only be selected once.",
4531
+ hint: "Choose the acp mode once. If you need a different acp, start a new decryptForTx() builder chain."
4264
4532
  });
4265
4533
  }
4266
- if (this.permitSelection === "without-permit") {
4534
+ if (this.acpSelection === "without-acp") {
4267
4535
  throw new CofheError({
4268
4536
  code: "INTERNAL_ERROR" /* InternalError */,
4269
- message: "decryptForTx: cannot call withPermit() after withoutPermit() has been selected.",
4270
- hint: "Choose exactly one permit mode: either call .withPermit(...) or .withoutPermit(), but not both."
4537
+ message: "decryptForTx: cannot call withACP() after withoutACP() has been selected.",
4538
+ hint: "Choose exactly one acp mode: either call .withACP(...) or .withoutACP(), but not both."
4271
4539
  });
4272
4540
  }
4273
- this.permitSelection = "with-permit";
4274
- if (typeof permitOrPermitHash === "string") {
4275
- this.permitHash = permitOrPermitHash;
4276
- this.permit = void 0;
4277
- } else if (permitOrPermitHash === void 0) {
4278
- this.permitHash = void 0;
4279
- this.permit = void 0;
4541
+ this.acpSelection = "with-acp";
4542
+ if (typeof acpOrACPHash === "string") {
4543
+ this.acpHash = acpOrACPHash;
4544
+ this.acp = void 0;
4545
+ } else if (acpOrACPHash === void 0) {
4546
+ this.acpHash = void 0;
4547
+ this.acp = void 0;
4280
4548
  } else {
4281
- this.permit = permitOrPermitHash;
4282
- this.permitHash = void 0;
4549
+ this.acp = acpOrACPHash;
4550
+ this.acpHash = void 0;
4283
4551
  }
4284
4552
  return this;
4285
4553
  }
4286
4554
  /**
4287
- * Select "no permit" mode.
4555
+ * Select "no acp" mode.
4288
4556
  *
4289
- * This uses global allowance (no permit required) and sends an empty permission payload to `/decrypt`.
4557
+ * This uses global allowance (no acp required) and sends an empty permission payload to `/decrypt`.
4290
4558
  */
4291
- withoutPermit() {
4292
- if (this.permitSelection === "without-permit") {
4559
+ withoutACP() {
4560
+ if (this.acpSelection === "without-acp") {
4293
4561
  throw new CofheError({
4294
4562
  code: "INTERNAL_ERROR" /* InternalError */,
4295
- message: "decryptForTx: withoutPermit() can only be selected once.",
4296
- hint: "Choose the permit mode once. If you need a different mode, start a new decryptForTx() builder chain."
4563
+ message: "decryptForTx: withoutACP() can only be selected once.",
4564
+ hint: "Choose the acp mode once. If you need a different mode, start a new decryptForTx() builder chain."
4297
4565
  });
4298
4566
  }
4299
- if (this.permitSelection === "with-permit") {
4567
+ if (this.acpSelection === "with-acp") {
4300
4568
  throw new CofheError({
4301
4569
  code: "INTERNAL_ERROR" /* InternalError */,
4302
- message: "decryptForTx: cannot call withoutPermit() after withPermit() has been selected.",
4303
- hint: "Choose exactly one permit mode: either call .withPermit(...) or .withoutPermit(), but not both."
4570
+ message: "decryptForTx: cannot call withoutACP() after withACP() has been selected.",
4571
+ hint: "Choose exactly one acp mode: either call .withACP(...) or .withoutACP(), but not both."
4304
4572
  });
4305
4573
  }
4306
- this.permitSelection = "without-permit";
4307
- this.permitHash = void 0;
4308
- this.permit = void 0;
4574
+ this.acpSelection = "without-acp";
4575
+ this.acpHash = void 0;
4576
+ this.acp = void 0;
4309
4577
  return this;
4310
4578
  }
4311
- getPermit() {
4312
- return this.permit;
4579
+ getACP() {
4580
+ return this.acp;
4313
4581
  }
4314
- getPermitHash() {
4315
- return this.permitHash;
4582
+ getACPHash() {
4583
+ return this.acpHash;
4316
4584
  }
4317
4585
  async getThresholdNetworkUrl() {
4318
4586
  this.assertChainId();
4319
4587
  return getThresholdNetworkUrlOrThrow(this.config, this.chainId);
4320
4588
  }
4321
- async getResolvedPermit() {
4322
- if (this.permitSelection === "unset") {
4589
+ async getResolvedACP() {
4590
+ if (this.acpSelection === "unset") {
4323
4591
  throw new CofheError({
4324
4592
  code: "INTERNAL_ERROR" /* InternalError */,
4325
- message: "decryptForTx: missing permit selection; call withPermit(...) or withoutPermit() before execute().",
4326
- hint: "Call .withPermit() to use the active permit, or .withoutPermit() for global allowance."
4593
+ message: "decryptForTx: missing acp selection; call withACP(...) or withoutACP() before execute().",
4594
+ hint: "Call .withACP() to use the active acp, or .withoutACP() for global allowance."
4327
4595
  });
4328
4596
  }
4329
- if (this.permitSelection === "without-permit") {
4597
+ if (this.acpSelection === "without-acp") {
4330
4598
  return null;
4331
4599
  }
4332
- if (this.permit)
4333
- return this.permit;
4600
+ if (this.acp)
4601
+ return this.acp;
4334
4602
  this.assertChainId();
4335
4603
  this.assertAccount();
4336
- if (this.permitHash) {
4337
- const permit2 = await permits.getPermit(this.chainId, this.account, this.permitHash);
4338
- if (!permit2) {
4604
+ if (this.acpHash) {
4605
+ const acp2 = await acps.getACP(this.chainId, this.account, this.acpHash);
4606
+ if (!acp2) {
4339
4607
  throw new CofheError({
4340
- code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
4341
- message: `Permit with hash <${this.permitHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
4342
- hint: "Ensure the permit exists and is valid.",
4608
+ code: "ACP_NOT_FOUND" /* ACPNotFound */,
4609
+ message: `ACP with hash <${this.acpHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
4610
+ hint: "Ensure the acp exists and is valid.",
4343
4611
  context: {
4344
4612
  chainId: this.chainId,
4345
4613
  account: this.account,
4346
- permitHash: this.permitHash
4614
+ acpHash: this.acpHash
4347
4615
  }
4348
4616
  });
4349
4617
  }
4350
- return permit2;
4618
+ return acp2;
4351
4619
  }
4352
- const permit = await permits.getActivePermit(this.chainId, this.account);
4353
- if (!permit) {
4620
+ const acp = await acps.getActiveACP(this.chainId, this.account);
4621
+ if (!acp) {
4354
4622
  throw new CofheError({
4355
- code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
4356
- message: `Active permit not found for chainId <${this.chainId}> and account <${this.account}>`,
4357
- hint: "Create a permit (e.g. client.permits.createSelf(...)) and/or set it active (client.permits.selectActivePermit(hash)).",
4623
+ code: "ACP_NOT_FOUND" /* ACPNotFound */,
4624
+ message: `Active acp not found for chainId <${this.chainId}> and account <${this.account}>`,
4625
+ hint: "Create an ACP (e.g. client.acp.createSelf(...)) and/or set it active (client.acp.selectActiveACP(hash)).",
4358
4626
  context: {
4359
4627
  chainId: this.chainId,
4360
4628
  account: this.account
4361
4629
  }
4362
4630
  });
4363
4631
  }
4364
- return permit;
4632
+ return acp;
4365
4633
  }
4366
4634
  /**
4367
4635
  * On hardhat, interact with MockThresholdNetwork contract
4368
4636
  */
4369
- async mocksDecryptForTx(permit) {
4637
+ async mocksDecryptForTx(acp) {
4370
4638
  this.assertPublicClient();
4371
4639
  const delay = this.config.mocks.decryptDelay;
4372
4640
  if (delay > 0)
4373
4641
  await sleep(delay);
4374
- const result = await cofheMocksDecryptForTx(this.ctHash, 0, permit, this.publicClient);
4642
+ const result = await cofheMocksDecryptForTx(this.ctHash, 0, acp, this.publicClient);
4375
4643
  return result;
4376
4644
  }
4377
4645
  /**
4378
4646
  * In the production context, perform a true decryption with the CoFHE coprocessor.
4379
4647
  */
4380
- async productionDecryptForTx(permit) {
4648
+ async productionDecryptForTx(acp) {
4381
4649
  this.assertChainId();
4382
4650
  this.assertPublicClient();
4383
4651
  const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
4384
- const permission = permit ? PermitUtils.getPermission(permit, true) : null;
4652
+ const wireAcp = acp ? ACPUtils.getPublic(acp, true) : null;
4385
4653
  const { decryptedValue, signature } = await tnDecryptV2({
4386
4654
  ctHash: this.ctHash,
4387
4655
  chainId: this.chainId,
4388
- permission,
4656
+ acp: wireAcp,
4389
4657
  thresholdNetworkUrl,
4390
4658
  retry404TimeoutMs: this.retry404TimeoutMs,
4391
4659
  onPoll: this.pollCallback
@@ -4399,19 +4667,19 @@ var DecryptForTxBuilder = class extends BaseBuilder {
4399
4667
  /**
4400
4668
  * Final step of the decryptForTx process. MUST BE CALLED LAST IN THE CHAIN.
4401
4669
  *
4402
- * You must explicitly choose one permit mode before calling `execute()`:
4403
- * - `withPermit(permit)` / `withPermit(permitHash)` / `withPermit()` (active permit)
4404
- * - `withoutPermit()` (global allowance)
4670
+ * You must explicitly choose one acp mode before calling `execute()`:
4671
+ * - `withACP(acp)` / `withACP(acpHash)` / `withACP()` (active acp)
4672
+ * - `withoutACP()` (global allowance)
4405
4673
  */
4406
4674
  async execute() {
4407
- const permit = await this.getResolvedPermit();
4408
- if (permit !== null) {
4409
- PermitUtils.validate(permit);
4410
- const chainId = permit._signedDomain.chainId;
4675
+ const acp = await this.getResolvedACP();
4676
+ if (acp !== null) {
4677
+ ACPUtils.validate(acp);
4678
+ const chainId = acp._signedDomain.chainId;
4411
4679
  if (chainId === hardhat2.id) {
4412
- return await this.mocksDecryptForTx(permit);
4680
+ return await this.mocksDecryptForTx(acp);
4413
4681
  } else {
4414
- return await this.productionDecryptForTx(permit);
4682
+ return await this.productionDecryptForTx(acp);
4415
4683
  }
4416
4684
  } else {
4417
4685
  if (!this.chainId) {
@@ -4474,6 +4742,21 @@ function createCofheClientBase(opts) {
4474
4742
  const updateConnectState = (partial) => {
4475
4743
  connectStore.setState((state) => ({ ...state, ...partial }));
4476
4744
  };
4745
+ const _resolveSharingRegistry = async (publicClient, chainId) => {
4746
+ const configured = opts.config.acp?.sharingRegistry?.[chainId];
4747
+ if (configured != null)
4748
+ return configured;
4749
+ const registry = (await acps.getAclServedAddresses(publicClient, chainId)).shareRegistry;
4750
+ if (registry == null) {
4751
+ throw new CofheError({
4752
+ code: "MISSING_CONFIG" /* MissingConfig */,
4753
+ message: `No ACP share registry available for chainId <${chainId}>`,
4754
+ 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.",
4755
+ context: { chainId }
4756
+ });
4757
+ }
4758
+ return registry;
4759
+ };
4477
4760
  const _requireConnected = () => {
4478
4761
  const state = connectStore.getState();
4479
4762
  const notConnected = !state.connected || !state.account || !state.chainId || !state.publicClient || !state.walletClient;
@@ -4596,74 +4879,147 @@ function createCofheClientBase(opts) {
4596
4879
  }
4597
4880
  return { chainId: _chainId, account: _account };
4598
4881
  };
4599
- const clientPermits = {
4882
+ const clientACPs = {
4600
4883
  // Pass through store access
4601
- getSnapshot: permits.getSnapshot,
4602
- subscribe: permits.subscribe,
4884
+ getSnapshot: acps.getSnapshot,
4885
+ subscribe: acps.subscribe,
4603
4886
  // Creation methods (require connection)
4604
4887
  createSelf: async (options, clients) => {
4605
4888
  _requireConnected();
4606
4889
  const { publicClient, walletClient } = clients ?? connectStore.getState();
4607
- return permits.createSelf(options, publicClient, walletClient);
4890
+ const chainId = await publicClient.getChainId();
4891
+ return acps.createSelf(
4892
+ await acps.applyACPDefaultsFromChain(options, opts.config.acp, publicClient, chainId),
4893
+ publicClient,
4894
+ walletClient
4895
+ );
4608
4896
  },
4609
4897
  createSharing: async (options, clients) => {
4610
4898
  _requireConnected();
4611
4899
  const { publicClient, walletClient } = clients ?? connectStore.getState();
4612
- return permits.createSharing(options, publicClient, walletClient);
4900
+ const chainId = await publicClient.getChainId();
4901
+ return acps.createSharing(
4902
+ await acps.applyACPDefaultsFromChain(options, opts.config.acp, publicClient, chainId),
4903
+ publicClient,
4904
+ walletClient
4905
+ );
4613
4906
  },
4614
4907
  importShared: async (options, clients) => {
4615
4908
  _requireConnected();
4616
4909
  const { publicClient, walletClient } = clients ?? connectStore.getState();
4617
- return permits.importShared(options, publicClient, walletClient);
4910
+ return acps.importShared(options, publicClient, walletClient);
4618
4911
  },
4619
4912
  // Get or create methods (require connection)
4620
- getOrCreateSelfPermit: async (chainId, account, options) => {
4913
+ getOrCreateSelfACP: async (chainId, account, options) => {
4621
4914
  _requireConnected();
4622
4915
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
4623
4916
  const { publicClient, walletClient } = connectStore.getState();
4624
- return permits.getOrCreateSelfPermit(publicClient, walletClient, _chainId, _account, options);
4917
+ const optionsWithDefaults = await acps.applyACPDefaultsFromChain(
4918
+ options ?? { issuer: _account, name: "Autogenerated Self ACP" },
4919
+ opts.config.acp,
4920
+ publicClient,
4921
+ _chainId
4922
+ );
4923
+ return acps.getOrCreateSelfACP(publicClient, walletClient, _chainId, _account, optionsWithDefaults);
4625
4924
  },
4626
- getOrCreateSharingPermit: async (options, chainId, account) => {
4925
+ getOrCreateSharingACP: async (options, chainId, account) => {
4627
4926
  _requireConnected();
4628
4927
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
4629
4928
  const { publicClient, walletClient } = connectStore.getState();
4630
- return permits.getOrCreateSharingPermit(publicClient, walletClient, options, _chainId, _account);
4929
+ return acps.getOrCreateSharingACP(
4930
+ publicClient,
4931
+ walletClient,
4932
+ await acps.applyACPDefaultsFromChain(options, opts.config.acp, publicClient, _chainId),
4933
+ _chainId,
4934
+ _account
4935
+ );
4936
+ },
4937
+ // Revocation (require connection)
4938
+ revokeACP: async (acp) => {
4939
+ _requireConnected();
4940
+ const { walletClient } = connectStore.getState();
4941
+ return acps.revokeACP(acp, walletClient);
4942
+ },
4943
+ revokeAllACPs: async (revokerContract) => {
4944
+ _requireConnected();
4945
+ const { publicClient, walletClient } = connectStore.getState();
4946
+ return acps.revokeAllACPs(walletClient, publicClient, revokerContract);
4947
+ },
4948
+ isACPRevoked: async (acp) => {
4949
+ _requireConnected();
4950
+ const { publicClient } = connectStore.getState();
4951
+ return acps.isACPRevoked(acp, publicClient);
4952
+ },
4953
+ // On-chain sharing (require connection + config.acp.sharingRegistry)
4954
+ shareOnChain: async (acp) => {
4955
+ _requireConnected();
4956
+ const { publicClient, walletClient } = connectStore.getState();
4957
+ const chainId = await publicClient.getChainId();
4958
+ const sharingRegistry = await _resolveSharingRegistry(publicClient, chainId);
4959
+ return acps.shareOnChain(acp, walletClient, sharingRegistry);
4960
+ },
4961
+ getIncomingShares: async () => {
4962
+ _requireConnected();
4963
+ const { publicClient, walletClient } = connectStore.getState();
4964
+ const chainId = await publicClient.getChainId();
4965
+ const account = walletClient.account.address;
4966
+ const sharingRegistry = await _resolveSharingRegistry(publicClient, chainId);
4967
+ return acps.getIncomingShares(publicClient, sharingRegistry, account);
4968
+ },
4969
+ importFromChain: async (share) => {
4970
+ _requireConnected();
4971
+ const { publicClient, walletClient } = connectStore.getState();
4972
+ return acps.importFromChain(share, publicClient, walletClient);
4973
+ },
4974
+ dismissShare: async (shareId) => {
4975
+ _requireConnected();
4976
+ const { publicClient, walletClient } = connectStore.getState();
4977
+ const chainId = await publicClient.getChainId();
4978
+ const sharingRegistry = await _resolveSharingRegistry(publicClient, chainId);
4979
+ return acps.removeShareOnChain(shareId, walletClient, sharingRegistry);
4980
+ },
4981
+ cancelShare: async (shareId) => {
4982
+ _requireConnected();
4983
+ const { publicClient, walletClient } = connectStore.getState();
4984
+ const chainId = await publicClient.getChainId();
4985
+ const sharingRegistry = await _resolveSharingRegistry(publicClient, chainId);
4986
+ return acps.removeShareOnChain(shareId, walletClient, sharingRegistry);
4631
4987
  },
4632
4988
  // Retrieval methods (auto-fill chainId/account)
4633
- getPermit: (hash, chainId, account) => {
4989
+ getACP: (hash, chainId, account) => {
4634
4990
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
4635
- return permits.getPermit(_chainId, _account, hash);
4991
+ return acps.getACP(_chainId, _account, hash);
4636
4992
  },
4637
- getPermits: (chainId, account) => {
4993
+ getACPs: (chainId, account) => {
4638
4994
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
4639
- return permits.getPermits(_chainId, _account);
4995
+ return acps.getACPs(_chainId, _account);
4640
4996
  },
4641
- getActivePermit: (chainId, account) => {
4997
+ getActiveACP: (chainId, account) => {
4642
4998
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
4643
- return permits.getActivePermit(_chainId, _account);
4999
+ return acps.getActiveACP(_chainId, _account);
4644
5000
  },
4645
- getActivePermitHash: (chainId, account) => {
5001
+ getActiveACPHash: (chainId, account) => {
4646
5002
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
4647
- return permits.getActivePermitHash(_chainId, _account);
5003
+ return acps.getActiveACPHash(_chainId, _account);
4648
5004
  },
4649
5005
  // Mutation methods (auto-fill chainId/account)
4650
- selectActivePermit: (hash, chainId, account) => {
5006
+ selectActiveACP: (hash, chainId, account) => {
4651
5007
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
4652
- return permits.selectActivePermit(_chainId, _account, hash);
5008
+ return acps.selectActiveACP(_chainId, _account, hash);
4653
5009
  },
4654
- removePermit: async (hash, chainId, account) => {
5010
+ removeACP: async (hash, chainId, account) => {
4655
5011
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
4656
- return permits.removePermit(_chainId, _account, hash);
5012
+ return acps.removeACP(_chainId, _account, hash);
4657
5013
  },
4658
- removeActivePermit: async (chainId, account) => {
5014
+ removeActiveACP: async (chainId, account) => {
4659
5015
  const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
4660
- return permits.removeActivePermit(_chainId, _account);
5016
+ return acps.removeActiveACP(_chainId, _account);
4661
5017
  },
4662
5018
  // Utils (no context needed)
4663
- getHash: permits.getHash,
4664
- export: permits.export,
4665
- serialize: permits.serialize,
4666
- deserialize: permits.deserialize
5019
+ getHash: acps.getHash,
5020
+ export: acps.export,
5021
+ serialize: acps.serialize,
5022
+ deserialize: acps.deserialize
4667
5023
  };
4668
5024
  return {
4669
5025
  // Zustand reactive accessors (don't export store directly to prevent mutation)
@@ -4691,7 +5047,7 @@ function createCofheClientBase(opts) {
4691
5047
  decryptHandle: decryptForView,
4692
5048
  decryptForTx,
4693
5049
  verifyDecryptResult: verifyDecryptResult2,
4694
- permits: clientPermits
5050
+ acp: clientACPs
4695
5051
  // Add SDK-specific methods below that require connection
4696
5052
  // Example:
4697
5053
  // async encryptData(data: unknown) {
@@ -4720,7 +5076,7 @@ exports.MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY = MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_
4720
5076
  exports.TASK_MANAGER_ADDRESS = TASK_MANAGER_ADDRESS;
4721
5077
  exports.TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT = TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT;
4722
5078
  exports.TFHE_RS_ZK_MAX_BITS = TFHE_RS_ZK_MAX_BITS;
4723
- exports.assertCorrectEncryptedItemInput = assertCorrectEncryptedItemInput;
5079
+ exports.assertNoRenamedConfigKeys = assertNoRenamedConfigKeys;
4724
5080
  exports.cofheFetch = cofheFetch;
4725
5081
  exports.createCofheClientBase = createCofheClientBase;
4726
5082
  exports.createCofheConfigBase = createCofheConfigBase;