@tokenops/sdk 1.5.1 → 2.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/CHANGELOG.md +198 -2
  2. package/CONTRIBUTING.md +4 -2
  3. package/README.md +146 -90
  4. package/SECURITY.md +7 -1
  5. package/SUPPORT.md +47 -0
  6. package/dist/{chunk-YQIBBEFJ.js → chunk-335Z2W67.js} +1 -1
  7. package/dist/{chunk-2NCLOQ56.cjs → chunk-3QHNYEQD.cjs} +77 -0
  8. package/dist/chunk-456VDDA3.js +370 -0
  9. package/dist/{chunk-SG65XWH7.js → chunk-4RAAATVY.js} +1 -3
  10. package/dist/{chunk-6BMP4ICG.js → chunk-4TSDNZQ3.js} +60 -2
  11. package/dist/{chunk-PUPKNW3R.cjs → chunk-5576FRT3.cjs} +30 -6
  12. package/dist/{chunk-AOP6HMPW.js → chunk-6GNR22OV.js} +75 -1
  13. package/dist/{chunk-NTZY6IB7.js → chunk-6NAVMWZQ.js} +4 -3
  14. package/dist/{chunk-C7BRZXJA.cjs → chunk-6PXXGACR.cjs} +8 -7
  15. package/dist/{chunk-IJFQ5L4I.js → chunk-74QFZ5MK.js} +4 -3
  16. package/dist/chunk-7AFPOE7N.cjs +59 -0
  17. package/dist/chunk-AXIPOR3C.js +56 -0
  18. package/dist/chunk-CTED3MTR.cjs +380 -0
  19. package/dist/{chunk-XGGTQQFH.js → chunk-DZHYSUGY.js} +28 -7
  20. package/dist/{chunk-OXTLPTO3.js → chunk-EAJ7SYHE.js} +4 -3
  21. package/dist/{chunk-V2PXZVBF.cjs → chunk-FGEB7RMY.cjs} +4 -4
  22. package/dist/chunk-GKKDAW44.js +8823 -0
  23. package/dist/{chunk-2PWNH3UE.js → chunk-H5POPGOZ.js} +63 -5
  24. package/dist/{chunk-W7IGCOVL.cjs → chunk-JQYC66TO.cjs} +9 -8
  25. package/dist/{chunk-PFXURMBZ.cjs → chunk-JZLGCTGK.cjs} +68 -8
  26. package/dist/{chunk-JYOTGRSO.cjs → chunk-KFRDLKMA.cjs} +61 -1
  27. package/dist/chunk-M4IT6DNJ.cjs +608 -0
  28. package/dist/{chunk-KLKI352M.cjs → chunk-MVDQMV25.cjs} +0 -3
  29. package/dist/chunk-NCVX3K2N.cjs +161 -0
  30. package/dist/chunk-NWFMBLSQ.js +4 -0
  31. package/dist/chunk-O5676ZWY.js +585 -0
  32. package/dist/chunk-PUX5VXDB.cjs +8845 -0
  33. package/dist/{chunk-IXLO7GO5.js → chunk-TWT3STIX.js} +46 -80
  34. package/dist/chunk-UG5RKLU2.cjs +6 -0
  35. package/dist/chunk-VP2B4WM2.js +154 -0
  36. package/dist/{chunk-5X5WL5CU.cjs → chunk-WJLECC22.cjs} +51 -88
  37. package/dist/{chunk-WENHUPZC.cjs → chunk-XAYGD4E4.cjs} +9 -8
  38. package/dist/core/addresses.d.ts +15 -3
  39. package/dist/core/brands.d.ts +8 -2
  40. package/dist/core/errors.d.ts +71 -10
  41. package/dist/core/preflight.d.ts +1 -0
  42. package/dist/fhe/erc7984-abi.d.ts +1 -0
  43. package/dist/fhe/index.cjs +34 -13
  44. package/dist/fhe/index.d.cts +1 -0
  45. package/dist/fhe/index.d.ts +1 -0
  46. package/dist/fhe/index.js +19 -6
  47. package/dist/fhe/mock-erc7984.d.ts +4 -4
  48. package/dist/fhe/operators.d.ts +160 -3
  49. package/dist/fhe/react/index.cjs +14 -0
  50. package/dist/fhe/react/index.d.cts +2 -0
  51. package/dist/fhe/react/index.d.ts +2 -0
  52. package/dist/fhe/react/index.js +6 -0
  53. package/dist/fhe/react/useEnsureOperator.d.ts +56 -0
  54. package/dist/fhe/react/useIsOperator.d.ts +54 -0
  55. package/dist/fhe/sepolia-encryptor-web.d.ts +18 -3
  56. package/dist/fhe/types.d.ts +6 -0
  57. package/dist/fhe-airdrop/abis/{cloneable.d.ts → airdrop-base.d.ts} +254 -396
  58. package/dist/fhe-airdrop/abis/compliance.d.ts +422 -0
  59. package/dist/fhe-airdrop/abis/ecdsa.d.ts +1316 -0
  60. package/dist/fhe-airdrop/abis/factory.d.ts +1319 -190
  61. package/dist/fhe-airdrop/abis/index.d.ts +5 -2
  62. package/dist/fhe-airdrop/abis/merkle.d.ts +1238 -0
  63. package/dist/fhe-airdrop/advanced/index.cjs +10 -12
  64. package/dist/fhe-airdrop/advanced/index.d.cts +34 -11
  65. package/dist/fhe-airdrop/advanced/index.d.ts +34 -11
  66. package/dist/fhe-airdrop/advanced/index.js +2 -8
  67. package/dist/fhe-airdrop/advanced/react/index.cjs +34 -48
  68. package/dist/fhe-airdrop/advanced/react/index.d.cts +9 -3
  69. package/dist/fhe-airdrop/advanced/react/index.d.ts +9 -3
  70. package/dist/fhe-airdrop/advanced/react/index.js +33 -48
  71. package/dist/fhe-airdrop/advanced/react/usePredictEcdsaAirdropAddress.d.ts +33 -0
  72. package/dist/fhe-airdrop/advanced/react/usePredictMerkleAirdropAddress.d.ts +27 -0
  73. package/dist/fhe-airdrop/airdrop-base.d.ts +600 -0
  74. package/dist/fhe-airdrop/campaign.d.ts +297 -0
  75. package/dist/fhe-airdrop/compliance.d.ts +302 -0
  76. package/dist/fhe-airdrop/constants.d.ts +33 -0
  77. package/dist/fhe-airdrop/ecdsa.d.ts +263 -0
  78. package/dist/fhe-airdrop/encryption.d.ts +92 -14
  79. package/dist/fhe-airdrop/errors.d.ts +245 -15
  80. package/dist/fhe-airdrop/factory.d.ts +533 -274
  81. package/dist/fhe-airdrop/guards.d.ts +273 -0
  82. package/dist/fhe-airdrop/index.cjs +1089 -33
  83. package/dist/fhe-airdrop/index.d.cts +46 -8
  84. package/dist/fhe-airdrop/index.d.ts +46 -8
  85. package/dist/fhe-airdrop/index.js +929 -7
  86. package/dist/fhe-airdrop/merkle-tree.d.ts +103 -0
  87. package/dist/fhe-airdrop/merkle.d.ts +180 -0
  88. package/dist/fhe-airdrop/react/_shared.d.ts +144 -71
  89. package/dist/fhe-airdrop/react/index.cjs +364 -413
  90. package/dist/fhe-airdrop/react/index.d.cts +53 -72
  91. package/dist/fhe-airdrop/react/index.d.ts +53 -72
  92. package/dist/fhe-airdrop/react/index.js +258 -369
  93. package/dist/fhe-airdrop/react/useAirdropGasFee.d.ts +10 -5
  94. package/dist/fhe-airdrop/react/useAirdropHasRole.d.ts +15 -6
  95. package/dist/fhe-airdrop/react/useAirdropPause.d.ts +30 -0
  96. package/dist/fhe-airdrop/react/useAirdropPaused.d.ts +17 -0
  97. package/dist/fhe-airdrop/react/useAirdropToken.d.ts +11 -4
  98. package/dist/fhe-airdrop/react/useAirdropWindow.d.ts +37 -0
  99. package/dist/fhe-airdrop/react/useClaimedAmount.d.ts +29 -0
  100. package/dist/fhe-airdrop/react/useComplianceManager.d.ts +16 -0
  101. package/dist/fhe-airdrop/react/useCreateEcdsaAirdrop.d.ts +28 -0
  102. package/dist/fhe-airdrop/react/useCreateMerkleAirdrop.d.ts +25 -0
  103. package/dist/fhe-airdrop/react/useEcdsaClaim.d.ts +23 -0
  104. package/dist/fhe-airdrop/react/useEffectiveUpgradeable.d.ts +20 -0
  105. package/dist/fhe-airdrop/react/useExtendClaimWindow.d.ts +17 -12
  106. package/dist/fhe-airdrop/react/useFactoryFees.d.ts +28 -0
  107. package/dist/fhe-airdrop/react/useFactoryRegistry.d.ts +35 -0
  108. package/dist/fhe-airdrop/react/useFundAirdrop.d.ts +35 -0
  109. package/dist/fhe-airdrop/react/useGrantInstanceRoles.d.ts +35 -0
  110. package/dist/fhe-airdrop/react/useMerkleClaim.d.ts +34 -0
  111. package/dist/fhe-airdrop/react/useMerkleRoot.d.ts +15 -0
  112. package/dist/fhe-airdrop/react/useSetMerkleRoot.d.ts +22 -0
  113. package/dist/fhe-airdrop/react/useWithdrawConfidential.d.ts +23 -0
  114. package/dist/fhe-airdrop/roles.d.ts +147 -0
  115. package/dist/fhe-airdrop/types.d.ts +68 -55
  116. package/dist/fhe-disperse/errors.d.ts +55 -0
  117. package/dist/fhe-disperse/index.cjs +34 -25
  118. package/dist/fhe-disperse/index.d.cts +1 -1
  119. package/dist/fhe-disperse/index.d.ts +1 -1
  120. package/dist/fhe-disperse/index.js +6 -5
  121. package/dist/fhe-disperse/react/index.cjs +42 -23
  122. package/dist/fhe-disperse/react/index.d.cts +3 -1
  123. package/dist/fhe-disperse/react/index.d.ts +3 -1
  124. package/dist/fhe-disperse/react/index.js +9 -6
  125. package/dist/fhe-vesting/advanced/index.cjs +8 -7
  126. package/dist/fhe-vesting/advanced/index.js +6 -5
  127. package/dist/fhe-vesting/advanced/react/index.cjs +12 -11
  128. package/dist/fhe-vesting/advanced/react/index.js +9 -8
  129. package/dist/fhe-vesting/index.cjs +35 -34
  130. package/dist/fhe-vesting/index.js +7 -6
  131. package/dist/fhe-vesting/manager.d.ts +19 -0
  132. package/dist/fhe-vesting/react/index.cjs +160 -140
  133. package/dist/fhe-vesting/react/index.d.cts +6 -4
  134. package/dist/fhe-vesting/react/index.d.ts +6 -4
  135. package/dist/fhe-vesting/react/index.js +24 -16
  136. package/dist/fhe-vesting/react/useAccessClaimableAmount.d.ts +11 -3
  137. package/dist/fhe-vesting/react/useAccessSettledAmount.d.ts +11 -3
  138. package/dist/fhe-vesting/react/useAccessTotalAllocation.d.ts +11 -3
  139. package/dist/fhe-vesting/react/useAccessVestedAmount.d.ts +11 -3
  140. package/dist/fhe-vesting/react/useAdminGetClaimableAmount.d.ts +1 -1
  141. package/dist/fhe-vesting/react/useAdminGetSettledAmount.d.ts +1 -1
  142. package/dist/fhe-vesting/react/useAdminGetTotalAllocation.d.ts +1 -1
  143. package/dist/fhe-vesting/react/useAdminGetVestedAmount.d.ts +1 -1
  144. package/dist/fhe-vesting/react/useAdminPartialClaim.d.ts +8 -0
  145. package/dist/fhe-vesting/react/useClaim.d.ts +1 -1
  146. package/dist/fhe-vesting/react/useDiscloseHandleToParty.d.ts +1 -1
  147. package/dist/fhe-vesting/react/useManagerDiscloseHandleToParty.d.ts +1 -1
  148. package/dist/fhe-vesting/react/usePartialClaim.d.ts +1 -1
  149. package/dist/fhe-vesting/react/useVestingInfo.d.ts +1 -1
  150. package/dist/fhe-vesting/types.d.ts +12 -1
  151. package/dist/index.cjs +27 -15
  152. package/dist/index.js +1 -1
  153. package/dist/testnet-faucet/index.cjs +17 -16
  154. package/dist/testnet-faucet/index.js +5 -4
  155. package/dist/testnet-faucet/react/index.cjs +11 -10
  156. package/dist/testnet-faucet/react/index.js +6 -5
  157. package/package.json +18 -9
  158. package/dist/chunk-4WPGQSNT.cjs +0 -44
  159. package/dist/chunk-6R4KNAPK.js +0 -1630
  160. package/dist/chunk-DUZIIRPF.js +0 -1655
  161. package/dist/chunk-MCRBVJGZ.cjs +0 -1637
  162. package/dist/chunk-ODLTEGHB.js +0 -41
  163. package/dist/chunk-ORFTDNFZ.js +0 -105
  164. package/dist/chunk-T46YXSBP.cjs +0 -109
  165. package/dist/chunk-TIUKIY5V.cjs +0 -1663
  166. package/dist/fhe-airdrop/advanced/factory-advanced.d.ts +0 -53
  167. package/dist/fhe-airdrop/advanced/react/usePredictAirdropAddress.d.ts +0 -49
  168. package/dist/fhe-airdrop/airdrop.d.ts +0 -310
  169. package/dist/fhe-airdrop/react/useAccessClaimAmount.d.ts +0 -31
  170. package/dist/fhe-airdrop/react/useAirdropCanExtendClaimWindow.d.ts +0 -7
  171. package/dist/fhe-airdrop/react/useAirdropClaim.d.ts +0 -27
  172. package/dist/fhe-airdrop/react/useAirdropClaimTypehash.d.ts +0 -10
  173. package/dist/fhe-airdrop/react/useAirdropClaimedSignatures.d.ts +0 -16
  174. package/dist/fhe-airdrop/react/useAirdropDeploymentBlockNumber.d.ts +0 -6
  175. package/dist/fhe-airdrop/react/useAirdropDomainSeparator.d.ts +0 -8
  176. package/dist/fhe-airdrop/react/useAirdropEndTime.d.ts +0 -10
  177. package/dist/fhe-airdrop/react/useAirdropFactoryCustomFee.d.ts +0 -17
  178. package/dist/fhe-airdrop/react/useAirdropFactoryDefaultGasFee.d.ts +0 -10
  179. package/dist/fhe-airdrop/react/useAirdropFactoryDisableCustomFee.d.ts +0 -15
  180. package/dist/fhe-airdrop/react/useAirdropFactoryFeeCollector.d.ts +0 -11
  181. package/dist/fhe-airdrop/react/useAirdropFactoryInitCodeHash.d.ts +0 -17
  182. package/dist/fhe-airdrop/react/useAirdropFactorySetCustomFee.d.ts +0 -17
  183. package/dist/fhe-airdrop/react/useAirdropFactorySetDefaultGasFee.d.ts +0 -16
  184. package/dist/fhe-airdrop/react/useAirdropFactorySetFeeCollector.d.ts +0 -15
  185. package/dist/fhe-airdrop/react/useAirdropGrantRole.d.ts +0 -16
  186. package/dist/fhe-airdrop/react/useAirdropHasClaimEnded.d.ts +0 -7
  187. package/dist/fhe-airdrop/react/useAirdropHasClaimStarted.d.ts +0 -7
  188. package/dist/fhe-airdrop/react/useAirdropIsClaimWindowActive.d.ts +0 -9
  189. package/dist/fhe-airdrop/react/useAirdropIsPaused.d.ts +0 -8
  190. package/dist/fhe-airdrop/react/useAirdropIsSignatureClaimed.d.ts +0 -22
  191. package/dist/fhe-airdrop/react/useAirdropIsSignatureValid.d.ts +0 -51
  192. package/dist/fhe-airdrop/react/useAirdropRevokeRole.d.ts +0 -15
  193. package/dist/fhe-airdrop/react/useAirdropStartTime.d.ts +0 -10
  194. package/dist/fhe-airdrop/react/useAirdropWithdrawGasFee.d.ts +0 -15
  195. package/dist/fhe-airdrop/react/useAirdropWithdrawOtherConfidentialToken.d.ts +0 -14
  196. package/dist/fhe-airdrop/react/useAirdropWithdrawOtherToken.d.ts +0 -14
  197. package/dist/fhe-airdrop/react/useClaim.d.ts +0 -31
  198. package/dist/fhe-airdrop/react/useConfidentialAirdropFactoryImplementation.d.ts +0 -11
  199. package/dist/fhe-airdrop/react/useCreateAndFundConfidentialAirdrop.d.ts +0 -41
  200. package/dist/fhe-airdrop/react/useCreateAndFundConfidentialAirdropAndGetAddress.d.ts +0 -48
  201. package/dist/fhe-airdrop/react/useCreateConfidentialAirdrop.d.ts +0 -29
  202. package/dist/fhe-airdrop/react/useCreateConfidentialAirdropAndGetAddress.d.ts +0 -31
  203. package/dist/fhe-airdrop/react/useDisableCustomFee.d.ts +0 -14
  204. package/dist/fhe-airdrop/react/useFactoryCustomFee.d.ts +0 -17
  205. package/dist/fhe-airdrop/react/useFactoryDefaultGasFee.d.ts +0 -10
  206. package/dist/fhe-airdrop/react/useFactoryFeeCollector.d.ts +0 -11
  207. package/dist/fhe-airdrop/react/useFactoryInitCodeHash.d.ts +0 -17
  208. package/dist/fhe-airdrop/react/useFundConfidentialAirdrop.d.ts +0 -33
  209. package/dist/fhe-airdrop/react/useGetClaimAmount.d.ts +0 -30
  210. package/dist/fhe-airdrop/react/usePreflightCreateAirdrop.d.ts +0 -51
  211. package/dist/fhe-airdrop/react/useSetCustomFee.d.ts +0 -16
  212. package/dist/fhe-airdrop/react/useSetDefaultGasFee.d.ts +0 -15
  213. package/dist/fhe-airdrop/react/useSetFeeCollector.d.ts +0 -14
  214. package/dist/fhe-airdrop/react/useSetPaused.d.ts +0 -14
  215. package/dist/fhe-airdrop/react/useSignClaimAuthorization.d.ts +0 -31
  216. package/dist/fhe-airdrop/react/useWithdraw.d.ts +0 -12
  217. package/dist/fhe-airdrop/react/useWithdrawOtherConfidentialToken.d.ts +0 -13
  218. package/dist/fhe-airdrop/react/useWithdrawOtherToken.d.ts +0 -13
  219. package/dist/fhe-vesting/react/useGetClaimableAmount.d.ts +0 -13
  220. package/dist/fhe-vesting/react/useGetSettledAmount.d.ts +0 -14
  221. package/dist/fhe-vesting/react/useGetTotalAllocation.d.ts +0 -13
  222. package/dist/fhe-vesting/react/useGetVestedAmount.d.ts +0 -25
@@ -0,0 +1,297 @@
1
+ import type { Address, Hex } from "viem";
2
+ import type { WriteAccountOverride } from "./airdrop-base.js";
3
+ import { type EncryptorSource } from "./encryption.js";
4
+ import type { ConfidentialAirdropFactoryClient } from "./factory.js";
5
+ import type { MerkleAirdropClient } from "./merkle.js";
6
+ import { type MerkleLeafInput } from "./merkle-tree.js";
7
+ import type { DeploymentMode } from "./constants.js";
8
+ import type { BuiltCampaign, CampaignRecipient, MerkleAirdropParams } from "./types.js";
9
+ export type { BuiltCampaign, CampaignEntry, CampaignRecipient } from "./types.js";
10
+ /**
11
+ * Reject the campaign shapes that produce an unusable or misleading tree,
12
+ * before any encryption work is done.
13
+ *
14
+ * Five rules, each of which is silent rather than loud if left unchecked:
15
+ *
16
+ * - **Well-formed address.** A malformed one would otherwise escape as a raw
17
+ * viem `InvalidAddressError` out of the zero-address check below - an
18
+ * untyped throw from the function whose job is producing typed ones.
19
+ * - **No duplicate recipient.** `claimedAmount` is a cumulative running total
20
+ * keyed by account alone (`ConfidentialAirdropMerkleStorage`), and a claim
21
+ * pays `total - min(total, claimed)`. Two leaves for one account under one
22
+ * root therefore pay `max(totalA, totalB)`, in either claim order — never
23
+ * the sum the author almost certainly intended.
24
+ * - **No zero address.** A zero-address leaf is unclaimable and silently
25
+ * burns its share of the pool.
26
+ * - **`uint64` range.** The contract's `euint64` arithmetic cannot represent
27
+ * anything else; a wider total would be rejected far downstream, at
28
+ * encryption time.
29
+ * - **Non-empty.** An empty tree has no root to publish.
30
+ *
31
+ * @param recipients The campaign roster to check.
32
+ * @throws {@link InvalidArgumentError} on any of the five. The thrown error
33
+ * never carries a `cumulativeTotal`: the totals are the confidential part of
34
+ * a confidential airdrop, so they are named by index, never by value.
35
+ *
36
+ * @alpha
37
+ */
38
+ export declare function validateCampaignRecipients(recipients: readonly CampaignRecipient[]): void;
39
+ /**
40
+ * Real implementation behind {@link validateCampaignRecipients}, parameterised
41
+ * on the function name a thrown {@link InvalidArgumentError} blames.
42
+ *
43
+ * Not part of the public surface - exported from this module only so the
44
+ * orchestrators can attribute a roster failure to themselves rather than to a
45
+ * validator the caller never invoked. Neither barrel re-exports it. Same
46
+ * pattern as `buildMerkleTreeInternal` in `./merkle-tree.js`.
47
+ */
48
+ export declare function validateCampaignRecipientsInternal(recipients: readonly CampaignRecipient[], method: string): void;
49
+ /**
50
+ * Inputs for {@link buildMerkleCampaign}.
51
+ *
52
+ * @alpha
53
+ */
54
+ export interface BuildMerkleCampaignArgs {
55
+ /** The LIVE `MerkleConfidentialAirdrop` instance every input is bound to. Not the factory, not the implementation. */
56
+ instance: Address;
57
+ recipients: readonly CampaignRecipient[];
58
+ encryptor: EncryptorSource;
59
+ }
60
+ /**
61
+ * One recipient's encrypted allocation, ready to be fed to {@link buildMerkleTree}.
62
+ *
63
+ * @alpha
64
+ */
65
+ export interface EncryptedCampaignLeaf extends MerkleLeafInput {
66
+ /** The KMS input proof binding `handle` to `(instance, recipient)`. Required at claim time, unused by the tree. */
67
+ inputProof: Hex;
68
+ }
69
+ /**
70
+ * Inputs for {@link encryptCampaignAmounts}.
71
+ *
72
+ * @alpha
73
+ */
74
+ export interface EncryptCampaignAmountsArgs {
75
+ /** The LIVE `MerkleConfidentialAirdrop` instance every input is bound to. Not the factory, not the implementation. */
76
+ instance: Address;
77
+ recipients: readonly CampaignRecipient[];
78
+ encryptor: EncryptorSource;
79
+ }
80
+ /**
81
+ * Encrypt a plaintext roster into per-recipient handles, without building a tree.
82
+ *
83
+ * Use this when you want the two stages apart — to persist the handles before
84
+ * publishing a root, or to hand them to something else that builds the tree.
85
+ * If you just want a campaign, {@link buildMerkleCampaign} does both.
86
+ *
87
+ * **One relayer request per recipient, issued concurrently.** Each input binds
88
+ * to `(instance, that recipient)`, so they cannot share a proof: a single
89
+ * batched proof binds every value to one account and produces a campaign only
90
+ * that account can claim against.
91
+ *
92
+ * **The output is not reproducible.** Encryption is randomised, so calling this
93
+ * twice with the same roster yields different handles and therefore a different
94
+ * root. Persist what you get back; you cannot regenerate it.
95
+ *
96
+ * @param args The live instance, the roster, and an eager or lazy encryptor.
97
+ * @returns One `{ recipient, handle, inputProof }` per roster entry, in roster order.
98
+ * @throws {@link InvalidArgumentError} on any roster problem {@link validateCampaignRecipients} rejects, or a zero `instance`.
99
+ * @throws {@link MissingEncryptorError} when `encryptor` resolves to `undefined`.
100
+ *
101
+ * @example
102
+ * const leaves = await encryptCampaignAmounts({ instance: airdrop, recipients, encryptor });
103
+ * const { root, entries } = buildMerkleTree({ instance: airdrop, leaves });
104
+ *
105
+ * @alpha
106
+ */
107
+ export declare function encryptCampaignAmounts(args: EncryptCampaignAmountsArgs): Promise<readonly EncryptedCampaignLeaf[]>;
108
+ /**
109
+ * Encrypt every recipient's cumulative total against their own address, then
110
+ * build the tree those ciphertexts belong to.
111
+ *
112
+ * Use this on the **mutable-root** path: the instance already exists, so its
113
+ * address is known and encryption can bind to it directly. Publish the returned
114
+ * `root` with {@link MerkleAirdropClient.setMerkleRoot} — or let
115
+ * {@link rotateMerkleRoot} do both in one call. For an instance whose root is
116
+ * fixed at create time, use {@link planMerkleCampaign} instead: this function
117
+ * cannot help you, because there is no address to encrypt against yet.
118
+ *
119
+ * **Distribution is yours.** The returned `entries` are the campaign — nothing
120
+ * about them is recoverable from the chain. The instance stores only the
121
+ * 32-byte root; there is no getter that maps an account to its handle, its
122
+ * input proof, or its Merkle branch, and no event that emits them. A recipient
123
+ * who does not hold their own `(handle, inputProof, merkleProof)` triple cannot
124
+ * claim, and no amount of on-chain data will reconstruct it. Persist the
125
+ * entries when this resolves and serve each recipient theirs.
126
+ *
127
+ * **One relayer request per recipient, issued concurrently.** Each input has a
128
+ * different `userAddress`, so they cannot share a proof — see the note on
129
+ * `encryptUint64Batch` below. Large rosters fan out correspondingly; chunk the
130
+ * roster yourself if your relayer rate-limits.
131
+ *
132
+ * **Already hold the handles?** This function encrypts unconditionally, and
133
+ * encryption is randomised — so re-encrypting handles that exist elsewhere
134
+ * produces a tree committing to handles nobody holds. Use
135
+ * {@link buildMerkleTree} directly instead.
136
+ *
137
+ * @param args The live instance, the roster, and an eager or lazy encryptor.
138
+ * @returns The root to publish and one proof-bearing {@link CampaignEntry} per recipient, in roster order.
139
+ * @throws {@link InvalidArgumentError} on any roster problem {@link validateCampaignRecipients} rejects, or a zero `instance`.
140
+ * @throws {@link MissingEncryptorError} when `encryptor` resolves to `undefined`.
141
+ *
142
+ * @example
143
+ * const { root, entries } = await buildMerkleCampaign({
144
+ * instance: airdrop.address,
145
+ * recipients: [{ recipient: alice, cumulativeTotal: 1_000_000n }],
146
+ * encryptor,
147
+ * });
148
+ * await airdrop.setMerkleRoot({ newRoot: root });
149
+ * // then hand `entries[i]` to `entries[i].recipient`, out of band
150
+ *
151
+ * @alpha
152
+ */
153
+ export declare function buildMerkleCampaign({ instance, recipients, encryptor, }: BuildMerkleCampaignArgs): Promise<BuiltCampaign>;
154
+ /**
155
+ * Inputs for {@link planMerkleCampaign}.
156
+ *
157
+ * @alpha
158
+ */
159
+ export interface PlanMerkleCampaignArgs {
160
+ factory: ConfidentialAirdropFactoryClient;
161
+ /** The exact params the subsequent `createMerkleAirdrop` will use, except `merkleRoot` — supply the planned root there. */
162
+ params: MerkleAirdropParams;
163
+ mode: DeploymentMode;
164
+ /** The account that will send `createMerkleAirdrop`. CREATE2 salts are per-deployer. */
165
+ creator: Address;
166
+ userSalt: Hex;
167
+ recipients: readonly CampaignRecipient[];
168
+ encryptor: EncryptorSource;
169
+ }
170
+ /**
171
+ * A campaign built against a not-yet-deployed instance, plus the evidence needed to trust the prediction.
172
+ *
173
+ * @alpha
174
+ */
175
+ export interface PlannedCampaign extends BuiltCampaign {
176
+ /** Where `createMerkleAirdrop({ mode, userSalt })` from `creator` will land. Every entry is bound to this address. */
177
+ predictedAddress: Address;
178
+ /** The factory's Merkle init-code hash read BEFORE the address was predicted. */
179
+ initCodeHashBefore: Hex;
180
+ /** The same hash read AFTER. Always equal to `initCodeHashBefore` on a returned plan - a difference throws instead. */
181
+ initCodeHashAfter: Hex;
182
+ }
183
+ /**
184
+ * Build a campaign for an instance that does not exist yet, so its root can be
185
+ * baked in at create time.
186
+ *
187
+ * This is the **immutable-root** path, and it exists because that path is
188
+ * otherwise circular: the root must be known before `createMerkleAirdrop`, the
189
+ * root depends on every recipient's ciphertext, and every ciphertext is bound
190
+ * to the instance address `createMerkleAirdrop` has not produced yet. The
191
+ * factory's `predictMerkleAirdropAddress` oracle breaks it — encryption binds
192
+ * to the predicted address, and the create call then lands exactly there.
193
+ *
194
+ * **Passing the planned root back in `params` is safe.** A predicted address
195
+ * commits only to `(implementation, mode, deployer, userSalt)`; the params
196
+ * struct is accepted by the oracle and ignored
197
+ * (`predictECDSAAirdropAddress` does not even name its params argument). So
198
+ * calling this with a placeholder root and then creating with the real one does
199
+ * not move the address. The corollary is the trap: two campaigns sharing a
200
+ * `(variant, mode, creator, userSalt)` tuple predict the SAME address however
201
+ * different their params — pick a fresh `userSalt` per campaign.
202
+ *
203
+ * **Drift is judged, the rest is not.** The factory's Merkle init-code hash is
204
+ * read once BEFORE `predictMerkleAirdropAddress` and once AFTER the campaign
205
+ * is built, so the window brackets the prediction itself as well as the
206
+ * build — an implementation-pointer swap landing in either gap is caught. A
207
+ * difference between the two means the factory's Merkle implementation
208
+ * pointer moved and `predictedAddress` is stale: every entry would be bound
209
+ * to an address the create will not produce, so this function throws
210
+ * {@link PredictionDriftError} rather than hand back a campaign that cannot
211
+ * be claimed. Both observations are still returned on the success path, for
212
+ * callers that want to record them. What it does NOT check is whether
213
+ * `creator` may deploy `mode` and whether the salt is free - run
214
+ * `preflightCreate` (`./guards.js`) for those, or let `createMerkleAirdrop`
215
+ * enforce them at send time.
216
+ *
217
+ * **Distribution is yours** — same as {@link buildMerkleCampaign}: the chain
218
+ * keeps only the root, so each recipient must be handed their own
219
+ * `(handle, inputProof, merkleProof)` out of band or they cannot claim.
220
+ *
221
+ * @param args The factory client, the create arguments the campaign is planned against, the roster and an encryptor.
222
+ * @returns The built campaign, the predicted instance address, and the two init-code-hash observations.
223
+ * @throws {@link InvalidArgumentError} on any roster problem {@link validateCampaignRecipients} rejects.
224
+ * @throws {@link MissingEncryptorError} when `encryptor` resolves to `undefined`.
225
+ * @throws {@link PredictionDriftError} when the factory's Merkle implementation pointer moved mid-build.
226
+ *
227
+ * @example
228
+ * const plan = await planMerkleCampaign({
229
+ * factory, params, mode: "clone", creator, userSalt, recipients, encryptor,
230
+ * });
231
+ * await factory.createMerkleAirdrop({
232
+ * params: { ...params, merkleRoot: plan.root, isMerkleRootMutable: false },
233
+ * mode: "clone",
234
+ * userSalt,
235
+ * });
236
+ *
237
+ * @alpha
238
+ */
239
+ export declare function planMerkleCampaign({ factory, params, mode, creator, userSalt, recipients, encryptor, }: PlanMerkleCampaignArgs): Promise<PlannedCampaign>;
240
+ /**
241
+ * Inputs for {@link rotateMerkleRoot}.
242
+ *
243
+ * @alpha
244
+ */
245
+ export interface RotateMerkleRootArgs extends WriteAccountOverride {
246
+ /** The live instance. Its `address` is read off the client — nothing is predicted here. */
247
+ airdrop: MerkleAirdropClient;
248
+ /** The FULL updated roster: cumulative totals, not the deltas since the last root. */
249
+ recipients: readonly CampaignRecipient[];
250
+ encryptor: EncryptorSource;
251
+ }
252
+ /**
253
+ * A rebuilt campaign together with the transaction that published its root.
254
+ *
255
+ * @alpha
256
+ */
257
+ export interface RotatedCampaign extends BuiltCampaign {
258
+ /** The `setMerkleRoot` transaction hash. */
259
+ hash: Hex;
260
+ }
261
+ /**
262
+ * Republish a campaign with updated cumulative totals: rebuild every entry
263
+ * against the live instance, then set the new root.
264
+ *
265
+ * **A rotation is a top-up, not a second payout.** `claimedAmount` survives the
266
+ * rotation, and a claim against the new root pays
267
+ * `newTotal - min(newTotal, alreadyDelivered)` — so `recipients` must carry
268
+ * each account's new CUMULATIVE total, never the increment. Passing increments
269
+ * pays out the increment minus everything already delivered, which for most
270
+ * rosters is encrypted zero. A total lower than what an account already
271
+ * received pays nothing; a rotation cannot claw back.
272
+ *
273
+ * Every entry is re-encrypted because the tree commits to handles, and a new
274
+ * total is a new ciphertext. Entries from the previous root do not survive:
275
+ * once the root moves, the old proofs no longer verify. **Distribute the new
276
+ * entries to every recipient**, including the ones whose total was unchanged —
277
+ * the chain stores only the root, so an un-updated recipient is simply stuck.
278
+ *
279
+ * Requires `MERKLE_ADMIN_ROLE` on the instance and an instance created with
280
+ * `isMerkleRootMutable: true`.
281
+ *
282
+ * @param args The live client, the full updated roster, an encryptor and an optional sending account.
283
+ * @returns The new root, the rebuilt entries, and the `setMerkleRoot` transaction hash.
284
+ * @throws {@link InvalidArgumentError} on any roster problem {@link validateCampaignRecipients} rejects.
285
+ * @throws {@link MissingEncryptorError} when `encryptor` resolves to `undefined`.
286
+ * @throws {@link FeatureDisabledError} when the instance was created with `isMerkleRootMutable: false`.
287
+ *
288
+ * @example
289
+ * const { root, entries, hash } = await rotateMerkleRoot({
290
+ * airdrop,
291
+ * recipients: [{ recipient: alice, cumulativeTotal: 1_500_000n }], // was 1_000_000n
292
+ * encryptor,
293
+ * });
294
+ *
295
+ * @alpha
296
+ */
297
+ export declare function rotateMerkleRoot({ airdrop, recipients, encryptor, account, }: RotateMerkleRootArgs): Promise<RotatedCampaign>;
@@ -0,0 +1,302 @@
1
+ import type { Address, Hex, PublicClient, WalletClient } from "viem";
2
+ import { type SdkTelemetry } from "../core/telemetry.js";
3
+ import type { WriteAccountOverride } from "./airdrop-base.js";
4
+ /**
5
+ * Whether `error` is the relayer's transient "the ACL hasn't propagated to
6
+ * the gateway yet" condition — as opposed to a genuine, non-retryable
7
+ * failure (a malformed handle, an unauthenticated request, an unrelated
8
+ * server error, etc.).
9
+ *
10
+ * **Why this exists:** after {@link ComplianceManagerClient.addDelegate}
11
+ * lands, a delegate is authorized on-chain immediately, but the gateway that
12
+ * serves a delegated read needs time to observe that change. Calling it in
13
+ * that window fails with the *same* HTTP status a permission failure or an
14
+ * unrelated server error would use, so a caller that treats every failure of
15
+ * that status as "access denied" will conclude the delegation is broken and
16
+ * go debug the wrong thing, when the correct response is to retry with
17
+ * backoff.
18
+ *
19
+ * The SDK does not call the relayer's delegated-decrypt itself (that call
20
+ * belongs to the relayer client the consumer already holds) — this function
21
+ * only classifies whatever error that call throws, so a caller can
22
+ * distinguish "retry me" from "this delegation really doesn't exist."
23
+ *
24
+ * **What counts as a match**, verified against the shipped `@zama-fhe/sdk`
25
+ * source rather than assumed (see the module comment above):
26
+ * - `error.code === "DELEGATION_NOT_PROPAGATED"` or
27
+ * `error.name === "DelegationNotPropagatedError"` — an exact discriminator,
28
+ * true regardless of status or message. This is how the SDK's own
29
+ * `ConfidentialFungibleToken#decryptBalanceAs` reports the condition, and
30
+ * that error carries no status field at all.
31
+ * - Otherwise, a status of `400` **or** `500` (read from `.status`,
32
+ * `.statusCode`, `.cause.status`, or `.cause.statusCode` — a raw relayer
33
+ * error may report it on any of those four) combined with a message (read
34
+ * from `.message` or `.cause.message`) that names the propagation
35
+ * condition — see {@link matchesPropagationMessage}.
36
+ *
37
+ * **Erring broad is the correct trade-off here**, not erring narrow: this
38
+ * classifier only gates whether a caller retries a read. A false positive
39
+ * costs a handful of unnecessary retries; a false negative sends an engineer
40
+ * to debug correct delegation wiring that was never broken. The matcher is
41
+ * therefore permissive about status and phrasing, while still refusing to
42
+ * classify a message that says nothing about propagation — an unrelated 400
43
+ * or 500 (bad signature, malformed handle, a genuine outage) still returns
44
+ * `false`.
45
+ *
46
+ * @param error The error thrown by a relayer's delegated-decrypt call — a
47
+ * plain object, an `Error` subclass, or the `@zama-fhe/sdk` package's own
48
+ * `DelegationNotPropagatedError` / `RelayerRequestFailedError` all satisfy
49
+ * this; only duck-typed field access is used, so no import of
50
+ * `@zama-fhe/sdk` (an optional peer dependency) is required.
51
+ * @returns `true` for the propagation condition, in any of the shapes above.
52
+ *
53
+ * @example
54
+ * try {
55
+ * await relayer.delegatedUserDecrypt({ handle, delegate });
56
+ * } catch (err) {
57
+ * if (isAclPropagationError(err)) {
58
+ * // retry with backoff — the delegation is fine, the gateway just hasn't caught up yet
59
+ * } else {
60
+ * throw err;
61
+ * }
62
+ * }
63
+ *
64
+ * @alpha
65
+ */
66
+ export declare function isAclPropagationError(error: unknown): boolean;
67
+ /** @alpha */
68
+ export interface ComplianceManagerClientConfig {
69
+ publicClient: PublicClient;
70
+ walletClient?: WalletClient | undefined;
71
+ /** The `ComplianceRoleManager` clone — read it off `factory.createX(...)`'s result, or `factory.complianceManagerOf(airdrop)`. */
72
+ address: Address;
73
+ /**
74
+ * Chain id used for the support check. Defaults to `publicClient.chain?.id`;
75
+ * one of the two must resolve, because the client refuses to talk to a
76
+ * chain it cannot name.
77
+ */
78
+ chainId?: number | undefined;
79
+ /**
80
+ * Optional telemetry sink. When provided, the SDK emits a
81
+ * `fhe-airdrop.client.init` event on construction and brackets write
82
+ * methods with named spans (`fhe-airdrop.compliance.addDelegate`, …).
83
+ * Defaults to a no-op.
84
+ */
85
+ telemetry?: SdkTelemetry | undefined;
86
+ }
87
+ /**
88
+ * Client for one `ComplianceRoleManager` clone — the per-airdrop-instance
89
+ * contract that holds account-level user-decryption delegations, so a
90
+ * compliance team or platform operator can decrypt an airdrop's handles
91
+ * without the airdrop contract itself granting them ACL one handle at a time.
92
+ *
93
+ * One clone serves exactly one airdrop instance (see {@link airdrop}), is
94
+ * created and `initialize`d atomically by the factory inside `createX(...)` —
95
+ * **this client never exposes `initialize`**, since calling it directly would
96
+ * either revert (already initialized) or, on a stand-alone clone nobody else
97
+ * has wired, produce a delegation nobody intended. There is consequently no
98
+ * externally observable "deployed but not yet wired" state: by the time an
99
+ * address is reachable through this client, `initialize` has already run.
100
+ *
101
+ * Two delegate slots exist per clone:
102
+ * - **The platform compliance delegate** — set once, at `initialize`, iff the
103
+ * factory's compliance policy was ON for that creator at create time.
104
+ * {@link complianceDelegate} returns the zero address when the policy was
105
+ * OFF; because of the point above, a zero return is unambiguous — it always
106
+ * means "this clone was created with the policy off," never "not wired
107
+ * yet." This delegate is **irrevocable by construction**: no method on this
108
+ * contract (or this client) ever revokes it.
109
+ * - **Client delegates** — zero or more addresses the client adds/removes
110
+ * itself via {@link addDelegate} / {@link revokeDelegate}, gated by
111
+ * {@link DELEGATION_ADMIN_ROLE}.
112
+ *
113
+ * **The propagation gotcha** (see {@link isAclPropagationError}'s TSDoc for
114
+ * the full mechanics): {@link addDelegate} and {@link revokeDelegate} are
115
+ * effective on-chain the instant their transaction lands, but the Zama
116
+ * gateway that serves a delegated read observes that change out of band, with
117
+ * a lag. A caller who wires a delegate and immediately attempts a delegated
118
+ * decrypt should expect the SDK-observed shapes of this condition — an HTTP
119
+ * 400 reading "ACL check not propagated" from the gateway directly, or, via
120
+ * `@zama-fhe/sdk`'s own `decryptBalanceAs`, an HTTP 500 wrapped as a
121
+ * `DelegationNotPropagatedError` — for a short window (the SDK's own guidance
122
+ * is 1-2 minutes), and should **retry with backoff** rather than conclude the
123
+ * delegation failed. This client does not call the relayer's delegated-decrypt
124
+ * itself (that belongs to whatever relayer client the consumer already
125
+ * holds); it only gives you {@link isAclPropagationError} to classify the
126
+ * error that call throws.
127
+ *
128
+ * @example
129
+ * const compliance = new ComplianceManagerClient({ publicClient, walletClient, address });
130
+ * await compliance.addDelegate({ delegate: complianceOfficer });
131
+ * // ... later, from wherever `delegatedUserDecrypt` is called:
132
+ * // if (isAclPropagationError(err)) { retry with backoff; }
133
+ *
134
+ * @alpha
135
+ */
136
+ export declare class ComplianceManagerClient {
137
+ #private;
138
+ readonly publicClient: PublicClient;
139
+ readonly walletClient?: WalletClient | undefined;
140
+ readonly address: Address;
141
+ readonly chainId: number;
142
+ constructor(config: ComplianceManagerClientConfig);
143
+ /**
144
+ * Add a client delegate: grants `delegate` permanent (never-expiring)
145
+ * user-decryption delegation over this clone's airdrop. Requires
146
+ * {@link DELEGATION_ADMIN_ROLE}.
147
+ *
148
+ * Effective on-chain immediately; see the class TSDoc for the gateway
149
+ * propagation lag before `delegatedUserDecrypt` catches up.
150
+ *
151
+ * @throws {@link InvalidArgumentError} (`argument: "delegate"`) when `delegate` is the zero address
152
+ * (`ZeroDelegate`), already an active client delegate (`DelegateAlreadyAdded`), or targets the
153
+ * irrevocable platform compliance delegate (`CannotManageComplianceDelegate`).
154
+ * @returns The transaction hash.
155
+ */
156
+ addDelegate(args: {
157
+ delegate: Address;
158
+ } & WriteAccountOverride): Promise<Hex>;
159
+ /**
160
+ * Revoke a client delegate. Requires {@link DELEGATION_ADMIN_ROLE}.
161
+ *
162
+ * Effective on-chain immediately — but off-chain, gateway-served
163
+ * `delegatedUserDecrypt` calls stop succeeding only once the gateway
164
+ * observes the revocation, which is not instantaneous either. Cannot target
165
+ * the platform compliance delegate, which is irrevocable by construction.
166
+ *
167
+ * **Not in the same block as {@link addDelegate} for the same delegate.**
168
+ * The FHEVM ACL rejects an add and a revoke of one delegate within a single
169
+ * block (`AlreadyDelegatedOrRevokedInSameBlock`), and because that revert
170
+ * comes from the ACL rather than from this contract, it surfaces as an
171
+ * opaque {@link ContractRevertError} with no decodable selector — nothing
172
+ * names the delegate or the cause. Batching an add and a revoke into one
173
+ * multicall, or sending both inside one block, is the way to hit it; wait a
174
+ * block between them. This is the sequencing counterpart to the propagation
175
+ * gotcha on the class TSDoc: that one is the gateway lagging the chain, this
176
+ * one is the chain refusing two conflicting writes at the same height.
177
+ *
178
+ * @throws {@link InvalidArgumentError} (`argument: "delegate"`) when `delegate` is the zero address
179
+ * (`ZeroDelegate`), not currently an active client delegate (`DelegateNotFound`), or targets the
180
+ * irrevocable platform compliance delegate (`CannotManageComplianceDelegate`).
181
+ * @returns The transaction hash.
182
+ */
183
+ revokeDelegate(args: {
184
+ delegate: Address;
185
+ } & WriteAccountOverride): Promise<Hex>;
186
+ /** The one airdrop instance this clone serves — set once, at `initialize`. */
187
+ airdrop(): Promise<Address>;
188
+ /**
189
+ * The platform compliance delegate.
190
+ *
191
+ * @returns The delegate address, or the zero address when this clone was
192
+ * created with the platform compliance policy OFF. Because `initialize`
193
+ * always runs atomically before this client can reach the clone (see the
194
+ * class TSDoc), a zero return never means "not wired yet" — there is no
195
+ * such observable state on this contract. It unambiguously means "no
196
+ * platform delegate for this airdrop."
197
+ */
198
+ complianceDelegate(): Promise<Address>;
199
+ /** The current set of active client delegates (excludes the platform compliance delegate, if any). */
200
+ clientDelegates(): Promise<readonly Address[]>;
201
+ /**
202
+ * Authoritative active-delegate check for `delegate` — reads the ACL
203
+ * expiration date directly rather than the contract's `EnumerableSet`
204
+ * mirror, so it reflects the platform compliance delegate too (which never
205
+ * appears in {@link clientDelegates}).
206
+ *
207
+ * On-chain truth only: a `true` result means the delegation is live in the
208
+ * ACL, not that the gateway has caught up with it yet — see the class
209
+ * TSDoc's propagation note.
210
+ */
211
+ isActiveDelegate(delegate: Address): Promise<boolean>;
212
+ /** Gates {@link addDelegate} / {@link revokeDelegate}. */
213
+ DELEGATION_ADMIN_ROLE(): Promise<Hex>;
214
+ /**
215
+ * OpenZeppelin's root role (`bytes32(0)`), read from the clone rather than
216
+ * hard-coded. It administers {@link DELEGATION_ADMIN_ROLE}.
217
+ */
218
+ DEFAULT_ADMIN_ROLE(): Promise<Hex>;
219
+ /**
220
+ * Whether `holder` holds `role`.
221
+ *
222
+ * The role subject is called `holder`, not `account`: on the writes below
223
+ * `account` already means "who sends this transaction", and one key cannot
224
+ * be both.
225
+ *
226
+ * @param args.role A `bytes32` from {@link DELEGATION_ADMIN_ROLE} or {@link DEFAULT_ADMIN_ROLE}.
227
+ */
228
+ hasRole(args: {
229
+ role: Hex;
230
+ holder: Address;
231
+ }): Promise<boolean>;
232
+ /** The role whose holders may {@link grantRole} and {@link revokeRole} `role`. */
233
+ getRoleAdmin(role: Hex): Promise<Hex>;
234
+ /** How many accounts hold `role`. */
235
+ getRoleMemberCount(role: Hex): Promise<bigint>;
236
+ /**
237
+ * The `index`-th holder of `role`, in `EnumerableSet` order - which is not
238
+ * stable across grants and revokes. Prefer {@link getRoleMembers}.
239
+ */
240
+ getRoleMember(args: {
241
+ role: Hex;
242
+ index: bigint;
243
+ }): Promise<Address>;
244
+ /**
245
+ * Every account currently holding `role`.
246
+ *
247
+ * With {@link DELEGATION_ADMIN_ROLE} this answers "who may add or revoke a
248
+ * delegate on this clone?" - the administrative counterpart to
249
+ * {@link clientDelegates}, which answers "who may currently decrypt?".
250
+ */
251
+ getRoleMembers(role: Hex): Promise<readonly Address[]>;
252
+ /**
253
+ * Grant `role` to `holder`. Requires the role's admin role
254
+ * ({@link getRoleAdmin}).
255
+ *
256
+ * This is how a second operator is added to {@link DELEGATION_ADMIN_ROLE} -
257
+ * the delegation verbs themselves are unaffected, the grant only widens who
258
+ * may call them.
259
+ *
260
+ * @returns The transaction hash.
261
+ */
262
+ grantRole(args: {
263
+ role: Hex;
264
+ holder: Address;
265
+ } & WriteAccountOverride): Promise<Hex>;
266
+ /**
267
+ * Revoke `role` from `holder`. Requires the role's admin role.
268
+ *
269
+ * Revoking a delegation admin does **not** revoke the delegations they
270
+ * created: an existing delegate keeps decrypting until
271
+ * {@link revokeDelegate} is called for it explicitly.
272
+ *
273
+ * @returns The transaction hash.
274
+ */
275
+ revokeRole(args: {
276
+ role: Hex;
277
+ holder: Address;
278
+ } & WriteAccountOverride): Promise<Hex>;
279
+ /**
280
+ * Give up `role` yourself.
281
+ *
282
+ * The contract's signature is `renounceRole(role, callerConfirmation)` and
283
+ * it reverts `AccessControlBadConfirmation` unless `callerConfirmation` is
284
+ * the sender, so this method takes no holder and fills the confirmation from
285
+ * the resolved sending account. Renouncing for somebody else is not a call
286
+ * that can succeed; use {@link revokeRole} to remove another account's role.
287
+ *
288
+ * @returns The transaction hash.
289
+ */
290
+ renounceRole(args: {
291
+ role: Hex;
292
+ } & WriteAccountOverride): Promise<Hex>;
293
+ }
294
+ /**
295
+ * Create a {@link ComplianceManagerClient}. Mirrors viem's `create*` convention.
296
+ *
297
+ * @example
298
+ * const compliance = createComplianceManagerClient({ publicClient, walletClient, address });
299
+ *
300
+ * @alpha
301
+ */
302
+ export declare function createComplianceManagerClient(config: ComplianceManagerClientConfig): ComplianceManagerClient;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Contract commit every vendored ABI and deployed address in this module resolves against.
3
+ *
4
+ * @alpha
5
+ */
6
+ export declare const AIRDROP_CONTRACTS_COMMIT = "8e5b144bdbcdf35b9f36b62f5257d795bf954e8e";
7
+ /**
8
+ * Deployment shell selected at create time. Mirrors the contract's `DeploymentMode` enum
9
+ * (`IConfidentialAirdropTypes.sol`): `enum DeploymentMode { Clone, UUPS }`.
10
+ *
11
+ * @alpha
12
+ */
13
+ export declare const DEPLOYMENT_MODE: {
14
+ readonly clone: 0;
15
+ readonly uups: 1;
16
+ };
17
+ /** @alpha */
18
+ export type DeploymentMode = keyof typeof DEPLOYMENT_MODE;
19
+ /**
20
+ * Replay-protection policy for ECDSA campaigns. Mirrors the contract's `DedupMode` enum
21
+ * (`IECDSAConfidentialAirdropTypes.sol`):
22
+ * `enum DedupMode { PerAddress, PerDedupId, Both, None }`.
23
+ *
24
+ * @alpha
25
+ */
26
+ export declare const DEDUP_MODE: {
27
+ readonly perAddress: 0;
28
+ readonly perDedupId: 1;
29
+ readonly both: 2;
30
+ readonly none: 3;
31
+ };
32
+ /** @alpha */
33
+ export type DedupMode = keyof typeof DEDUP_MODE;