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

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 (160) hide show
  1. package/CHANGELOG.md +92 -3
  2. package/README.md +76 -34
  3. package/SUPPORT.md +1 -1
  4. package/dist/{chunk-PYYSB5ZN.js → chunk-2ND7US2I.js} +1 -1
  5. package/dist/{chunk-EYDA6Q6C.js → chunk-3ZSPRHR3.js} +63 -12
  6. package/dist/{chunk-X7WBPCEU.js → chunk-67Q6KSVV.js} +4578 -3383
  7. package/dist/{chunk-UHHMVBLU.cjs → chunk-6AYJRUGP.cjs} +7 -50
  8. package/dist/{chunk-FEDX7B6T.cjs → chunk-6FUHF73F.cjs} +5 -5
  9. package/dist/{chunk-NWFMBLSQ.js → chunk-7KY4K4PH.js} +1 -1
  10. package/dist/{chunk-FHWSBGWE.cjs → chunk-ARZ5C3FS.cjs} +7 -7
  11. package/dist/{chunk-SPLNGUFF.js → chunk-AX6MQAWU.js} +2 -2
  12. package/dist/{chunk-IGO5XSPS.js → chunk-BSXEX2SH.js} +3 -3
  13. package/dist/{chunk-44YJPMQC.js → chunk-CHGY6B7L.js} +34 -81
  14. package/dist/{chunk-IUKKNJ2R.cjs → chunk-DFK5GCJP.cjs} +55 -72
  15. package/dist/{chunk-PZZK3O3S.cjs → chunk-E4IV4M4E.cjs} +4598 -3403
  16. package/dist/{chunk-A4DCEE33.js → chunk-GHGF65LN.js} +16 -12
  17. package/dist/{chunk-TWT3STIX.js → chunk-K3R27WX4.js} +8 -46
  18. package/dist/{chunk-GADGBQJO.js → chunk-KJUNBOJQ.js} +52 -71
  19. package/dist/{chunk-MM5BV5CS.cjs → chunk-PO3A2AQX.cjs} +4 -4
  20. package/dist/{chunk-EBLBPUPI.cjs → chunk-QHDMPT7I.cjs} +72 -19
  21. package/dist/{chunk-3YHBO2DL.cjs → chunk-S47IBDTA.cjs} +36 -83
  22. package/dist/{chunk-UG5RKLU2.cjs → chunk-SUYBAF27.cjs} +1 -1
  23. package/dist/{chunk-WJMEBBU7.js → chunk-TWU7L5H7.js} +5 -48
  24. package/dist/{chunk-WJLECC22.cjs → chunk-UUSSWOPR.cjs} +9 -47
  25. package/dist/{chunk-AREQJHKA.cjs → chunk-VHKMWWBA.cjs} +428 -22
  26. package/dist/{chunk-FT5H2Q7Y.cjs → chunk-YAL6JSAZ.cjs} +16 -12
  27. package/dist/{chunk-VW356KR3.js → chunk-YMWMIWBP.js} +421 -25
  28. package/dist/core/addresses.d.ts +4 -4
  29. package/dist/core/errors.d.ts +1 -1
  30. package/dist/core/index.d.ts +1 -0
  31. package/dist/core/pending.d.ts +57 -0
  32. package/dist/core/version.d.ts +1 -1
  33. package/dist/fhe/operators.d.ts +6 -5
  34. package/dist/fhe/types.d.ts +1 -1
  35. package/dist/fhe-airdrop/abis/airdrop-base.d.ts +97 -1
  36. package/dist/fhe-airdrop/abis/ecdsa.d.ts +117 -1
  37. package/dist/fhe-airdrop/abis/factory.d.ts +332 -1
  38. package/dist/fhe-airdrop/abis/merkle.d.ts +116 -1
  39. package/dist/fhe-airdrop/advanced/index.cjs +8 -4
  40. package/dist/fhe-airdrop/advanced/index.d.cts +1 -0
  41. package/dist/fhe-airdrop/advanced/index.d.ts +1 -0
  42. package/dist/fhe-airdrop/advanced/index.js +1 -1
  43. package/dist/fhe-airdrop/advanced/react/index.cjs +145 -137
  44. package/dist/fhe-airdrop/advanced/react/index.d.cts +1 -0
  45. package/dist/fhe-airdrop/advanced/react/index.d.ts +1 -0
  46. package/dist/fhe-airdrop/advanced/react/index.js +85 -78
  47. package/dist/fhe-airdrop/advanced/react/useClearCompliancePolicy.d.ts +3 -1
  48. package/dist/fhe-airdrop/advanced/react/useDisableCustomFee.d.ts +4 -1
  49. package/dist/fhe-airdrop/advanced/react/useFactoryComplianceDelegate.d.ts +2 -4
  50. package/dist/fhe-airdrop/advanced/react/useFactoryRenounceRole.d.ts +4 -3
  51. package/dist/fhe-airdrop/advanced/react/useFactoryRevokeRole.d.ts +9 -7
  52. package/dist/fhe-airdrop/advanced/react/useFactoryRoleMembers.d.ts +6 -5
  53. package/dist/fhe-airdrop/advanced/react/useSetComplianceDelegate.d.ts +7 -7
  54. package/dist/fhe-airdrop/advanced/react/useSetComplianceManagerImpl.d.ts +3 -1
  55. package/dist/fhe-airdrop/advanced/react/useSetCompliancePolicy.d.ts +2 -1
  56. package/dist/fhe-airdrop/advanced/react/useSetCustomFee.d.ts +4 -1
  57. package/dist/fhe-airdrop/advanced/react/useSetDefaultDelegateToCompliance.d.ts +5 -4
  58. package/dist/fhe-airdrop/advanced/react/useSetDefaultGasFee.d.ts +7 -3
  59. package/dist/fhe-airdrop/advanced/react/useSetMaxGasFee.d.ts +37 -0
  60. package/dist/fhe-airdrop/airdrop-base.d.ts +142 -18
  61. package/dist/fhe-airdrop/campaign.d.ts +37 -73
  62. package/dist/fhe-airdrop/compliance-clone.d.ts +21 -0
  63. package/dist/fhe-airdrop/constants.d.ts +11 -1
  64. package/dist/fhe-airdrop/ecdsa.d.ts +79 -26
  65. package/dist/fhe-airdrop/encryption.d.ts +19 -6
  66. package/dist/fhe-airdrop/errors.d.ts +136 -2
  67. package/dist/fhe-airdrop/factory-params.d.ts +2361 -0
  68. package/dist/fhe-airdrop/factory.d.ts +189 -75
  69. package/dist/fhe-airdrop/guards.d.ts +183 -19
  70. package/dist/fhe-airdrop/index.cjs +88 -56
  71. package/dist/fhe-airdrop/index.d.cts +12 -10
  72. package/dist/fhe-airdrop/index.d.ts +12 -10
  73. package/dist/fhe-airdrop/index.js +5 -5
  74. package/dist/fhe-airdrop/merkle-tree.d.ts +9 -9
  75. package/dist/fhe-airdrop/merkle.d.ts +32 -11
  76. package/dist/fhe-airdrop/react/_shared.d.ts +12 -6
  77. package/dist/fhe-airdrop/react/index.cjs +336 -240
  78. package/dist/fhe-airdrop/react/index.d.cts +19 -9
  79. package/dist/fhe-airdrop/react/index.d.ts +19 -9
  80. package/dist/fhe-airdrop/react/index.js +158 -97
  81. package/dist/fhe-airdrop/react/keys.d.ts +54 -7
  82. package/dist/fhe-airdrop/react/useAccessEcdsaClaimAmount.d.ts +6 -3
  83. package/dist/fhe-airdrop/react/useAccessMerkleClaimAmount.d.ts +2 -2
  84. package/dist/fhe-airdrop/react/useAirdropConfig.d.ts +8 -3
  85. package/dist/fhe-airdrop/react/useAirdropPause.d.ts +5 -0
  86. package/dist/fhe-airdrop/react/useBuildMerkleCampaign.d.ts +4 -6
  87. package/dist/fhe-airdrop/react/useComplianceManager.d.ts +2 -2
  88. package/dist/fhe-airdrop/react/useComplianceManagerOf.d.ts +1 -2
  89. package/dist/fhe-airdrop/react/useCreateAndFundEcdsaAirdrop.d.ts +16 -11
  90. package/dist/fhe-airdrop/react/useCreateAndFundMerkleAirdrop.d.ts +23 -7
  91. package/dist/fhe-airdrop/react/useCreateEcdsaAirdrop.d.ts +13 -8
  92. package/dist/fhe-airdrop/react/useCreateMerkleAirdrop.d.ts +27 -7
  93. package/dist/fhe-airdrop/react/useDedupMode.d.ts +16 -0
  94. package/dist/fhe-airdrop/react/useDiscloseHandleToParty.d.ts +4 -3
  95. package/dist/fhe-airdrop/react/useEcdsaClaim.d.ts +6 -4
  96. package/dist/fhe-airdrop/react/useEcdsaClaimAndUnwrap.d.ts +15 -8
  97. package/dist/fhe-airdrop/react/useEcdsaDomain.d.ts +1 -1
  98. package/dist/fhe-airdrop/react/useEncryptCampaignAmounts.d.ts +5 -7
  99. package/dist/fhe-airdrop/react/useExtendClaimWindow.d.ts +4 -1
  100. package/dist/fhe-airdrop/react/useFactoryFees.d.ts +11 -4
  101. package/dist/fhe-airdrop/react/useFundAirdrop.d.ts +3 -4
  102. package/dist/fhe-airdrop/react/useGrantInstanceRoles.d.ts +2 -1
  103. package/dist/fhe-airdrop/react/useIsAirdrop.d.ts +44 -0
  104. package/dist/fhe-airdrop/react/useIsSignatureValid.d.ts +5 -4
  105. package/dist/fhe-airdrop/react/useMerkleClaim.d.ts +4 -1
  106. package/dist/fhe-airdrop/react/useMerkleClaimAndUnwrap.d.ts +14 -3
  107. package/dist/fhe-airdrop/react/usePlanMerkleCampaign.d.ts +18 -3
  108. package/dist/fhe-airdrop/react/usePreflightClaim.d.ts +1 -1
  109. package/dist/fhe-airdrop/react/usePreflightCreateAirdrop.d.ts +34 -13
  110. package/dist/fhe-airdrop/react/useRefreshComplianceBalance.d.ts +36 -0
  111. package/dist/fhe-airdrop/react/useRescueERC20.d.ts +3 -3
  112. package/dist/fhe-airdrop/react/useRescueNativeToken.d.ts +23 -0
  113. package/dist/fhe-airdrop/react/useResolveGasFee.d.ts +30 -0
  114. package/dist/fhe-airdrop/react/useRotateMerkleRoot.d.ts +5 -2
  115. package/dist/fhe-airdrop/react/useSignClaimAuthorization.d.ts +4 -0
  116. package/dist/fhe-airdrop/react/useTokenOf.d.ts +29 -0
  117. package/dist/fhe-airdrop/react/useUnwrapRequest.d.ts +25 -0
  118. package/dist/fhe-airdrop/react/useWithdrawConfidential.d.ts +4 -0
  119. package/dist/fhe-airdrop/roles.d.ts +82 -7
  120. package/dist/fhe-airdrop/types.d.ts +122 -14
  121. package/dist/fhe-disperse/errors.d.ts +3 -3
  122. package/dist/fhe-disperse/index.cjs +22 -22
  123. package/dist/fhe-disperse/index.d.cts +2 -1
  124. package/dist/fhe-disperse/index.d.ts +2 -1
  125. package/dist/fhe-disperse/index.js +3 -3
  126. package/dist/fhe-disperse/react/index.cjs +27 -25
  127. package/dist/fhe-disperse/react/index.d.cts +2 -1
  128. package/dist/fhe-disperse/react/index.d.ts +2 -1
  129. package/dist/fhe-disperse/react/index.js +8 -6
  130. package/dist/fhe-disperse/react/useDisperse.d.ts +6 -2
  131. package/dist/fhe-disperse/react/useRegister.d.ts +9 -3
  132. package/dist/fhe-disperse/react/useSingletonWithdrawTokenFee.d.ts +7 -2
  133. package/dist/fhe-disperse/react/useWithdrawTokenFee.d.ts +7 -2
  134. package/dist/fhe-disperse/singleton.d.ts +33 -19
  135. package/dist/fhe-disperse/types.d.ts +48 -8
  136. package/dist/fhe-vesting/advanced/index.cjs +6 -6
  137. package/dist/fhe-vesting/advanced/index.js +4 -4
  138. package/dist/fhe-vesting/advanced/react/index.cjs +9 -9
  139. package/dist/fhe-vesting/advanced/react/index.js +6 -6
  140. package/dist/fhe-vesting/factory.d.ts +31 -8
  141. package/dist/fhe-vesting/index.cjs +23 -23
  142. package/dist/fhe-vesting/index.d.cts +3 -2
  143. package/dist/fhe-vesting/index.d.ts +3 -2
  144. package/dist/fhe-vesting/index.js +4 -4
  145. package/dist/fhe-vesting/manager.d.ts +27 -2
  146. package/dist/fhe-vesting/react/index.cjs +126 -126
  147. package/dist/fhe-vesting/react/index.d.cts +3 -2
  148. package/dist/fhe-vesting/react/index.d.ts +3 -2
  149. package/dist/fhe-vesting/react/index.js +5 -5
  150. package/dist/fhe-vesting/react/useCreateManager.d.ts +16 -9
  151. package/dist/fhe-vesting/react/useCreateManagerAndGetAddress.d.ts +9 -5
  152. package/dist/fhe-vesting/react/useSplitVesting.d.ts +9 -3
  153. package/dist/index.cjs +18 -18
  154. package/dist/index.js +1 -1
  155. package/dist/testnet-faucet/faucet.d.ts +3 -0
  156. package/dist/testnet-faucet/index.cjs +15 -15
  157. package/dist/testnet-faucet/index.js +3 -3
  158. package/dist/testnet-faucet/react/index.cjs +9 -9
  159. package/dist/testnet-faucet/react/index.js +4 -4
  160. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  import type { Address, Hex } from "viem";
2
2
  import type { EncryptedInput, EncryptedViewResult } from "../fhe/types.js";
3
3
  import { AirdropBaseClient, type AirdropBaseClientConfig, type WriteAccountOverride } from "./airdrop-base.js";
4
- import type { DedupMode } from "./constants.js";
4
+ import { type DedupMode } from "./constants.js";
5
5
  /**
6
6
  * EIP-712 domain name every `ECDSAConfidentialAirdrop` instance shares. Set once, at `initialize`.
7
7
  *
@@ -50,19 +50,12 @@ export declare const CLAIM_TYPEHASH: `0x${string}`;
50
50
  /** @alpha */
51
51
  export interface EcdsaAirdropClientConfig extends AirdropBaseClientConfig {
52
52
  /**
53
- * The replay-protection policy this instance was deployed with
54
- * (`perAddress` / `perDedupId` / `both` / `none`).
53
+ * The replay-protection policy this instance was created with, as configured on
54
+ * this client. Purely informational - no method branches on it.
55
55
  *
56
- * Required at construction because the contract exposes **no on-chain
57
- * getter** for it: `ECDSADedupStorage.dedupMode`
58
- * (`ConfidentialAirdropECDSAStorage.sol`) is a private field inside an
59
- * ERC-7201 namespaced storage struct, unreachable through any ABI-visible
60
- * read — every other constant this client exposes (`SIGNER_ROLE`,
61
- * `CLAIM_TYPEHASH`, `DOMAIN_SEPARATOR`) has a public getter; this one does
62
- * not. Pass the same value used at
63
- * `factory.createEcdsaAirdrop({ params: { dedupMode } })` time.
56
+ * @deprecated Read the policy from the chain with {@link EcdsaAirdropClient.readDedupMode}.
64
57
  */
65
- dedupMode: DedupMode;
58
+ dedupMode?: DedupMode | undefined;
66
59
  }
67
60
  /**
68
61
  * Inputs shared by {@link EcdsaAirdropClient.claim} and {@link EcdsaAirdropClient.claimAndUnwrap}.
@@ -73,12 +66,19 @@ export interface EcdsaClaimArgs extends WriteAccountOverride {
73
66
  /**
74
67
  * Payout destination. Omit (or pass the zero address) to default to the
75
68
  * sending account — mirrors the contract's own `to == address(0)` redirect
76
- * rule. Authorization (the signature), replay dedup and the FHE input
77
- * proof all stay bound to the sending account regardless of `to`; this
78
- * field only redirects where the tokens (and the recipient ACL) land.
69
+ * rule. Authorization (the signature), replay dedup and a non-empty FHE
70
+ * input proof all stay bound to the sending account regardless of `to`;
71
+ * this field only redirects where the tokens (and the recipient ACL) land.
79
72
  */
80
73
  to?: Address;
81
- /** The claimant's encrypted allocation, bound to `(airdrop, sendingAccount)` at encryption time. */
74
+ /**
75
+ * The claimant's encrypted allocation.
76
+ *
77
+ * A non-empty `inputProof` binds the handle to `(airdrop, sendingAccount)`. An empty one
78
+ * (`"0x"`) skips verification: a zero handle becomes an encrypted zero, and a nonzero handle
79
+ * is accepted only if the sender and the instance already hold ACL on it, else it reverts.
80
+ * See the guide's "Encryption binding differs by path".
81
+ */
82
82
  encryptedInput: EncryptedInput;
83
83
  /** The off-chain claim id bound into the signature. */
84
84
  dedupId: Hex;
@@ -95,6 +95,7 @@ export interface EcdsaClaimArgs extends WriteAccountOverride {
95
95
  * @alpha
96
96
  */
97
97
  export interface GetClaimAmountArgs extends WriteAccountOverride {
98
+ /** The claimant's encrypted allocation; the same empty-proof rule as {@link EcdsaClaimArgs.encryptedInput}. */
98
99
  encryptedInput: EncryptedInput;
99
100
  dedupId: Hex;
100
101
  deadline: bigint;
@@ -141,15 +142,21 @@ export interface IsSignatureValidArgs {
141
142
  * amount against the contract's `msg.value != gasFee()` revert.
142
143
  *
143
144
  * @example
144
- * const airdrop = new EcdsaAirdropClient({ publicClient, walletClient, address, dedupMode: "perAddress" });
145
+ * const airdrop = new EcdsaAirdropClient({ publicClient, walletClient, address });
145
146
  * const hash = await airdrop.claim({ encryptedInput, dedupId, deadline, signer, signature });
146
147
  *
147
148
  * @alpha
148
149
  */
149
150
  export declare class EcdsaAirdropClient extends AirdropBaseClient {
150
- /** @see EcdsaAirdropClientConfig.dedupMode */
151
- readonly dedupMode: DedupMode;
151
+ /** @deprecated Read the policy from the chain with {@link EcdsaAirdropClient.readDedupMode}. */
152
+ readonly dedupMode: DedupMode | undefined;
152
153
  constructor(config: EcdsaAirdropClientConfig);
154
+ /**
155
+ * Read the instance's frozen replay policy from the chain (`dedupMode()`).
156
+ *
157
+ * @throws {@link TokenOpsSdkError} when the contract returns an ordinal this SDK does not know.
158
+ */
159
+ readDedupMode(): Promise<DedupMode>;
153
160
  /**
154
161
  * Claim a signed encrypted allocation, delivering the tokens to `to`
155
162
  * (defaults to the sending account).
@@ -158,12 +165,18 @@ export declare class EcdsaAirdropClient extends AirdropBaseClient {
158
165
  * depth EIP-712 digest guard. Requires `msg.value == gasFee()` exactly —
159
166
  * handled for you; see the class TSDoc.
160
167
  *
168
+ * An empty `inputProof` is accepted only for a zero handle or one the sender and the
169
+ * instance already hold ACL on; see {@link EcdsaClaimArgs.encryptedInput}.
170
+ *
161
171
  * @throws {@link ClaimNotStartedError} before `startTime`.
162
172
  * @throws {@link ClaimWindowClosedError} after `endTime`.
163
173
  * @throws {@link SignatureExpiredError} after `args.deadline` has passed.
164
174
  * @throws {@link InvalidSignatureError} when `signer` lacks `SIGNER_ROLE` or the signature does not verify.
165
175
  * @throws {@link AlreadyClaimedError} on an address or digest replay.
166
176
  * @throws {@link DedupIdConsumedError} on a `dedupId` replay under `perDedupId`/`both`.
177
+ * @throws {@link FheHandleNotAllowedError} on an empty proof for a nonzero handle the sender
178
+ * holds no ACL on (`SenderNotAllowedToUseHandle`); the ACL's `SenderNotAllowed`, when only the
179
+ * instance lacks it, surfaces as a raw `ContractRevertError`.
167
180
  * @returns The transaction hash.
168
181
  */
169
182
  claim(args: EcdsaClaimArgs): Promise<Hex>;
@@ -173,12 +186,22 @@ export declare class EcdsaAirdropClient extends AirdropBaseClient {
173
186
  * `TokenNotUnwrappable` (surfaced as `FeatureDisabledError`) on a
174
187
  * non-unwrappable campaign.
175
188
  *
176
- * Same replay consumption and `msg.value == gasFee()` requirement as
177
- * {@link claim}.
189
+ * Same replay consumption, empty-proof rule and `msg.value == gasFee()`
190
+ * requirement as {@link claim}.
178
191
  *
179
- * @returns The transaction hash. The underlying ERC-20 is released later by
180
- * a separate, permissionless `finalizeUnwrap` — this hash is only the
181
- * unwrap request.
192
+ * **Discloses the amount immediately.** With the stock wrapper the unwrapped amount is
193
+ * publicly decryptable from this claim transaction (the emitted `unwrapRequestId` is its
194
+ * handle), so anyone can learn it at once; `finalizeUnwrap` only releases the ERC-20. Only
195
+ * {@link claim} keeps the amount confidential.
196
+ *
197
+ * @throws {@link FheHandleNotAllowedError} on an empty proof for a nonzero handle the sender
198
+ * holds no ACL on (`SenderNotAllowedToUseHandle`); the ACL's `SenderNotAllowed`, when only the
199
+ * instance lacks it, surfaces as a raw `ContractRevertError`.
200
+ * @returns The transaction hash. It is only the unwrap request: the underlying
201
+ * ERC-20 is released later by the wrapper's permissionless `finalizeUnwrap`. Read
202
+ * its `unwrapRequestId` with {@link AirdropBaseClient.readUnwrapRequest} (or
203
+ * {@link AirdropBaseClient.parseUnwrapRequest} over a receipt you hold), then
204
+ * finalize with Zama's `sdk.createToken(wrapper).finalizeUnwrap(unwrapRequestId)`.
182
205
  */
183
206
  claimAndUnwrap(args: EcdsaClaimArgs): Promise<Hex>;
184
207
  /**
@@ -186,11 +209,32 @@ export declare class EcdsaAirdropClient extends AirdropBaseClient {
186
209
  * consuming either replay guard — the same input can still be claimed for
187
210
  * real afterwards. No fee.
188
211
  *
212
+ * **It is repeatable, not unconditional** (audit-07). While the claim is
213
+ * still available this may be called any number of times; once it is not,
214
+ * this reverts with the same error the consuming claim would raise, in the
215
+ * same order: the mode's dedup slot first (`AddressAlreadyClaimed` /
216
+ * `DedupIdAlreadyClaimed`), the EIP-712 digest second (`SignatureAlreadyUsed`).
217
+ * A rejected preview performs no FHE op, grants no ACL and emits nothing.
218
+ *
219
+ * So this is not a probe for "has this been claimed" - use
220
+ * {@link isSignatureValid}, which never reverts and answers the same
221
+ * question for free. Reach for this when you want the AMOUNT.
222
+ *
189
223
  * An encrypted view: the contract calls `FHE.allow(amount, msg.sender)`, so
190
224
  * the result is recovered from the receipt's ACL `Allowed` event, never
191
225
  * from a simulation. See {@link AirdropBaseClient}'s class TSDoc.
192
226
  *
227
+ * The same empty-proof rule as {@link claim} applies; see {@link EcdsaClaimArgs.encryptedInput}.
228
+ *
193
229
  * @returns `{ handle, hash }` — pass `handle` to the Zama relayer's `userDecrypt`.
230
+ * @throws {@link AlreadyClaimedError} when this recipient's dedup slot or this exact digest is consumed.
231
+ * @throws {@link DedupIdConsumedError} when this `dedupId`'s slot is consumed.
232
+ * @throws {@link SignatureExpiredError} when `deadline` has passed.
233
+ * @throws {@link InvalidSignatureError} when the voucher was not signed by the instance's signer.
234
+ * @throws {@link PausedError} / {@link ClaimNotStartedError} / {@link ClaimWindowClosedError} when the campaign is paused or outside its claim window.
235
+ * @throws {@link FheHandleNotAllowedError} on an empty proof for a nonzero handle the sender
236
+ * holds no ACL on (`SenderNotAllowedToUseHandle`); the ACL's `SenderNotAllowed`, when only the
237
+ * instance lacks it, surfaces as a raw `ContractRevertError`.
194
238
  */
195
239
  getClaimAmount(args: GetClaimAmountArgs): Promise<EncryptedViewResult>;
196
240
  /**
@@ -203,10 +247,19 @@ export declare class EcdsaAirdropClient extends AirdropBaseClient {
203
247
  * invalid signature, an already-consumed digest, or an already-deduped
204
248
  * claim per this instance's `dedupMode`).
205
249
  *
250
+ * **Signer services should pre-check every voucher with this**, as an `eth_call` from the
251
+ * claimant while the window is open. It is `false` while paused, before `startTime` or past
252
+ * the deadline, so before the window opens verify off-chain with a `SignatureChecker`-equivalent
253
+ * check. It is also `false` for every voucher once the `SIGNER_ROLE` key is EIP-7702-delegated,
254
+ * although the key still holds the role; see the guide's "The ECDSA signer key".
255
+ *
206
256
  * @returns Whether the signature is currently valid and unconsumed for `args.recipient`.
207
257
  */
208
258
  isSignatureValid(args: IsSignatureValidArgs): Promise<boolean>;
209
- /** `bytes32` identifier for the role that must authorize a claim signature. */
259
+ /**
260
+ * `bytes32` identifier for the role that must authorize a claim signature. Hold it on a
261
+ * dedicated key that is never EIP-7702-delegated; see {@link isSignatureValid}.
262
+ */
210
263
  SIGNER_ROLE(): Promise<Hex>;
211
264
  /**
212
265
  * The live on-chain `CLAIM_TYPEHASH`. Prefer the module-level
@@ -256,7 +309,7 @@ export interface Eip712Domain {
256
309
  * Create an {@link EcdsaAirdropClient}. Mirrors viem's `create*` convention.
257
310
  *
258
311
  * @example
259
- * const airdrop = createEcdsaAirdropClient({ publicClient, walletClient, address, dedupMode: "perAddress" });
312
+ * const airdrop = createEcdsaAirdropClient({ publicClient, walletClient, address });
260
313
  *
261
314
  * @alpha
262
315
  */
@@ -79,20 +79,26 @@ export interface EncryptUint64BatchArgs {
79
79
  * The handle and proof are bound to `contractAddress` and `userAddress` — they
80
80
  * cannot be replayed against a different contract or sender. The binding must
81
81
  * name whichever contract calls `FHE.fromExternal` and whichever account sends
82
- * that transaction, and for airdrops those differ between the two flows:
82
+ * that transaction, and for airdrops those differ between the flows:
83
83
  *
84
84
  * - **Claiming** (`EcdsaAirdropClient.claim` / `claimAndUnwrap`): bind to
85
85
  * `(airdropInstanceAddress, recipientAddress)`. The `userAddress` MUST be
86
86
  * the **recipient** — the account that sends the claim — not the admin.
87
+ * This binding is checked only for a non-empty proof; an ECDSA claim with an
88
+ * empty proof (`"0x"`) skips verification and needs a zero handle or one the
89
+ * claimant and the instance already hold ACL on. Merkle claims always reject
90
+ * an empty proof.
87
91
  * - **Funding** (`ConfidentialAirdropFactoryClient.fundAirdrop` /
88
92
  * `createAndFund*`, i.e. a hand-built `FundInput.encryptedInput`):
89
93
  * bind to `(factoryAddress, funderAddress)`. The factory, not the instance,
90
- * is what calls `FHE.fromExternal` on the pool amount, and the funder is the
91
- * admin sending the create/fund transaction. A proof bound to the instance
92
- * reverts inside `FHE.fromExternal`.
94
+ * is what calls `FHE.fromExternal` on the pool amount, and the funder is
95
+ * whoever sends the create-and-fund or fund transaction. A proof bound to the
96
+ * instance reverts inside `FHE.fromExternal`.
97
+ * - **Merkle leaves**: bind each Merkle leaf to `(instance, instance)`, never
98
+ * `(instance, recipient)`; the campaign builders do this for you.
93
99
  *
94
- * Either way `FHE.fromExternal` rejects a proof bound to any other pair, so
95
- * the binding is a hard requirement, not a convention.
100
+ * Either way a non-empty proof bound to any other pair is rejected, so the
101
+ * binding is a hard requirement, not a convention.
96
102
  *
97
103
  * **Amount units:** TokenOps confidential (ERC-7984) tokens use a 6-decimals
98
104
  * convention (1 token = 1_000_000 base units), not the 18 decimals typical of
@@ -153,6 +159,13 @@ export declare function encryptUint64Batch({ encryptor, contractAddress, userAdd
153
159
  * `signer` as an explicit parameter and verifies the signature against it,
154
160
  * so the signature alone proves who signed.
155
161
  *
162
+ * **`SIGNER_ROLE` must be a dedicated key that is never EIP-7702-delegated** (or an
163
+ * ERC-1271 contract signer over this digest). A delegation gives the key code, so
164
+ * `SignatureChecker` switches to ERC-1271 against the delegate and every outstanding
165
+ * voucher fails (`InvalidSignature`), although the key still holds the role. Pre-check
166
+ * each voucher with `EcdsaAirdropClient.isSignatureValid`; see the guide's "The ECDSA
167
+ * signer key".
168
+ *
156
169
  * **Replay is bounded by the instance's `dedupMode`, not by this function.**
157
170
  * Every mode consumes the EIP-712 digest, so the exact same signature bytes
158
171
  * can never be replayed once used — but that is only ONE of two possible
@@ -1,5 +1,5 @@
1
1
  import type { Address, Hex } from "viem";
2
- import { TokenOpsSdkError } from "../core/errors.js";
2
+ import { InvalidArgumentError, TokenOpsSdkError } from "../core/errors.js";
3
3
  import type { RevertNameMapper } from "../core/revert-mapper.js";
4
4
  /**
5
5
  * A Merkle campaign's per-account claim state (`claimedAmount`) sits at an
@@ -166,6 +166,70 @@ export declare class PredictionDriftError extends TokenOpsSdkError {
166
166
  cause?: unknown;
167
167
  });
168
168
  }
169
+ /**
170
+ * A create reverted because one of its {@link CreateCommitments} no longer matches what the
171
+ * factory would deploy: the airdrop implementation, the compliance-manager implementation
172
+ * or the creator's resolved platform delegate moved between quote and send. Nothing was
173
+ * deployed and the salt is unused. Re-quote; for `airdrop`, also rebuild anything bound to
174
+ * the old prediction (Merkle leaves, vouchers, encrypted inputs).
175
+ *
176
+ * @alpha
177
+ */
178
+ export declare class CreateCommitmentMismatchError extends TokenOpsSdkError {
179
+ readonly name = "CreateCommitmentMismatchError";
180
+ readonly context: {
181
+ method: string;
182
+ contractAddress: Address;
183
+ field: "airdrop" | "complianceManagerImpl" | "complianceDelegate";
184
+ expected?: Address;
185
+ actual?: Address;
186
+ };
187
+ constructor(args: {
188
+ method: string;
189
+ contractAddress: Address;
190
+ field: "airdrop" | "complianceManagerImpl" | "complianceDelegate";
191
+ expected?: Address;
192
+ actual?: Address;
193
+ cause?: unknown;
194
+ });
195
+ }
196
+ /**
197
+ * `withdrawConfidential` reverted with `ClawbackRequiresPause`: the campaign is unpaused and
198
+ * still inside its claim window, so the clawback is refused. Pause first (`PAUSER_ROLE`), or
199
+ * run it outside the window (before `startTime` or after `endTime`).
200
+ *
201
+ * @alpha
202
+ */
203
+ export declare class ClawbackRequiresPauseError extends TokenOpsSdkError {
204
+ readonly name = "ClawbackRequiresPauseError";
205
+ readonly context: {
206
+ method: string;
207
+ contractAddress: Address;
208
+ };
209
+ constructor(args: {
210
+ method: string;
211
+ contractAddress: Address;
212
+ cause?: unknown;
213
+ });
214
+ }
215
+ /**
216
+ * `rescueNativeToken` reverted with `NativeRescueRequiresZeroFee`: the instance charges a gas
217
+ * fee, so its ETH is fee revenue and belongs to `withdrawGasFee`.
218
+ *
219
+ * @alpha
220
+ */
221
+ export declare class NativeRescueRequiresZeroFeeError extends TokenOpsSdkError {
222
+ readonly name = "NativeRescueRequiresZeroFeeError";
223
+ readonly context: {
224
+ method: string;
225
+ contractAddress: Address;
226
+ };
227
+ constructor(args: {
228
+ method: string;
229
+ contractAddress: Address;
230
+ cause?: unknown;
231
+ });
232
+ }
169
233
  /**
170
234
  * Factory `create*` reverted with `UpgradeabilityNotAllowed`: the creator's effective upgradeability policy is off.
171
235
  *
@@ -186,7 +250,7 @@ export declare class UpgradeabilityNotAllowedError extends TokenOpsSdkError {
186
250
  });
187
251
  }
188
252
  /**
189
- * `planInstanceRoleSplit` (`roles.ts`, Task 13) refuses to plan a
253
+ * `planInstanceRoleSplit` (`roles.ts`) refuses to plan a
190
254
  * `FEE_COLLECTOR_ROLE` grant: the role is its own role-admin (not
191
255
  * `DEFAULT_ADMIN_ROLE`), so a grant issued from the caller's admin role would
192
256
  * simply fail on-chain with `AccessControlUnauthorizedAccount`. An existing
@@ -315,4 +379,74 @@ export declare class ClaimWindowClosedError extends TokenOpsSdkError {
315
379
  cause?: unknown;
316
380
  });
317
381
  }
382
+ /**
383
+ * `create*` refused the fee the factory resolved for this creator: it landed
384
+ * above their `CommonAirdropParams.maxAcceptedGasFee`.
385
+ *
386
+ * The fee is frozen into the instance at initialization and is immutable
387
+ * afterwards, while the value that resolves is set by the factory's fee manager.
388
+ * The bound is how a creator declines a fee raised between planning and sending
389
+ * - so the fix is a deliberate one: re-send with a higher bound, or wait for the
390
+ * fee to come down. Raising the bound to {@link UINT96_MAX} accepts whatever the
391
+ * factory charges, now and at every later re-plan.
392
+ *
393
+ * @alpha
394
+ */
395
+ export declare class GasFeeNotAcceptedError extends TokenOpsSdkError {
396
+ readonly name = "GasFeeNotAcceptedError";
397
+ readonly context: {
398
+ method: string;
399
+ contractAddress: Address;
400
+ /** The fee the factory resolved for this creator, in wei. */
401
+ resolvedFee?: bigint;
402
+ /** The bound the creator declared, in wei. */
403
+ maxAcceptedGasFee?: bigint;
404
+ };
405
+ constructor(args: {
406
+ method: string;
407
+ contractAddress: Address;
408
+ resolvedFee?: bigint;
409
+ maxAcceptedGasFee?: bigint;
410
+ cause?: unknown;
411
+ });
412
+ }
413
+ /**
414
+ * The canonical factory's registry does not contain this address, so it is not
415
+ * an airdrop this SDK deployed.
416
+ *
417
+ * Instances are the wrong place to ask. An address with the same ABI, the same
418
+ * events and a pool the deployer controls is trivial to stand up, and nothing
419
+ * observable at the instance distinguishes it - `factory.isAirdrop` against a
420
+ * factory address taken from `src/core/addresses.ts` is the only check that
421
+ * means anything (audit-10).
422
+ *
423
+ * @alpha
424
+ */
425
+ export declare class UnrecognisedAirdropError extends TokenOpsSdkError {
426
+ readonly name = "UnrecognisedAirdropError";
427
+ readonly context: {
428
+ method: string;
429
+ contractAddress: Address;
430
+ factory: Address;
431
+ };
432
+ constructor(args: {
433
+ method: string;
434
+ /** The address that failed the check. */
435
+ contractAddress: Address;
436
+ /** The factory whose registry was consulted. */
437
+ factory: Address;
438
+ cause?: unknown;
439
+ });
440
+ }
318
441
  export declare const airdropProductMapper: RevertNameMapper;
442
+ /**
443
+ * The typed form of the factory's `GasFeeExceedsMaximum(gasFee, maxGasFee)`, shared by the
444
+ * revert mapper and `preflightCreate` so both paths surface one error code.
445
+ *
446
+ * @internal
447
+ */
448
+ export declare function gasFeeExceedsMaximumError(args: {
449
+ method: string;
450
+ gasFee: bigint | undefined;
451
+ maxGasFee: bigint | undefined;
452
+ }): InvalidArgumentError;