@tokenops/sdk 2.0.0-alpha.1 → 2.0.0-alpha.2

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 (145) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +5 -5
  3. package/dist/{chunk-JZLGCTGK.cjs → chunk-3YHBO2DL.cjs} +2 -2
  4. package/dist/{chunk-H5POPGOZ.js → chunk-44YJPMQC.js} +1 -1
  5. package/dist/{chunk-DZHYSUGY.js → chunk-A4DCEE33.js} +11 -5
  6. package/dist/{chunk-M4IT6DNJ.cjs → chunk-AREQJHKA.cjs} +108 -3
  7. package/dist/chunk-EBLBPUPI.cjs +255 -0
  8. package/dist/chunk-EYDA6Q6C.js +245 -0
  9. package/dist/{chunk-XAYGD4E4.cjs → chunk-FEDX7B6T.cjs} +3 -3
  10. package/dist/{chunk-JQYC66TO.cjs → chunk-FHWSBGWE.cjs} +5 -5
  11. package/dist/{chunk-5576FRT3.cjs → chunk-FT5H2Q7Y.cjs} +11 -5
  12. package/dist/{chunk-456VDDA3.js → chunk-GADGBQJO.js} +78 -25
  13. package/dist/{chunk-6NAVMWZQ.js → chunk-IGO5XSPS.js} +2 -2
  14. package/dist/{chunk-CTED3MTR.cjs → chunk-IUKKNJ2R.cjs} +82 -29
  15. package/dist/{chunk-FGEB7RMY.cjs → chunk-MM5BV5CS.cjs} +4 -4
  16. package/dist/{chunk-335Z2W67.js → chunk-PYYSB5ZN.js} +1 -1
  17. package/dist/{chunk-PUX5VXDB.cjs → chunk-PZZK3O3S.cjs} +1040 -42
  18. package/dist/{chunk-74QFZ5MK.js → chunk-SPLNGUFF.js} +1 -1
  19. package/dist/{chunk-6PXXGACR.cjs → chunk-UHHMVBLU.cjs} +2 -2
  20. package/dist/{chunk-O5676ZWY.js → chunk-VW356KR3.js} +108 -5
  21. package/dist/{chunk-EAJ7SYHE.js → chunk-WJMEBBU7.js} +1 -1
  22. package/dist/{chunk-GKKDAW44.js → chunk-X7WBPCEU.js} +1026 -32
  23. package/dist/core/addresses.d.ts +4 -4
  24. package/dist/core/errors.d.ts +1 -1
  25. package/dist/fhe/types.d.ts +2 -2
  26. package/dist/fhe-airdrop/abis/merkle.d.ts +24 -12
  27. package/dist/fhe-airdrop/advanced/index.cjs +4 -4
  28. package/dist/fhe-airdrop/advanced/index.js +1 -1
  29. package/dist/fhe-airdrop/advanced/react/index.cjs +590 -9
  30. package/dist/fhe-airdrop/advanced/react/index.d.cts +34 -0
  31. package/dist/fhe-airdrop/advanced/react/index.d.ts +34 -0
  32. package/dist/fhe-airdrop/advanced/react/index.js +561 -7
  33. package/dist/fhe-airdrop/advanced/react/useClearCompliancePolicy.d.ts +28 -0
  34. package/dist/fhe-airdrop/advanced/react/useClearUpgradeabilityPolicy.d.ts +26 -0
  35. package/dist/fhe-airdrop/advanced/react/useDisableCustomFee.d.ts +25 -0
  36. package/dist/fhe-airdrop/advanced/react/useEcdsaInitCodeHash.d.ts +30 -0
  37. package/dist/fhe-airdrop/advanced/react/useFactoryComplianceDelegate.d.ts +25 -0
  38. package/dist/fhe-airdrop/advanced/react/useFactoryCompliancePolicy.d.ts +38 -0
  39. package/dist/fhe-airdrop/advanced/react/useFactoryCustomFee.d.ts +24 -0
  40. package/dist/fhe-airdrop/advanced/react/useFactoryGrantRole.d.ts +32 -0
  41. package/dist/fhe-airdrop/advanced/react/useFactoryHasRole.d.ts +27 -0
  42. package/dist/fhe-airdrop/advanced/react/useFactoryImplementations.d.ts +33 -0
  43. package/dist/fhe-airdrop/advanced/react/useFactoryRenounceRole.d.ts +36 -0
  44. package/dist/fhe-airdrop/advanced/react/useFactoryRevokeRole.d.ts +35 -0
  45. package/dist/fhe-airdrop/advanced/react/useFactoryRoleConstants.d.ts +46 -0
  46. package/dist/fhe-airdrop/advanced/react/useFactoryRoleMembers.d.ts +47 -0
  47. package/dist/fhe-airdrop/advanced/react/useFactoryUpgradeabilityPolicy.d.ts +39 -0
  48. package/dist/fhe-airdrop/advanced/react/useMerkleInitCodeHash.d.ts +24 -0
  49. package/dist/fhe-airdrop/advanced/react/useSetComplianceDelegate.d.ts +33 -0
  50. package/dist/fhe-airdrop/advanced/react/useSetComplianceManagerImpl.d.ts +27 -0
  51. package/dist/fhe-airdrop/advanced/react/useSetCompliancePolicy.d.ts +28 -0
  52. package/dist/fhe-airdrop/advanced/react/useSetCustomFee.d.ts +28 -0
  53. package/dist/fhe-airdrop/advanced/react/useSetDefaultDelegateToCompliance.d.ts +31 -0
  54. package/dist/fhe-airdrop/advanced/react/useSetDefaultGasFee.d.ts +28 -0
  55. package/dist/fhe-airdrop/advanced/react/useSetDefaultUpgradeable.d.ts +27 -0
  56. package/dist/fhe-airdrop/advanced/react/useSetEcdsaImplementation.d.ts +34 -0
  57. package/dist/fhe-airdrop/advanced/react/useSetFeeCollector.d.ts +27 -0
  58. package/dist/fhe-airdrop/advanced/react/useSetMerkleImplementation.d.ts +30 -0
  59. package/dist/fhe-airdrop/advanced/react/useSetUpgradeabilityPolicy.d.ts +31 -0
  60. package/dist/fhe-airdrop/airdrop-base.d.ts +8 -0
  61. package/dist/fhe-airdrop/campaign.d.ts +61 -20
  62. package/dist/fhe-airdrop/constants.d.ts +1 -1
  63. package/dist/fhe-airdrop/errors.d.ts +28 -0
  64. package/dist/fhe-airdrop/guards.d.ts +46 -2
  65. package/dist/fhe-airdrop/index.cjs +74 -971
  66. package/dist/fhe-airdrop/index.d.cts +2 -2
  67. package/dist/fhe-airdrop/index.d.ts +2 -2
  68. package/dist/fhe-airdrop/index.js +8 -927
  69. package/dist/fhe-airdrop/merkle-tree.d.ts +32 -38
  70. package/dist/fhe-airdrop/merkle.d.ts +52 -31
  71. package/dist/fhe-airdrop/react/_shared.d.ts +13 -0
  72. package/dist/fhe-airdrop/react/index.cjs +934 -84
  73. package/dist/fhe-airdrop/react/index.d.cts +49 -3
  74. package/dist/fhe-airdrop/react/index.d.ts +49 -3
  75. package/dist/fhe-airdrop/react/index.js +825 -22
  76. package/dist/fhe-airdrop/react/keys.d.ts +90 -0
  77. package/dist/fhe-airdrop/react/useAccessEcdsaClaimAmount.d.ts +26 -0
  78. package/dist/fhe-airdrop/react/useAccessMerkleClaimAmount.d.ts +27 -0
  79. package/dist/fhe-airdrop/react/useAddComplianceDelegate.d.ts +37 -0
  80. package/dist/fhe-airdrop/react/useAdminBatchDiscloseBalanceToParties.d.ts +36 -0
  81. package/dist/fhe-airdrop/react/useAdminDiscloseBalanceToParty.d.ts +31 -0
  82. package/dist/fhe-airdrop/react/useAdminGetCurrentBalance.d.ts +27 -0
  83. package/dist/fhe-airdrop/react/useAirdropConfig.d.ts +49 -0
  84. package/dist/fhe-airdrop/react/useAirdropDeploymentMode.d.ts +28 -0
  85. package/dist/fhe-airdrop/react/useAirdropGrantRole.d.ts +35 -0
  86. package/dist/fhe-airdrop/react/useAirdropRenounceRole.d.ts +36 -0
  87. package/dist/fhe-airdrop/react/useAirdropRevokeRole.d.ts +33 -0
  88. package/dist/fhe-airdrop/react/useAirdropRoleAdmin.d.ts +28 -0
  89. package/dist/fhe-airdrop/react/useAirdropRoleConstants.d.ts +67 -0
  90. package/dist/fhe-airdrop/react/useAirdropRoleMembers.d.ts +49 -0
  91. package/dist/fhe-airdrop/react/useAirdropUpgradeToAndCall.d.ts +45 -0
  92. package/dist/fhe-airdrop/react/useBatchDiscloseHandlesToParty.d.ts +32 -0
  93. package/dist/fhe-airdrop/react/useBuildMerkleCampaign.d.ts +68 -0
  94. package/dist/fhe-airdrop/react/useComplianceGrantRole.d.ts +32 -0
  95. package/dist/fhe-airdrop/react/useComplianceHasRole.d.ts +37 -0
  96. package/dist/fhe-airdrop/react/useComplianceInfo.d.ts +50 -0
  97. package/dist/fhe-airdrop/react/useComplianceManagerOf.d.ts +32 -0
  98. package/dist/fhe-airdrop/react/useComplianceRenounceRole.d.ts +38 -0
  99. package/dist/fhe-airdrop/react/useComplianceRevokeRole.d.ts +36 -0
  100. package/dist/fhe-airdrop/react/useComplianceRoleConstants.d.ts +41 -0
  101. package/dist/fhe-airdrop/react/useComplianceRoleMembers.d.ts +45 -0
  102. package/dist/fhe-airdrop/react/useCreateAndFundEcdsaAirdrop.d.ts +55 -0
  103. package/dist/fhe-airdrop/react/useCreateAndFundMerkleAirdrop.d.ts +52 -0
  104. package/dist/fhe-airdrop/react/useDiscloseHandleToParty.d.ts +35 -0
  105. package/dist/fhe-airdrop/react/useEcdsaClaim.d.ts +4 -3
  106. package/dist/fhe-airdrop/react/useEcdsaClaimAndUnwrap.d.ts +27 -0
  107. package/dist/fhe-airdrop/react/useEcdsaDomain.d.ts +41 -0
  108. package/dist/fhe-airdrop/react/useEffectiveDelegateToCompliance.d.ts +26 -0
  109. package/dist/fhe-airdrop/react/useEncryptCampaignAmounts.d.ts +59 -0
  110. package/dist/fhe-airdrop/react/useIsActiveDelegate.d.ts +29 -0
  111. package/dist/fhe-airdrop/react/useIsMerkleRootMutable.d.ts +21 -0
  112. package/dist/fhe-airdrop/react/useIsSignatureValid.d.ts +46 -0
  113. package/dist/fhe-airdrop/react/useMerkleClaim.d.ts +7 -19
  114. package/dist/fhe-airdrop/react/useMerkleClaimAndUnwrap.d.ts +29 -0
  115. package/dist/fhe-airdrop/react/usePlanMerkleCampaign.d.ts +53 -0
  116. package/dist/fhe-airdrop/react/usePreflightClaim.d.ts +46 -0
  117. package/dist/fhe-airdrop/react/usePreflightCreateAirdrop.d.ts +67 -0
  118. package/dist/fhe-airdrop/react/useRescueERC20.d.ts +30 -0
  119. package/dist/fhe-airdrop/react/useRescueOtherConfidentialToken.d.ts +34 -0
  120. package/dist/fhe-airdrop/react/useRevokeComplianceDelegate.d.ts +37 -0
  121. package/dist/fhe-airdrop/react/useRotateMerkleRoot.d.ts +52 -0
  122. package/dist/fhe-airdrop/react/useSignClaimAuthorization.d.ts +42 -0
  123. package/dist/fhe-airdrop/react/useWithdrawGasFee.d.ts +37 -0
  124. package/dist/fhe-airdrop/types.d.ts +14 -1
  125. package/dist/fhe-disperse/index.cjs +21 -21
  126. package/dist/fhe-disperse/index.js +2 -2
  127. package/dist/fhe-disperse/react/index.cjs +22 -22
  128. package/dist/fhe-disperse/react/index.js +3 -3
  129. package/dist/fhe-vesting/advanced/index.cjs +5 -5
  130. package/dist/fhe-vesting/advanced/index.js +3 -3
  131. package/dist/fhe-vesting/advanced/react/index.cjs +7 -7
  132. package/dist/fhe-vesting/advanced/react/index.js +4 -4
  133. package/dist/fhe-vesting/index.cjs +8 -8
  134. package/dist/fhe-vesting/index.js +2 -2
  135. package/dist/fhe-vesting/react/index.cjs +114 -114
  136. package/dist/fhe-vesting/react/index.js +3 -3
  137. package/dist/index.cjs +18 -18
  138. package/dist/index.js +1 -1
  139. package/dist/testnet-faucet/index.cjs +14 -14
  140. package/dist/testnet-faucet/index.js +2 -2
  141. package/dist/testnet-faucet/react/index.cjs +8 -8
  142. package/dist/testnet-faucet/react/index.js +3 -3
  143. package/package.json +1 -1
  144. package/dist/chunk-NCVX3K2N.cjs +0 -161
  145. package/dist/chunk-VP2B4WM2.js +0 -154
@@ -1,8 +1,8 @@
1
- import { assertSupportedChain, airdropProductMapper, assertMerkleModeSupported, assertStockWrapper, assertSaltAvailable, DEDUP_MODE, DEPLOYMENT_MODE } from './chunk-O5676ZWY.js';
1
+ import { assertSupportedChain, airdropProductMapper, assertMerkleModeSupported, assertStockWrapper, assertSaltAvailable, assertMerkleClaimIdentity, DEDUP_MODE, DEPLOYMENT_MODE } from './chunk-VW356KR3.js';
2
2
  import { requireFhevmAclAddress, ACL_ALLOWED_EVENT } from './chunk-ZWXJTBZO.js';
3
3
  import { SDK_VERSION } from './chunk-NWFMBLSQ.js';
4
4
  import { isContractRevert, mapContractRevert } from './chunk-4RAAATVY.js';
5
- import { requireFheAirdropFactoryAddress } from './chunk-DZHYSUGY.js';
5
+ import { requireFheAirdropFactoryAddress } from './chunk-A4DCEE33.js';
6
6
  import { normaliseAddress } from './chunk-ZA673I3O.js';
7
7
  import { asTxHash, asEncryptedHandle, asExternalInputProof, asSignature } from './chunk-KWFFIJYX.js';
8
8
  import { DeploymentAddressUnavailableError, InvalidArgumentError, MissingWalletClientError, MissingAccountError, TokenOpsSdkError, MissingEncryptorError, ReceiptEventNotFoundError } from './chunk-QBJ7O2B4.js';
@@ -5807,6 +5807,17 @@ var AirdropBaseClient = class {
5807
5807
  }
5808
5808
  return acct;
5809
5809
  }
5810
+ /**
5811
+ * The address that will actually send the transaction, as a plain `Address`.
5812
+ *
5813
+ * Needed by any method whose arguments must be validated against the sender before
5814
+ * the write — on the Merkle variant the claim identity, the payout destination and
5815
+ * the submitter are three separate addresses with rules between them.
5816
+ */
5817
+ resolveSender(override, method) {
5818
+ const wallet = this.requireWallet(method);
5819
+ return accountAddress(this.resolveAccount(wallet, override, method));
5820
+ }
5810
5821
  };
5811
5822
  function createAirdropBaseClient(config) {
5812
5823
  return new AirdropBaseClient(config);
@@ -7330,22 +7341,6 @@ var merkleConfidentialAirdropAbi = [
7330
7341
  name: "SafeERC20FailedOperation",
7331
7342
  type: "error"
7332
7343
  },
7333
- {
7334
- inputs: [
7335
- {
7336
- internalType: "bytes32",
7337
- name: "handle",
7338
- type: "bytes32"
7339
- },
7340
- {
7341
- internalType: "address",
7342
- name: "sender",
7343
- type: "address"
7344
- }
7345
- ],
7346
- name: "SenderNotAllowedToUseHandle",
7347
- type: "error"
7348
- },
7349
7344
  {
7350
7345
  inputs: [],
7351
7346
  name: "TokenNotAWrapper",
@@ -7372,11 +7367,32 @@ var merkleConfidentialAirdropAbi = [
7372
7367
  name: "UUPSUnsupportedProxiableUUID",
7373
7368
  type: "error"
7374
7369
  },
7370
+ {
7371
+ inputs: [
7372
+ {
7373
+ internalType: "address",
7374
+ name: "account",
7375
+ type: "address"
7376
+ },
7377
+ {
7378
+ internalType: "address",
7379
+ name: "to",
7380
+ type: "address"
7381
+ }
7382
+ ],
7383
+ name: "UnauthorizedRedirect",
7384
+ type: "error"
7385
+ },
7375
7386
  {
7376
7387
  inputs: [],
7377
7388
  name: "ZamaProtocolUnsupported",
7378
7389
  type: "error"
7379
7390
  },
7391
+ {
7392
+ inputs: [],
7393
+ name: "ZeroAccount",
7394
+ type: "error"
7395
+ },
7380
7396
  {
7381
7397
  inputs: [],
7382
7398
  name: "ZeroAdminGrant",
@@ -7996,6 +8012,11 @@ var merkleConfidentialAirdropAbi = [
7996
8012
  },
7997
8013
  {
7998
8014
  inputs: [
8015
+ {
8016
+ internalType: "address",
8017
+ name: "account",
8018
+ type: "address"
8019
+ },
7999
8020
  {
8000
8021
  internalType: "address",
8001
8022
  name: "to",
@@ -8122,6 +8143,11 @@ var merkleConfidentialAirdropAbi = [
8122
8143
  },
8123
8144
  {
8124
8145
  inputs: [
8146
+ {
8147
+ internalType: "address",
8148
+ name: "account",
8149
+ type: "address"
8150
+ },
8125
8151
  {
8126
8152
  internalType: "externalEuint64",
8127
8153
  name: "inputAmount",
@@ -8674,8 +8700,8 @@ var MerkleAirdropClient = class extends AirdropBaseClient {
8674
8700
  // CLAIM
8675
8701
  // ============================================================
8676
8702
  /**
8677
- * Claim the outstanding amount for a proof-bearing entry, delivering the
8678
- * tokens to `to` (defaults to the sending account).
8703
+ * Claim the outstanding amount for a proof-bearing entry, delivering the tokens to
8704
+ * `to` — which defaults to `entry.account`, the CLAIM IDENTITY, not the sender.
8679
8705
  *
8680
8706
  * Requires `msg.value == gasFee()` exactly — handled for you; see the
8681
8707
  * class TSDoc.
@@ -8692,16 +8718,31 @@ var MerkleAirdropClient = class extends AirdropBaseClient {
8692
8718
  *
8693
8719
  * @throws {@link ClaimNotStartedError} before `startTime`.
8694
8720
  * @throws {@link ClaimWindowClosedError} after `endTime`.
8695
- * @throws {@link InvalidArgumentError} (`argument: "merkleProof"`) when the proof does not verify against
8696
- * the current root — including when `entry.recipient` does not match the sending account.
8721
+ * @throws {@link InvalidArgumentError} (`argument: "entry.boundTo"`) when the entry's proof is bound to
8722
+ * another address, or (`argument: "merkleProof"`) when the proof does not verify against the current root.
8723
+ * @throws {@link UnauthorizedRedirectError} when a third-party submitter passes a `to` other than `entry.account`.
8697
8724
  * @returns The transaction hash.
8698
8725
  */
8699
8726
  async claim(args) {
8700
8727
  return withTelemetry(this.telemetry, `${this.spanPrefix}.claim`, async () => {
8728
+ const submitter = this.resolveSender(args.account, "claim");
8729
+ assertMerkleClaimIdentity({
8730
+ method: "claim",
8731
+ account: args.entry.account,
8732
+ boundTo: args.entry.boundTo,
8733
+ submitter,
8734
+ to: args.to
8735
+ });
8701
8736
  const fee = await this.gasFee();
8702
8737
  return this.write(
8703
8738
  "claim",
8704
- [args.to ?? zeroAddress, args.entry.handle, args.entry.inputProof, args.entry.merkleProof],
8739
+ [
8740
+ args.entry.account,
8741
+ args.to ?? zeroAddress,
8742
+ args.entry.handle,
8743
+ args.entry.inputProof,
8744
+ args.entry.merkleProof
8745
+ ],
8705
8746
  args.account,
8706
8747
  "claim",
8707
8748
  fee
@@ -8717,12 +8758,29 @@ var MerkleAirdropClient = class extends AirdropBaseClient {
8717
8758
  * Same replay/accounting semantics and `msg.value == gasFee()` requirement
8718
8759
  * as {@link claim} — see its `@remarks`.
8719
8760
  *
8761
+ * @remarks
8762
+ * **Self-only by design.** This entrypoint takes no claim identity: releasing an
8763
+ * allocation as a public ERC-20 transfer publishes the amount irreversibly, which is
8764
+ * the recipient's own choice to make. A relayed unwrap is therefore unrepresentable
8765
+ * rather than merely rejected, and an entry whose `account` is not the sender is
8766
+ * refused before the write. A third party can still submit a confidential
8767
+ * {@link claim}.
8768
+ *
8720
8769
  * @returns The transaction hash. The underlying ERC-20 is released later by
8721
8770
  * a separate, permissionless `finalizeUnwrap` — this hash is only the
8722
8771
  * unwrap request.
8723
8772
  */
8724
8773
  async claimAndUnwrap(args) {
8725
8774
  return withTelemetry(this.telemetry, `${this.spanPrefix}.claimAndUnwrap`, async () => {
8775
+ const submitter = this.resolveSender(args.account, "claimAndUnwrap");
8776
+ assertMerkleClaimIdentity({
8777
+ method: "claimAndUnwrap",
8778
+ account: args.entry.account,
8779
+ boundTo: args.entry.boundTo,
8780
+ submitter,
8781
+ to: args.to,
8782
+ entrypoint: "claimAndUnwrap"
8783
+ });
8726
8784
  const fee = await this.gasFee();
8727
8785
  return this.write(
8728
8786
  "claimAndUnwrap",
@@ -8738,16 +8796,32 @@ var MerkleAirdropClient = class extends AirdropBaseClient {
8738
8796
  * caller can decrypt. Consumes no accounting and no per-leaf state — the
8739
8797
  * same entry still pays the same amount after a preview. No fee.
8740
8798
  *
8741
- * An encrypted view: the contract calls `FHE.allow(outstanding, msg.sender)`,
8742
- * so the result is recovered from the receipt's ACL `Allowed` event, never
8743
- * from a simulation. See {@link AirdropBaseClient}'s class TSDoc.
8799
+ * **Submits a transaction.** The contract calls `FHE.allow(outstanding, account)`, so
8800
+ * the result is recovered from the receipt's ACL `Allowed` event, never from a
8801
+ * simulation. See {@link AirdropBaseClient}'s class TSDoc.
8744
8802
  *
8745
- * @returns `{ handle, hash }` — pass `handle` to the Zama relayer's `userDecrypt`.
8803
+ * **`entry.account` is the decryptable party, not the caller.** A relayer previewing on
8804
+ * someone's behalf gets a valid handle it cannot read — that is the contract's intent,
8805
+ * and it is what makes a blind relayed submission possible.
8806
+ *
8807
+ * @returns `{ handle, hash }` — pass `handle` to the Zama relayer's `userDecrypt`, as `entry.account`.
8746
8808
  */
8747
8809
  async getClaimAmount(args) {
8810
+ const submitter = this.resolveSender(args.account, "getClaimAmount");
8811
+ assertMerkleClaimIdentity({
8812
+ method: "getClaimAmount",
8813
+ account: args.entry.account,
8814
+ boundTo: args.entry.boundTo,
8815
+ submitter
8816
+ });
8748
8817
  return this.encryptedView({
8749
8818
  functionName: "getClaimAmount",
8750
- args: [args.entry.handle, args.entry.inputProof, args.entry.merkleProof],
8819
+ args: [args.entry.account, args.entry.handle, args.entry.inputProof, args.entry.merkleProof],
8820
+ // The contract grants the outstanding handle to `account`, never to the caller
8821
+ // (`_outstandingOf(account, account, …)`), so the receipt's ACL `Allowed` event
8822
+ // names the account. Defaulting to the sender would fail extraction on any
8823
+ // relayed preview — after the transaction had already been mined.
8824
+ grantee: args.entry.account,
8751
8825
  account: args.account
8752
8826
  });
8753
8827
  }
@@ -8770,10 +8844,15 @@ var MerkleAirdropClient = class extends AirdropBaseClient {
8770
8844
  * leaves for the same recipient, claiming both pays the higher of the
8771
8845
  * two totals net of this running value — `max`, not `sum`.
8772
8846
  *
8773
- * The zero handle (uninitialized ciphertext) before an account's first
8774
- * settled claim decrypts as zero.
8847
+ * **An account that has never claimed returns the ZERO handle, which cannot be
8848
+ * decrypted.** It is an uninitialized ciphertext, so nobody holds an ACL on it and
8849
+ * the relayer rejects it with "not authorized to user decrypt handle 0x0…0" rather
8850
+ * than answering zero. Treat `handle === zeroHash` as "nothing delivered yet" and
8851
+ * skip the decrypt; only call `userDecrypt` on a non-zero handle. (A mock FHEVM
8852
+ * instance does answer zero here, so this only bites against a live relayer.)
8775
8853
  *
8776
- * @returns The account's cumulative delivered total, as an encrypted handle.
8854
+ * @returns The account's cumulative delivered total as an encrypted handle, or the
8855
+ * zero handle if it has never claimed.
8777
8856
  */
8778
8857
  async getClaimedAmount(account) {
8779
8858
  const handle = await this.read("getClaimedAmount", [account]);
@@ -8820,4 +8899,919 @@ function createMerkleAirdropClient(config) {
8820
8899
  return new MerkleAirdropClient(config);
8821
8900
  }
8822
8901
 
8823
- export { AirdropBaseClient, CLAIM_TYPEHASH, CLAIM_TYPES, ConfidentialAirdropFactoryClient, EIP712_DOMAIN_NAME, EIP712_DOMAIN_VERSION, EcdsaAirdropClient, FACTORY_ROLE_CONCENTRATION_NOTE, MerkleAirdropClient, airdropFactoryAbi, confidentialAirdropBaseAbi, createAirdropBaseClient, createConfidentialAirdropFactoryClient, createEcdsaAirdropClient, createMerkleAirdropClient, ecdsaConfidentialAirdropAbi, encryptUint64, encryptUint64Batch, merkleConfidentialAirdropAbi, resolveEncryptor, signClaimAuthorization };
8902
+ // src/fhe-airdrop/abis/compliance.ts
8903
+ var complianceRoleManagerAbi = [
8904
+ {
8905
+ inputs: [],
8906
+ stateMutability: "nonpayable",
8907
+ type: "constructor"
8908
+ },
8909
+ {
8910
+ inputs: [],
8911
+ name: "AccessControlBadConfirmation",
8912
+ type: "error"
8913
+ },
8914
+ {
8915
+ inputs: [
8916
+ {
8917
+ internalType: "address",
8918
+ name: "account",
8919
+ type: "address"
8920
+ },
8921
+ {
8922
+ internalType: "bytes32",
8923
+ name: "neededRole",
8924
+ type: "bytes32"
8925
+ }
8926
+ ],
8927
+ name: "AccessControlUnauthorizedAccount",
8928
+ type: "error"
8929
+ },
8930
+ {
8931
+ inputs: [
8932
+ {
8933
+ internalType: "address",
8934
+ name: "airdrop",
8935
+ type: "address"
8936
+ }
8937
+ ],
8938
+ name: "AirdropAndManagerAreSameAddress",
8939
+ type: "error"
8940
+ },
8941
+ {
8942
+ inputs: [],
8943
+ name: "CannotManageComplianceDelegate",
8944
+ type: "error"
8945
+ },
8946
+ {
8947
+ inputs: [],
8948
+ name: "DelegateAlreadyAdded",
8949
+ type: "error"
8950
+ },
8951
+ {
8952
+ inputs: [
8953
+ {
8954
+ internalType: "address",
8955
+ name: "delegate",
8956
+ type: "address"
8957
+ }
8958
+ ],
8959
+ name: "DelegateAndAirdropAreSameAddress",
8960
+ type: "error"
8961
+ },
8962
+ {
8963
+ inputs: [
8964
+ {
8965
+ internalType: "address",
8966
+ name: "delegate",
8967
+ type: "address"
8968
+ }
8969
+ ],
8970
+ name: "DelegateAndManagerAreSameAddress",
8971
+ type: "error"
8972
+ },
8973
+ {
8974
+ inputs: [],
8975
+ name: "DelegateNotFound",
8976
+ type: "error"
8977
+ },
8978
+ {
8979
+ inputs: [],
8980
+ name: "InvalidInitialization",
8981
+ type: "error"
8982
+ },
8983
+ {
8984
+ inputs: [],
8985
+ name: "NotInitializing",
8986
+ type: "error"
8987
+ },
8988
+ {
8989
+ inputs: [],
8990
+ name: "ZamaProtocolUnsupported",
8991
+ type: "error"
8992
+ },
8993
+ {
8994
+ inputs: [],
8995
+ name: "ZeroAirdrop",
8996
+ type: "error"
8997
+ },
8998
+ {
8999
+ inputs: [],
9000
+ name: "ZeroClientAdmin",
9001
+ type: "error"
9002
+ },
9003
+ {
9004
+ inputs: [],
9005
+ name: "ZeroDelegate",
9006
+ type: "error"
9007
+ },
9008
+ {
9009
+ anonymous: false,
9010
+ inputs: [
9011
+ {
9012
+ indexed: true,
9013
+ internalType: "address",
9014
+ name: "delegate",
9015
+ type: "address"
9016
+ }
9017
+ ],
9018
+ name: "ClientDelegateAdded",
9019
+ type: "event"
9020
+ },
9021
+ {
9022
+ anonymous: false,
9023
+ inputs: [
9024
+ {
9025
+ indexed: true,
9026
+ internalType: "address",
9027
+ name: "delegate",
9028
+ type: "address"
9029
+ }
9030
+ ],
9031
+ name: "ClientDelegateRevoked",
9032
+ type: "event"
9033
+ },
9034
+ {
9035
+ anonymous: false,
9036
+ inputs: [
9037
+ {
9038
+ indexed: true,
9039
+ internalType: "address",
9040
+ name: "delegate",
9041
+ type: "address"
9042
+ }
9043
+ ],
9044
+ name: "ComplianceDelegateSet",
9045
+ type: "event"
9046
+ },
9047
+ {
9048
+ anonymous: false,
9049
+ inputs: [
9050
+ {
9051
+ indexed: false,
9052
+ internalType: "uint64",
9053
+ name: "version",
9054
+ type: "uint64"
9055
+ }
9056
+ ],
9057
+ name: "Initialized",
9058
+ type: "event"
9059
+ },
9060
+ {
9061
+ anonymous: false,
9062
+ inputs: [
9063
+ {
9064
+ indexed: true,
9065
+ internalType: "bytes32",
9066
+ name: "role",
9067
+ type: "bytes32"
9068
+ },
9069
+ {
9070
+ indexed: true,
9071
+ internalType: "bytes32",
9072
+ name: "previousAdminRole",
9073
+ type: "bytes32"
9074
+ },
9075
+ {
9076
+ indexed: true,
9077
+ internalType: "bytes32",
9078
+ name: "newAdminRole",
9079
+ type: "bytes32"
9080
+ }
9081
+ ],
9082
+ name: "RoleAdminChanged",
9083
+ type: "event"
9084
+ },
9085
+ {
9086
+ anonymous: false,
9087
+ inputs: [
9088
+ {
9089
+ indexed: true,
9090
+ internalType: "bytes32",
9091
+ name: "role",
9092
+ type: "bytes32"
9093
+ },
9094
+ {
9095
+ indexed: true,
9096
+ internalType: "address",
9097
+ name: "account",
9098
+ type: "address"
9099
+ },
9100
+ {
9101
+ indexed: true,
9102
+ internalType: "address",
9103
+ name: "sender",
9104
+ type: "address"
9105
+ }
9106
+ ],
9107
+ name: "RoleGranted",
9108
+ type: "event"
9109
+ },
9110
+ {
9111
+ anonymous: false,
9112
+ inputs: [
9113
+ {
9114
+ indexed: true,
9115
+ internalType: "bytes32",
9116
+ name: "role",
9117
+ type: "bytes32"
9118
+ },
9119
+ {
9120
+ indexed: true,
9121
+ internalType: "address",
9122
+ name: "account",
9123
+ type: "address"
9124
+ },
9125
+ {
9126
+ indexed: true,
9127
+ internalType: "address",
9128
+ name: "sender",
9129
+ type: "address"
9130
+ }
9131
+ ],
9132
+ name: "RoleRevoked",
9133
+ type: "event"
9134
+ },
9135
+ {
9136
+ inputs: [],
9137
+ name: "DEFAULT_ADMIN_ROLE",
9138
+ outputs: [
9139
+ {
9140
+ internalType: "bytes32",
9141
+ name: "",
9142
+ type: "bytes32"
9143
+ }
9144
+ ],
9145
+ stateMutability: "view",
9146
+ type: "function"
9147
+ },
9148
+ {
9149
+ inputs: [],
9150
+ name: "DELEGATION_ADMIN_ROLE",
9151
+ outputs: [
9152
+ {
9153
+ internalType: "bytes32",
9154
+ name: "",
9155
+ type: "bytes32"
9156
+ }
9157
+ ],
9158
+ stateMutability: "view",
9159
+ type: "function"
9160
+ },
9161
+ {
9162
+ inputs: [
9163
+ {
9164
+ internalType: "address",
9165
+ name: "delegate",
9166
+ type: "address"
9167
+ }
9168
+ ],
9169
+ name: "addDelegate",
9170
+ outputs: [],
9171
+ stateMutability: "nonpayable",
9172
+ type: "function"
9173
+ },
9174
+ {
9175
+ inputs: [],
9176
+ name: "airdrop",
9177
+ outputs: [
9178
+ {
9179
+ internalType: "address",
9180
+ name: "",
9181
+ type: "address"
9182
+ }
9183
+ ],
9184
+ stateMutability: "view",
9185
+ type: "function"
9186
+ },
9187
+ {
9188
+ inputs: [],
9189
+ name: "clientDelegates",
9190
+ outputs: [
9191
+ {
9192
+ internalType: "address[]",
9193
+ name: "",
9194
+ type: "address[]"
9195
+ }
9196
+ ],
9197
+ stateMutability: "view",
9198
+ type: "function"
9199
+ },
9200
+ {
9201
+ inputs: [],
9202
+ name: "complianceDelegate",
9203
+ outputs: [
9204
+ {
9205
+ internalType: "address",
9206
+ name: "",
9207
+ type: "address"
9208
+ }
9209
+ ],
9210
+ stateMutability: "view",
9211
+ type: "function"
9212
+ },
9213
+ {
9214
+ inputs: [
9215
+ {
9216
+ internalType: "bytes32",
9217
+ name: "role",
9218
+ type: "bytes32"
9219
+ }
9220
+ ],
9221
+ name: "getRoleAdmin",
9222
+ outputs: [
9223
+ {
9224
+ internalType: "bytes32",
9225
+ name: "",
9226
+ type: "bytes32"
9227
+ }
9228
+ ],
9229
+ stateMutability: "view",
9230
+ type: "function"
9231
+ },
9232
+ {
9233
+ inputs: [
9234
+ {
9235
+ internalType: "bytes32",
9236
+ name: "role",
9237
+ type: "bytes32"
9238
+ },
9239
+ {
9240
+ internalType: "uint256",
9241
+ name: "index",
9242
+ type: "uint256"
9243
+ }
9244
+ ],
9245
+ name: "getRoleMember",
9246
+ outputs: [
9247
+ {
9248
+ internalType: "address",
9249
+ name: "",
9250
+ type: "address"
9251
+ }
9252
+ ],
9253
+ stateMutability: "view",
9254
+ type: "function"
9255
+ },
9256
+ {
9257
+ inputs: [
9258
+ {
9259
+ internalType: "bytes32",
9260
+ name: "role",
9261
+ type: "bytes32"
9262
+ }
9263
+ ],
9264
+ name: "getRoleMemberCount",
9265
+ outputs: [
9266
+ {
9267
+ internalType: "uint256",
9268
+ name: "",
9269
+ type: "uint256"
9270
+ }
9271
+ ],
9272
+ stateMutability: "view",
9273
+ type: "function"
9274
+ },
9275
+ {
9276
+ inputs: [
9277
+ {
9278
+ internalType: "bytes32",
9279
+ name: "role",
9280
+ type: "bytes32"
9281
+ }
9282
+ ],
9283
+ name: "getRoleMembers",
9284
+ outputs: [
9285
+ {
9286
+ internalType: "address[]",
9287
+ name: "",
9288
+ type: "address[]"
9289
+ }
9290
+ ],
9291
+ stateMutability: "view",
9292
+ type: "function"
9293
+ },
9294
+ {
9295
+ inputs: [
9296
+ {
9297
+ internalType: "bytes32",
9298
+ name: "role",
9299
+ type: "bytes32"
9300
+ },
9301
+ {
9302
+ internalType: "address",
9303
+ name: "account",
9304
+ type: "address"
9305
+ }
9306
+ ],
9307
+ name: "grantRole",
9308
+ outputs: [],
9309
+ stateMutability: "nonpayable",
9310
+ type: "function"
9311
+ },
9312
+ {
9313
+ inputs: [
9314
+ {
9315
+ internalType: "bytes32",
9316
+ name: "role",
9317
+ type: "bytes32"
9318
+ },
9319
+ {
9320
+ internalType: "address",
9321
+ name: "account",
9322
+ type: "address"
9323
+ }
9324
+ ],
9325
+ name: "hasRole",
9326
+ outputs: [
9327
+ {
9328
+ internalType: "bool",
9329
+ name: "",
9330
+ type: "bool"
9331
+ }
9332
+ ],
9333
+ stateMutability: "view",
9334
+ type: "function"
9335
+ },
9336
+ {
9337
+ inputs: [
9338
+ {
9339
+ internalType: "address",
9340
+ name: "airdrop_",
9341
+ type: "address"
9342
+ },
9343
+ {
9344
+ internalType: "address",
9345
+ name: "clientAdmin",
9346
+ type: "address"
9347
+ },
9348
+ {
9349
+ internalType: "address",
9350
+ name: "clientDelegate",
9351
+ type: "address"
9352
+ },
9353
+ {
9354
+ internalType: "address",
9355
+ name: "complianceDelegate_",
9356
+ type: "address"
9357
+ }
9358
+ ],
9359
+ name: "initialize",
9360
+ outputs: [],
9361
+ stateMutability: "nonpayable",
9362
+ type: "function"
9363
+ },
9364
+ {
9365
+ inputs: [
9366
+ {
9367
+ internalType: "address",
9368
+ name: "delegate",
9369
+ type: "address"
9370
+ }
9371
+ ],
9372
+ name: "isActiveDelegate",
9373
+ outputs: [
9374
+ {
9375
+ internalType: "bool",
9376
+ name: "",
9377
+ type: "bool"
9378
+ }
9379
+ ],
9380
+ stateMutability: "view",
9381
+ type: "function"
9382
+ },
9383
+ {
9384
+ inputs: [
9385
+ {
9386
+ internalType: "bytes32",
9387
+ name: "role",
9388
+ type: "bytes32"
9389
+ },
9390
+ {
9391
+ internalType: "address",
9392
+ name: "callerConfirmation",
9393
+ type: "address"
9394
+ }
9395
+ ],
9396
+ name: "renounceRole",
9397
+ outputs: [],
9398
+ stateMutability: "nonpayable",
9399
+ type: "function"
9400
+ },
9401
+ {
9402
+ inputs: [
9403
+ {
9404
+ internalType: "address",
9405
+ name: "delegate",
9406
+ type: "address"
9407
+ }
9408
+ ],
9409
+ name: "revokeDelegate",
9410
+ outputs: [],
9411
+ stateMutability: "nonpayable",
9412
+ type: "function"
9413
+ },
9414
+ {
9415
+ inputs: [
9416
+ {
9417
+ internalType: "bytes32",
9418
+ name: "role",
9419
+ type: "bytes32"
9420
+ },
9421
+ {
9422
+ internalType: "address",
9423
+ name: "account",
9424
+ type: "address"
9425
+ }
9426
+ ],
9427
+ name: "revokeRole",
9428
+ outputs: [],
9429
+ stateMutability: "nonpayable",
9430
+ type: "function"
9431
+ },
9432
+ {
9433
+ inputs: [
9434
+ {
9435
+ internalType: "bytes4",
9436
+ name: "interfaceId",
9437
+ type: "bytes4"
9438
+ }
9439
+ ],
9440
+ name: "supportsInterface",
9441
+ outputs: [
9442
+ {
9443
+ internalType: "bool",
9444
+ name: "",
9445
+ type: "bool"
9446
+ }
9447
+ ],
9448
+ stateMutability: "view",
9449
+ type: "function"
9450
+ }
9451
+ ];
9452
+
9453
+ // src/fhe-airdrop/compliance.ts
9454
+ var ACL_PROPAGATION_CODE = "DELEGATION_NOT_PROPAGATED";
9455
+ var ACL_PROPAGATION_ERROR_NAME = "DelegationNotPropagatedError";
9456
+ var ACL_PROPAGATION_STATUSES = /* @__PURE__ */ new Set([400, 500]);
9457
+ function matchesPropagationMessage(message) {
9458
+ const lower = message.toLowerCase();
9459
+ if (lower.includes("acl check not propagated")) return true;
9460
+ return lower.includes("propagat") && lower.includes("gateway");
9461
+ }
9462
+ function readRecord(value) {
9463
+ return typeof value === "object" && value !== null ? value : void 0;
9464
+ }
9465
+ function readNumber(obj, key) {
9466
+ const value = obj?.[key];
9467
+ return typeof value === "number" ? value : void 0;
9468
+ }
9469
+ function readString(obj, key) {
9470
+ const value = obj?.[key];
9471
+ return typeof value === "string" ? value : void 0;
9472
+ }
9473
+ function isAclPropagationError(error) {
9474
+ const err = readRecord(error);
9475
+ if (!err) return false;
9476
+ const cause = readRecord(err["cause"]);
9477
+ if (err["code"] === ACL_PROPAGATION_CODE || err["name"] === ACL_PROPAGATION_ERROR_NAME || cause?.["code"] === ACL_PROPAGATION_CODE || cause?.["name"] === ACL_PROPAGATION_ERROR_NAME) {
9478
+ return true;
9479
+ }
9480
+ const status = readNumber(err, "status") ?? readNumber(err, "statusCode") ?? readNumber(cause, "status") ?? readNumber(cause, "statusCode");
9481
+ if (status === void 0 || !ACL_PROPAGATION_STATUSES.has(status)) return false;
9482
+ const errMessage = readString(err, "message");
9483
+ const causeMessage = readString(cause, "message");
9484
+ return errMessage !== void 0 && matchesPropagationMessage(errMessage) || causeMessage !== void 0 && matchesPropagationMessage(causeMessage);
9485
+ }
9486
+ var ComplianceManagerClient = class {
9487
+ publicClient;
9488
+ walletClient;
9489
+ address;
9490
+ chainId;
9491
+ #telemetry;
9492
+ constructor(config) {
9493
+ this.publicClient = config.publicClient;
9494
+ this.walletClient = config.walletClient;
9495
+ const chainId = config.chainId ?? config.publicClient.chain?.id;
9496
+ if (chainId === void 0) {
9497
+ throw new DeploymentAddressUnavailableError({
9498
+ reason: "chain-id-missing",
9499
+ product: "fheAirdrop",
9500
+ contract: "complianceManager",
9501
+ clientLabel: "ComplianceManagerClient"
9502
+ });
9503
+ }
9504
+ assertSupportedChain(chainId);
9505
+ this.chainId = chainId;
9506
+ this.address = normaliseAddress(config.address);
9507
+ this.#telemetry = config.telemetry;
9508
+ this.#telemetry?.event("fhe-airdrop.client.init", {
9509
+ surface: "compliance",
9510
+ chainId,
9511
+ hasWallet: !!this.walletClient,
9512
+ sdkVersion: SDK_VERSION
9513
+ });
9514
+ }
9515
+ // ============================================================
9516
+ // CLIENT DELEGATION MGMT
9517
+ // ============================================================
9518
+ /**
9519
+ * Add a client delegate: grants `delegate` permanent (never-expiring)
9520
+ * user-decryption delegation over this clone's airdrop. Requires
9521
+ * {@link DELEGATION_ADMIN_ROLE}.
9522
+ *
9523
+ * Effective on-chain immediately; see the class TSDoc for the gateway
9524
+ * propagation lag before `delegatedUserDecrypt` catches up.
9525
+ *
9526
+ * @throws {@link InvalidArgumentError} (`argument: "delegate"`) when `delegate` is the zero address
9527
+ * (`ZeroDelegate`), already an active client delegate (`DelegateAlreadyAdded`), or targets the
9528
+ * irrevocable platform compliance delegate (`CannotManageComplianceDelegate`).
9529
+ * @returns The transaction hash.
9530
+ */
9531
+ async addDelegate(args) {
9532
+ return withTelemetry(
9533
+ this.#telemetry,
9534
+ "fhe-airdrop.compliance.addDelegate",
9535
+ () => this.#write("addDelegate", [args.delegate], args.account, "addDelegate")
9536
+ );
9537
+ }
9538
+ /**
9539
+ * Revoke a client delegate. Requires {@link DELEGATION_ADMIN_ROLE}.
9540
+ *
9541
+ * Effective on-chain immediately — but off-chain, gateway-served
9542
+ * `delegatedUserDecrypt` calls stop succeeding only once the gateway
9543
+ * observes the revocation, which is not instantaneous either. Cannot target
9544
+ * the platform compliance delegate, which is irrevocable by construction.
9545
+ *
9546
+ * **Not in the same block as {@link addDelegate} for the same delegate.**
9547
+ * The FHEVM ACL rejects an add and a revoke of one delegate within a single
9548
+ * block (`AlreadyDelegatedOrRevokedInSameBlock`), and because that revert
9549
+ * comes from the ACL rather than from this contract, it surfaces as an
9550
+ * opaque {@link ContractRevertError} with no decodable selector — nothing
9551
+ * names the delegate or the cause. Batching an add and a revoke into one
9552
+ * multicall, or sending both inside one block, is the way to hit it; wait a
9553
+ * block between them. This is the sequencing counterpart to the propagation
9554
+ * gotcha on the class TSDoc: that one is the gateway lagging the chain, this
9555
+ * one is the chain refusing two conflicting writes at the same height.
9556
+ *
9557
+ * @throws {@link InvalidArgumentError} (`argument: "delegate"`) when `delegate` is the zero address
9558
+ * (`ZeroDelegate`), not currently an active client delegate (`DelegateNotFound`), or targets the
9559
+ * irrevocable platform compliance delegate (`CannotManageComplianceDelegate`).
9560
+ * @returns The transaction hash.
9561
+ */
9562
+ async revokeDelegate(args) {
9563
+ return withTelemetry(
9564
+ this.#telemetry,
9565
+ "fhe-airdrop.compliance.revokeDelegate",
9566
+ () => this.#write("revokeDelegate", [args.delegate], args.account, "revokeDelegate")
9567
+ );
9568
+ }
9569
+ // ============================================================
9570
+ // READS
9571
+ // ============================================================
9572
+ /** The one airdrop instance this clone serves — set once, at `initialize`. */
9573
+ async airdrop() {
9574
+ return this.#read("airdrop");
9575
+ }
9576
+ /**
9577
+ * The platform compliance delegate.
9578
+ *
9579
+ * @returns The delegate address, or the zero address when this clone was
9580
+ * created with the platform compliance policy OFF. Because `initialize`
9581
+ * always runs atomically before this client can reach the clone (see the
9582
+ * class TSDoc), a zero return never means "not wired yet" — there is no
9583
+ * such observable state on this contract. It unambiguously means "no
9584
+ * platform delegate for this airdrop."
9585
+ */
9586
+ async complianceDelegate() {
9587
+ return this.#read("complianceDelegate");
9588
+ }
9589
+ /** The current set of active client delegates (excludes the platform compliance delegate, if any). */
9590
+ async clientDelegates() {
9591
+ return this.#read("clientDelegates");
9592
+ }
9593
+ /**
9594
+ * Authoritative active-delegate check for `delegate` — reads the ACL
9595
+ * expiration date directly rather than the contract's `EnumerableSet`
9596
+ * mirror, so it reflects the platform compliance delegate too (which never
9597
+ * appears in {@link clientDelegates}).
9598
+ *
9599
+ * On-chain truth only: a `true` result means the delegation is live in the
9600
+ * ACL, not that the gateway has caught up with it yet — see the class
9601
+ * TSDoc's propagation note.
9602
+ */
9603
+ async isActiveDelegate(delegate) {
9604
+ return this.#read("isActiveDelegate", [delegate]);
9605
+ }
9606
+ // Role-constant getters are named for the contract function they read, the
9607
+ // same convention every other client in this module follows: one spelling
9608
+ // per role, whichever client you happen to be holding.
9609
+ /** Gates {@link addDelegate} / {@link revokeDelegate}. */
9610
+ async DELEGATION_ADMIN_ROLE() {
9611
+ return this.#read("DELEGATION_ADMIN_ROLE");
9612
+ }
9613
+ /**
9614
+ * OpenZeppelin's root role (`bytes32(0)`), read from the clone rather than
9615
+ * hard-coded. It administers {@link DELEGATION_ADMIN_ROLE}.
9616
+ */
9617
+ async DEFAULT_ADMIN_ROLE() {
9618
+ return this.#read("DEFAULT_ADMIN_ROLE");
9619
+ }
9620
+ // ============================================================
9621
+ // ROLE ADMINISTRATION
9622
+ // ============================================================
9623
+ //
9624
+ // The clone is `AccessControlEnumerableUpgradeable`, so membership is
9625
+ // enumerable as well as checkable. This surface is what makes the delegation
9626
+ // verbs above administrable: without it, whoever the factory named at
9627
+ // `initialize` is the only account that can ever add a delegate, and there
9628
+ // is no way to find out who that is.
9629
+ //
9630
+ // Unlike an airdrop instance, this contract adds no "never empty" floor of
9631
+ // its own - emptying `DEFAULT_ADMIN_ROLE` here permanently freezes the
9632
+ // clone's delegate set at whatever it currently holds.
9633
+ /**
9634
+ * Whether `holder` holds `role`.
9635
+ *
9636
+ * The role subject is called `holder`, not `account`: on the writes below
9637
+ * `account` already means "who sends this transaction", and one key cannot
9638
+ * be both.
9639
+ *
9640
+ * @param args.role A `bytes32` from {@link DELEGATION_ADMIN_ROLE} or {@link DEFAULT_ADMIN_ROLE}.
9641
+ */
9642
+ async hasRole(args) {
9643
+ return this.#read("hasRole", [args.role, args.holder]);
9644
+ }
9645
+ /** The role whose holders may {@link grantRole} and {@link revokeRole} `role`. */
9646
+ async getRoleAdmin(role) {
9647
+ return this.#read("getRoleAdmin", [role]);
9648
+ }
9649
+ /** How many accounts hold `role`. */
9650
+ async getRoleMemberCount(role) {
9651
+ return this.#read("getRoleMemberCount", [role]);
9652
+ }
9653
+ /**
9654
+ * The `index`-th holder of `role`, in `EnumerableSet` order - which is not
9655
+ * stable across grants and revokes. Prefer {@link getRoleMembers}.
9656
+ */
9657
+ async getRoleMember(args) {
9658
+ return this.#read("getRoleMember", [args.role, args.index]);
9659
+ }
9660
+ /**
9661
+ * Every account currently holding `role`.
9662
+ *
9663
+ * With {@link DELEGATION_ADMIN_ROLE} this answers "who may add or revoke a
9664
+ * delegate on this clone?" - the administrative counterpart to
9665
+ * {@link clientDelegates}, which answers "who may currently decrypt?".
9666
+ */
9667
+ async getRoleMembers(role) {
9668
+ return this.#read("getRoleMembers", [role]);
9669
+ }
9670
+ /**
9671
+ * Grant `role` to `holder`. Requires the role's admin role
9672
+ * ({@link getRoleAdmin}).
9673
+ *
9674
+ * This is how a second operator is added to {@link DELEGATION_ADMIN_ROLE} -
9675
+ * the delegation verbs themselves are unaffected, the grant only widens who
9676
+ * may call them.
9677
+ *
9678
+ * @returns The transaction hash.
9679
+ */
9680
+ async grantRole(args) {
9681
+ return withTelemetry(
9682
+ this.#telemetry,
9683
+ "fhe-airdrop.compliance.grantRole",
9684
+ () => this.#write("grantRole", [args.role, args.holder], args.account, "grantRole")
9685
+ );
9686
+ }
9687
+ /**
9688
+ * Revoke `role` from `holder`. Requires the role's admin role.
9689
+ *
9690
+ * Revoking a delegation admin does **not** revoke the delegations they
9691
+ * created: an existing delegate keeps decrypting until
9692
+ * {@link revokeDelegate} is called for it explicitly.
9693
+ *
9694
+ * @returns The transaction hash.
9695
+ */
9696
+ async revokeRole(args) {
9697
+ return withTelemetry(
9698
+ this.#telemetry,
9699
+ "fhe-airdrop.compliance.revokeRole",
9700
+ () => this.#write("revokeRole", [args.role, args.holder], args.account, "revokeRole")
9701
+ );
9702
+ }
9703
+ /**
9704
+ * Give up `role` yourself.
9705
+ *
9706
+ * The contract's signature is `renounceRole(role, callerConfirmation)` and
9707
+ * it reverts `AccessControlBadConfirmation` unless `callerConfirmation` is
9708
+ * the sender, so this method takes no holder and fills the confirmation from
9709
+ * the resolved sending account. Renouncing for somebody else is not a call
9710
+ * that can succeed; use {@link revokeRole} to remove another account's role.
9711
+ *
9712
+ * @returns The transaction hash.
9713
+ */
9714
+ async renounceRole(args) {
9715
+ const method = "renounceRole";
9716
+ const wallet = this.#requireWallet(method);
9717
+ const account = this.#resolveAccount(wallet, args.account, method);
9718
+ return withTelemetry(
9719
+ this.#telemetry,
9720
+ "fhe-airdrop.compliance.renounceRole",
9721
+ () => this.#write(method, [args.role, accountAddress3(account)], account, method)
9722
+ );
9723
+ }
9724
+ // ============================================================
9725
+ // INTERNALS (private)
9726
+ // ============================================================
9727
+ async #write(functionName, args, account, method) {
9728
+ const wallet = this.#requireWallet(method);
9729
+ const acct = this.#resolveAccount(wallet, account, method);
9730
+ await this.#preflightWrite(method, functionName, args, acct);
9731
+ try {
9732
+ return await wallet.writeContract({
9733
+ address: this.address,
9734
+ abi: complianceRoleManagerAbi,
9735
+ functionName,
9736
+ args,
9737
+ account: acct,
9738
+ chain: wallet.chain
9739
+ });
9740
+ } catch (err) {
9741
+ throw this.#mapRevert(method, err, acct);
9742
+ }
9743
+ }
9744
+ async #read(functionName, args = []) {
9745
+ const result = await this.publicClient.readContract({
9746
+ address: this.address,
9747
+ abi: complianceRoleManagerAbi,
9748
+ functionName,
9749
+ args
9750
+ });
9751
+ return result;
9752
+ }
9753
+ /**
9754
+ * Simulate a write purely to surface typed reverts.
9755
+ *
9756
+ * The simulate's return value is discarded on principle: this contract
9757
+ * returns nothing from `addDelegate` / `revokeDelegate` anyway, but the
9758
+ * pattern is kept identical to every other airdrop v2 client so a revert is
9759
+ * always decoded before the user pays for it.
9760
+ */
9761
+ async #preflightWrite(method, functionName, args, account) {
9762
+ try {
9763
+ await this.publicClient.simulateContract({
9764
+ address: this.address,
9765
+ abi: complianceRoleManagerAbi,
9766
+ functionName,
9767
+ args,
9768
+ account
9769
+ });
9770
+ } catch (err) {
9771
+ if (isContractRevert(err)) {
9772
+ throw this.#mapRevert(method, err, account);
9773
+ }
9774
+ }
9775
+ }
9776
+ /**
9777
+ * Map a viem error to the SDK's typed palette.
9778
+ *
9779
+ * `productContext` deliberately carries only public identifiers — the
9780
+ * caller, the chain. Never an amount: this contract never handles amounts
9781
+ * at all, but the convention is shared across every airdrop v2 client.
9782
+ */
9783
+ #mapRevert(method, err, account) {
9784
+ return mapContractRevert(err, {
9785
+ method,
9786
+ contractAddress: this.address,
9787
+ abi: complianceRoleManagerAbi,
9788
+ productMapper: airdropProductMapper,
9789
+ account: accountAddress3(account),
9790
+ productContext: {
9791
+ creator: accountAddress3(account),
9792
+ chainId: this.chainId
9793
+ }
9794
+ });
9795
+ }
9796
+ #requireWallet(method) {
9797
+ if (!this.walletClient) {
9798
+ throw new MissingWalletClientError(method);
9799
+ }
9800
+ return this.walletClient;
9801
+ }
9802
+ #resolveAccount(wallet, override, method) {
9803
+ const acct = override ?? wallet.account;
9804
+ if (!acct) {
9805
+ throw new MissingAccountError(method);
9806
+ }
9807
+ return acct;
9808
+ }
9809
+ };
9810
+ function createComplianceManagerClient(config) {
9811
+ return new ComplianceManagerClient(config);
9812
+ }
9813
+ function accountAddress3(account) {
9814
+ return typeof account === "string" ? account : account.address;
9815
+ }
9816
+
9817
+ export { AirdropBaseClient, CLAIM_TYPEHASH, CLAIM_TYPES, ComplianceManagerClient, ConfidentialAirdropFactoryClient, EIP712_DOMAIN_NAME, EIP712_DOMAIN_VERSION, EcdsaAirdropClient, FACTORY_ROLE_CONCENTRATION_NOTE, MerkleAirdropClient, airdropFactoryAbi, complianceRoleManagerAbi, confidentialAirdropBaseAbi, createAirdropBaseClient, createComplianceManagerClient, createConfidentialAirdropFactoryClient, createEcdsaAirdropClient, createMerkleAirdropClient, ecdsaConfidentialAirdropAbi, encryptUint64, encryptUint64Batch, isAclPropagationError, merkleConfidentialAirdropAbi, resolveEncryptor, signClaimAuthorization };