@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
@@ -0,0 +1,27 @@
1
+ import { type UseMutationResult } from "@tanstack/react-query";
2
+ import type { Hex } from "viem";
3
+ import type { WriteAccountOverride } from "../../airdrop-base.js";
4
+ import { type AirdropClientOptions } from "../../react/_shared.js";
5
+ /** @alpha */
6
+ export interface SetDefaultUpgradeableArgs extends WriteAccountOverride {
7
+ /** Whether creators without an override may deploy `mode: "uups"`. */
8
+ allowed: boolean;
9
+ }
10
+ /**
11
+ * Set the factory-wide default for whether a `create*` may deploy
12
+ * `mode: "uups"`. Requires `UPGRADE_MANAGER_ROLE`.
13
+ *
14
+ * **Invalidates:** the `fn "effectiveUpgradeable"`,
15
+ * `fn "upgradeabilityPolicy"` and `fn `preflightCreate`` PREFIXES.
16
+ * Prefix invalidation is correct here because the write is chain-wide: every
17
+ * cached creator without an override moves with the default, and a preflight
18
+ * result is exactly the thing that flips between allowed and
19
+ * `UpgradeabilityNotAllowedError`.
20
+ *
21
+ * @example
22
+ * const setDefault = useSetDefaultUpgradeable();
23
+ * await setDefault.mutateAsync({ allowed: false });
24
+ *
25
+ * @alpha
26
+ */
27
+ export declare function useSetDefaultUpgradeable(options?: AirdropClientOptions): UseMutationResult<Hex, Error, SetDefaultUpgradeableArgs>;
@@ -0,0 +1,34 @@
1
+ import { type UseMutationResult } from "@tanstack/react-query";
2
+ import type { Address, Hex } from "viem";
3
+ import type { WriteAccountOverride } from "../../airdrop-base.js";
4
+ import { type AirdropClientOptions } from "../../react/_shared.js";
5
+ /** @alpha */
6
+ export interface SetEcdsaImplementationArgs extends WriteAccountOverride {
7
+ /** The new ECDSA implementation. The zero address reverts. */
8
+ implementation: Address;
9
+ }
10
+ /**
11
+ * Point future `createEcdsaAirdrop*` calls at a new ECDSA implementation.
12
+ *
13
+ * Requires `IMPL_MANAGER_ROLE`. Deployed instances are untouched - a clone
14
+ * stays bound to the implementation live when it was created.
15
+ *
16
+ * **Moving this pointer moves every future predicted address.** Any campaign
17
+ * plan built before this write is stale, and on an immutable-root instance
18
+ * its entries would be unclaimable; that is what `PredictionDriftError`
19
+ * exists to catch.
20
+ *
21
+ * **Invalidates:** `useFactoryImplementations` (fn `"implementations"`), plus
22
+ * the fn `"getEcdsaInitCodeHash"`, `"predictEcdsaAirdropAddress"` and
23
+ * ``preflightCreate`` PREFIXES - every cached args combination of each,
24
+ * because the init-code hash, the predicted address and the create preflight
25
+ * all shift together with the pointer. Invalidating the predictions is what
26
+ * stops a mounted UI offering a dead address.
27
+ *
28
+ * @example
29
+ * const setEcdsaImpl = useSetEcdsaImplementation();
30
+ * await setEcdsaImpl.mutateAsync({ implementation: newEcdsaImpl });
31
+ *
32
+ * @alpha
33
+ */
34
+ export declare function useSetEcdsaImplementation(options?: AirdropClientOptions): UseMutationResult<Hex, Error, SetEcdsaImplementationArgs>;
@@ -0,0 +1,27 @@
1
+ import { type UseMutationResult } from "@tanstack/react-query";
2
+ import type { Address, Hex } from "viem";
3
+ import type { WriteAccountOverride } from "../../airdrop-base.js";
4
+ import { type AirdropClientOptions } from "../../react/_shared.js";
5
+ /** @alpha */
6
+ export interface SetFeeCollectorArgs extends WriteAccountOverride {
7
+ /** Where accrued claim-fee ETH withdraws to. The zero address reverts. */
8
+ feeCollector: Address;
9
+ }
10
+ /**
11
+ * Redirect where the factory's accrued claim-fee ETH withdraws to.
12
+ *
13
+ * Requires `FEE_MANAGER_ROLE`. The headless factory method takes positional
14
+ * args, so this hook adapts its object-shaped variables to
15
+ * `setFeeCollector(feeCollector, account?)`.
16
+ *
17
+ * **Invalidates:** this factory's `useFactoryFees` entry (fn `"fees"`), which
18
+ * bundles `feeCollector` with `defaultGasFee`. Nothing else moves - deployed
19
+ * instances hold no copy of the collector.
20
+ *
21
+ * @example
22
+ * const setCollector = useSetFeeCollector();
23
+ * await setCollector.mutateAsync({ feeCollector: treasuryAddress });
24
+ *
25
+ * @alpha
26
+ */
27
+ export declare function useSetFeeCollector(options?: AirdropClientOptions): UseMutationResult<Hex, Error, SetFeeCollectorArgs>;
@@ -0,0 +1,30 @@
1
+ import { type UseMutationResult } from "@tanstack/react-query";
2
+ import type { Address, Hex } from "viem";
3
+ import type { WriteAccountOverride } from "../../airdrop-base.js";
4
+ import { type AirdropClientOptions } from "../../react/_shared.js";
5
+ /** @alpha */
6
+ export interface SetMerkleImplementationArgs extends WriteAccountOverride {
7
+ /** The new Merkle implementation. The zero address reverts. */
8
+ implementation: Address;
9
+ }
10
+ /**
11
+ * Point future `createMerkleAirdrop*` calls at a new Merkle implementation.
12
+ *
13
+ * Requires `IMPL_MANAGER_ROLE`. Deployed instances are untouched.
14
+ *
15
+ * **Same prediction-drift hazard as {@link useSetEcdsaImplementation}, with a
16
+ * worse blast radius.** Merkle campaigns are commonly immutable-root: a plan
17
+ * whose entries were bound to an address predicted before this write has no
18
+ * on-chain repair, so re-plan rather than re-point.
19
+ *
20
+ * **Invalidates:** `useFactoryImplementations` (fn `"implementations"`), plus
21
+ * the fn `"getMerkleInitCodeHash"`, `"predictMerkleAirdropAddress"` and
22
+ * ``preflightCreate`` PREFIXES - every cached args combination of each.
23
+ *
24
+ * @example
25
+ * const setMerkleImpl = useSetMerkleImplementation();
26
+ * await setMerkleImpl.mutateAsync({ implementation: newMerkleImpl });
27
+ *
28
+ * @alpha
29
+ */
30
+ export declare function useSetMerkleImplementation(options?: AirdropClientOptions): UseMutationResult<Hex, Error, SetMerkleImplementationArgs>;
@@ -0,0 +1,31 @@
1
+ import { type UseMutationResult } from "@tanstack/react-query";
2
+ import type { Address, Hex } from "viem";
3
+ import type { WriteAccountOverride } from "../../airdrop-base.js";
4
+ import { type AirdropClientOptions } from "../../react/_shared.js";
5
+ /** @alpha */
6
+ export interface SetUpgradeabilityPolicyArgs extends WriteAccountOverride {
7
+ /** The creator the override applies to - not the admin sending the transaction. */
8
+ creator: Address;
9
+ /** Whether that creator may deploy `mode: "uups"`. */
10
+ allowed: boolean;
11
+ }
12
+ /**
13
+ * Override the factory's default upgradeability policy for one creator.
14
+ * Requires `UPGRADE_MANAGER_ROLE`.
15
+ *
16
+ * This is the write that flips whether that creator's next `mode: "uups"`
17
+ * create is refused with `UpgradeabilityNotAllowedError`.
18
+ *
19
+ * **Invalidates:** `fn "effectiveUpgradeable"` and
20
+ * `fn "upgradeabilityPolicy"` keyed on `args.creator` - the TARGET creator,
21
+ * never the sending admin - plus the `fn `preflightCreate`` PREFIX,
22
+ * which is keyed on the whole create payload rather than the creator alone
23
+ * and so cannot be narrowed here.
24
+ *
25
+ * @example
26
+ * const setPolicy = useSetUpgradeabilityPolicy();
27
+ * await setPolicy.mutateAsync({ creator, allowed: true });
28
+ *
29
+ * @alpha
30
+ */
31
+ export declare function useSetUpgradeabilityPolicy(options?: AirdropClientOptions): UseMutationResult<Hex, Error, SetUpgradeabilityPolicyArgs>;
@@ -588,6 +588,14 @@ export declare class AirdropBaseClient {
588
588
  protected mapRevert(method: string, err: unknown, account: Account | Address): TokenOpsSdkError;
589
589
  protected requireWallet(method: string): WalletClient;
590
590
  protected resolveAccount(wallet: WalletClient, override: Account | Address | undefined, method: string): Account | Address;
591
+ /**
592
+ * The address that will actually send the transaction, as a plain `Address`.
593
+ *
594
+ * Needed by any method whose arguments must be validated against the sender before
595
+ * the write — on the Merkle variant the claim identity, the payout destination and
596
+ * the submitter are three separate addresses with rules between them.
597
+ */
598
+ protected resolveSender(override: Account | Address | undefined, method: string): Address;
591
599
  }
592
600
  /**
593
601
  * Create an {@link AirdropBaseClient}. Mirrors viem's `create*` convention.
@@ -46,12 +46,45 @@ export declare function validateCampaignRecipients(recipients: readonly Campaign
46
46
  * pattern as `buildMerkleTreeInternal` in `./merkle-tree.js`.
47
47
  */
48
48
  export declare function validateCampaignRecipientsInternal(recipients: readonly CampaignRecipient[], method: string): void;
49
+ /**
50
+ * Who will submit the claims, for every builder that encrypts a roster.
51
+ *
52
+ * Follows the same shared-option pattern as `WriteAccountOverride`, because the choice
53
+ * applies identically to all four builders and is frozen once the root is published.
54
+ *
55
+ * @alpha
56
+ */
57
+ export interface CampaignSubmitterOption {
58
+ /**
59
+ * The single address that will send every `claim` in this campaign.
60
+ *
61
+ * Omit for a **self-claim** campaign: each recipient's input is bound to that
62
+ * recipient, one relayer request each, and only they can claim.
63
+ *
64
+ * Set it for a **relayed** campaign: the whole roster is bound to this one address and
65
+ * batched, so a single `inputProof` covers up to 32 recipients and only this address
66
+ * can submit. That batching is the point — one proof cannot be bound to many
67
+ * addresses, so per-recipient binding and batching are mutually exclusive.
68
+ *
69
+ * An input ciphertext packs at most 2048 bits, so a `euint64` roster is chunked at 32
70
+ * recipients per request; a longer roster simply issues more requests. Nothing about a
71
+ * claim changes, since every chunk's proof is bound to the same submitter.
72
+ *
73
+ * Either way the leaf still commits each recipient's own `account`, so payout and
74
+ * accounting are unaffected by who submits.
75
+ *
76
+ * **Frozen at publication.** An FHEVM handle encodes its `(instance, userAddress)`
77
+ * binding, so re-pointing a leaf at a different submitter means re-encrypting, which
78
+ * changes the handle and therefore the root. Choose before publishing, not after.
79
+ */
80
+ submitter?: Address;
81
+ }
49
82
  /**
50
83
  * Inputs for {@link buildMerkleCampaign}.
51
84
  *
52
85
  * @alpha
53
86
  */
54
- export interface BuildMerkleCampaignArgs {
87
+ export interface BuildMerkleCampaignArgs extends CampaignSubmitterOption {
55
88
  /** The LIVE `MerkleConfidentialAirdrop` instance every input is bound to. Not the factory, not the implementation. */
56
89
  instance: Address;
57
90
  recipients: readonly CampaignRecipient[];
@@ -63,7 +96,9 @@ export interface BuildMerkleCampaignArgs {
63
96
  * @alpha
64
97
  */
65
98
  export interface EncryptedCampaignLeaf extends MerkleLeafInput {
66
- /** The KMS input proof binding `handle` to `(instance, recipient)`. Required at claim time, unused by the tree. */
99
+ /** The only address that can submit this leaf — what `handle`/`inputProof` are bound to. */
100
+ boundTo: Address;
101
+ /** The KMS input proof binding `handle` to `(instance, boundTo)`. Required at claim time, unused by the tree. */
67
102
  inputProof: Hex;
68
103
  }
69
104
  /**
@@ -71,7 +106,7 @@ export interface EncryptedCampaignLeaf extends MerkleLeafInput {
71
106
  *
72
107
  * @alpha
73
108
  */
74
- export interface EncryptCampaignAmountsArgs {
109
+ export interface EncryptCampaignAmountsArgs extends CampaignSubmitterOption {
75
110
  /** The LIVE `MerkleConfidentialAirdrop` instance every input is bound to. Not the factory, not the implementation. */
76
111
  instance: Address;
77
112
  recipients: readonly CampaignRecipient[];
@@ -84,17 +119,17 @@ export interface EncryptCampaignAmountsArgs {
84
119
  * publishing a root, or to hand them to something else that builds the tree.
85
120
  * If you just want a campaign, {@link buildMerkleCampaign} does both.
86
121
  *
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.
122
+ * **Request count follows `submitter`.** Omitted: one relayer request per recipient,
123
+ * issued concurrently, each bound to that recipient. Set: one batched request per 32
124
+ * recipients (the 2048-bit input-ciphertext limit), every leaf claimable only by that
125
+ * submitter.
91
126
  *
92
127
  * **The output is not reproducible.** Encryption is randomised, so calling this
93
128
  * twice with the same roster yields different handles and therefore a different
94
129
  * root. Persist what you get back; you cannot regenerate it.
95
130
  *
96
131
  * @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.
132
+ * @returns One `{ account, boundTo, handle, inputProof }` per roster entry, in roster order.
98
133
  * @throws {@link InvalidArgumentError} on any roster problem {@link validateCampaignRecipients} rejects, or a zero `instance`.
99
134
  * @throws {@link MissingEncryptorError} when `encryptor` resolves to `undefined`.
100
135
  *
@@ -106,8 +141,9 @@ export interface EncryptCampaignAmountsArgs {
106
141
  */
107
142
  export declare function encryptCampaignAmounts(args: EncryptCampaignAmountsArgs): Promise<readonly EncryptedCampaignLeaf[]>;
108
143
  /**
109
- * Encrypt every recipient's cumulative total against their own address, then
110
- * build the tree those ciphertexts belong to.
144
+ * Encrypt every recipient's cumulative total, then build the tree those ciphertexts
145
+ * belong to. Binding follows `submitter`: omitted, each input is bound to its own
146
+ * recipient; set, the whole roster is bound to that one submitter.
111
147
  *
112
148
  * Use this on the **mutable-root** path: the instance already exists, so its
113
149
  * address is known and encryption can bind to it directly. Publish the returned
@@ -124,10 +160,9 @@ export declare function encryptCampaignAmounts(args: EncryptCampaignAmountsArgs)
124
160
  * claim, and no amount of on-chain data will reconstruct it. Persist the
125
161
  * entries when this resolves and serve each recipient theirs.
126
162
  *
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.
163
+ * **Relayer load follows `submitter`.** A self-claim roster fans out one request per
164
+ * recipient; a relayed roster issues one per 32. Either way, split the roster across
165
+ * calls yourself if your relayer rate-limits.
131
166
  *
132
167
  * **Already hold the handles?** This function encrypts unconditionally, and
133
168
  * encryption is randomised — so re-encrypting handles that exist elsewhere
@@ -146,17 +181,17 @@ export declare function encryptCampaignAmounts(args: EncryptCampaignAmountsArgs)
146
181
  * encryptor,
147
182
  * });
148
183
  * await airdrop.setMerkleRoot({ newRoot: root });
149
- * // then hand `entries[i]` to `entries[i].recipient`, out of band
184
+ * // then hand `entries[i]` to `entries[i].account`, out of band
150
185
  *
151
186
  * @alpha
152
187
  */
153
- export declare function buildMerkleCampaign({ instance, recipients, encryptor, }: BuildMerkleCampaignArgs): Promise<BuiltCampaign>;
188
+ export declare function buildMerkleCampaign({ instance, recipients, encryptor, submitter, }: BuildMerkleCampaignArgs): Promise<BuiltCampaign>;
154
189
  /**
155
190
  * Inputs for {@link planMerkleCampaign}.
156
191
  *
157
192
  * @alpha
158
193
  */
159
- export interface PlanMerkleCampaignArgs {
194
+ export interface PlanMerkleCampaignArgs extends CampaignSubmitterOption {
160
195
  factory: ConfidentialAirdropFactoryClient;
161
196
  /** The exact params the subsequent `createMerkleAirdrop` will use, except `merkleRoot` — supply the planned root there. */
162
197
  params: MerkleAirdropParams;
@@ -236,13 +271,13 @@ export interface PlannedCampaign extends BuiltCampaign {
236
271
  *
237
272
  * @alpha
238
273
  */
239
- export declare function planMerkleCampaign({ factory, params, mode, creator, userSalt, recipients, encryptor, }: PlanMerkleCampaignArgs): Promise<PlannedCampaign>;
274
+ export declare function planMerkleCampaign({ factory, params, mode, creator, userSalt, recipients, encryptor, submitter, }: PlanMerkleCampaignArgs): Promise<PlannedCampaign>;
240
275
  /**
241
276
  * Inputs for {@link rotateMerkleRoot}.
242
277
  *
243
278
  * @alpha
244
279
  */
245
- export interface RotateMerkleRootArgs extends WriteAccountOverride {
280
+ export interface RotateMerkleRootArgs extends WriteAccountOverride, CampaignSubmitterOption {
246
281
  /** The live instance. Its `address` is read off the client — nothing is predicted here. */
247
282
  airdrop: MerkleAirdropClient;
248
283
  /** The FULL updated roster: cumulative totals, not the deltas since the last root. */
@@ -276,6 +311,12 @@ export interface RotatedCampaign extends BuiltCampaign {
276
311
  * entries to every recipient**, including the ones whose total was unchanged —
277
312
  * the chain stores only the root, so an un-updated recipient is simply stuck.
278
313
  *
314
+ * **`submitter` is not remembered across rotations.** It is read from THIS call, not from
315
+ * the campaign being replaced, so omitting it on a rotation rebuilds a relayed campaign as
316
+ * a self-claim one - every new entry becomes claimable only by its own recipient, and the
317
+ * relayer that was settling for them can no longer submit anything. Pass the same
318
+ * `submitter` again to keep a relayed campaign relayed.
319
+ *
279
320
  * Requires `MERKLE_ADMIN_ROLE` on the instance and an instance created with
280
321
  * `isMerkleRootMutable: true`.
281
322
  *
@@ -294,4 +335,4 @@ export interface RotatedCampaign extends BuiltCampaign {
294
335
  *
295
336
  * @alpha
296
337
  */
297
- export declare function rotateMerkleRoot({ airdrop, recipients, encryptor, account, }: RotateMerkleRootArgs): Promise<RotatedCampaign>;
338
+ export declare function rotateMerkleRoot({ airdrop, recipients, encryptor, submitter, account, }: RotateMerkleRootArgs): Promise<RotatedCampaign>;
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * @alpha
5
5
  */
6
- export declare const AIRDROP_CONTRACTS_COMMIT = "8e5b144bdbcdf35b9f36b62f5257d795bf954e8e";
6
+ export declare const AIRDROP_CONTRACTS_COMMIT = "7175ac82f467f0f88c05aba1a4536892999b4251";
7
7
  /**
8
8
  * Deployment shell selected at create time. Mirrors the contract's `DeploymentMode` enum
9
9
  * (`IConfidentialAirdropTypes.sol`): `enum DeploymentMode { Clone, UUPS }`.
@@ -65,6 +65,34 @@ export declare class NonStockWrapperError extends TokenOpsSdkError {
65
65
  cause?: unknown;
66
66
  });
67
67
  }
68
+ /**
69
+ * A third party tried to redirect someone else's Merkle payout.
70
+ *
71
+ * `to` may differ from the claim identity only when the submitter IS that identity, so a
72
+ * relayer must leave `to` at `account` (or omit it). Raised by the SDK before the write
73
+ * and mapped from the contract's `UnauthorizedRedirect` revert, since the rule is decidable
74
+ * from the arguments alone — same two-producer shape as {@link NonStockWrapperError}.
75
+ *
76
+ * Carries all three addresses because the relation is the error: `to` on its own is a
77
+ * perfectly good address, and blaming it alone would be misleading.
78
+ *
79
+ * @alpha
80
+ */
81
+ export declare class UnauthorizedRedirectError extends TokenOpsSdkError {
82
+ readonly name = "UnauthorizedRedirectError";
83
+ readonly context: {
84
+ constraint: "merkle-third-party-redirect";
85
+ account?: Address;
86
+ to?: Address;
87
+ submitter?: Address;
88
+ };
89
+ constructor(args?: {
90
+ account?: Address;
91
+ to?: Address;
92
+ submitter?: Address;
93
+ cause?: unknown;
94
+ });
95
+ }
68
96
  /**
69
97
  * The two campaign variants, as used to label a prediction guard's context.
70
98
  *
@@ -207,6 +207,11 @@ export interface ClaimPreflightTarget {
207
207
  * the two blocked the claim.
208
208
  */
209
209
  paused(): Promise<boolean>;
210
+ /**
211
+ * Create-time flag; `claimAndUnwrap` reverts `TokenNotUnwrappable` when false. Optional
212
+ * so a hand-rolled target stays valid — the unwrap blocker is simply not reported then.
213
+ */
214
+ unwrappable?: () => Promise<boolean>;
210
215
  /** Present on `EcdsaAirdropClient` only. */
211
216
  isSignatureValid?: (args: {
212
217
  recipient: Address;
@@ -237,14 +242,51 @@ export interface EcdsaClaimPreflightSignature {
237
242
  */
238
243
  export interface PreflightClaimArgs {
239
244
  airdrop: ClaimPreflightTarget;
240
- /** The account that will send the claim - not the payout destination. */
245
+ /**
246
+ * The account that will SEND the claim, and therefore pays the exact-equality gas fee.
247
+ * On a relayed Merkle claim this is the relayer, not the entitled account.
248
+ */
241
249
  claimant: Address;
250
+ /**
251
+ * Merkle campaigns only: the claim identity, when it is not the submitter. Defaults to
252
+ * `claimant`. Supplying it enables the two argument-relation checks the contract makes
253
+ * before any FHE work — the zero identity and the third-party redirect rule.
254
+ */
255
+ account?: Address | undefined;
256
+ /** The payout destination, if one will be passed. Omitted means "defaults to `account`". */
257
+ to?: Address | undefined;
258
+ /**
259
+ * Set for `claimAndUnwrap`, which has no `account` parameter and is always submitted for
260
+ * the caller — so a claim identity that is not the submitter can never settle through it.
261
+ */
262
+ entrypoint?: "claim" | "claimAndUnwrap" | undefined;
242
263
  /**
243
264
  * ECDSA campaigns only. Supplied together with a client that exposes
244
265
  * `isSignatureValid`, it adds the authorisation check to the report.
245
266
  */
246
267
  signature?: EcdsaClaimPreflightSignature | undefined;
247
268
  }
269
+ /**
270
+ * The three argument-relation rules the Merkle claim path enforces before it touches the
271
+ * coprocessor. All are decidable from the arguments alone, so both `preflightClaim` and
272
+ * the client's own write path run them — no RPC, no chance of a wasted fee.
273
+ *
274
+ * @param account The claim identity (`claim`'s leading argument).
275
+ * @param submitter The address that will send the transaction.
276
+ * @param boundTo The address the entry's input proof is bound to, when known.
277
+ * @param to The payout destination, if one will be passed.
278
+ * @param entrypoint `claimAndUnwrap` is self-only; `claim` accepts a third-party submitter.
279
+ * @throws {@link InvalidArgumentError} on a zero `account`, a proof bound to another address, or a relayed `claimAndUnwrap`.
280
+ * @throws {@link UnauthorizedRedirectError} when a third party tries to redirect payout.
281
+ */
282
+ export declare function assertMerkleClaimIdentity(args: {
283
+ method: string;
284
+ account: Address;
285
+ submitter: Address;
286
+ boundTo?: Address | undefined;
287
+ to?: Address | undefined;
288
+ entrypoint?: "claim" | "claimAndUnwrap" | undefined;
289
+ }): void;
248
290
  /**
249
291
  * Report what would stop `claim` / `claimAndUnwrap` right now, without sending
250
292
  * anything.
@@ -252,7 +294,9 @@ export interface PreflightClaimArgs {
252
294
  * Checks the chain, the pause flag, the claim window on both ends, whether the
253
295
  * claimant can cover the instance's exact-equality gas fee, and - for an ECDSA
254
296
  * campaign given `signature` - whether the authorisation is currently valid and
255
- * unconsumed.
297
+ * unconsumed. Given `account` or `entrypoint`, it also checks the Merkle claim path's
298
+ * three argument relations: the zero identity, the third-party redirect rule, and
299
+ * `claimAndUnwrap`'s self-only constraint.
256
300
  *
257
301
  * The pause is read on its own rather than through `isClaimWindowActive()`:
258
302
  * that read ANDs the pause and the window together, so a `false` from it