@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.
- package/CHANGELOG.md +92 -3
- package/README.md +76 -34
- package/SUPPORT.md +1 -1
- package/dist/{chunk-PYYSB5ZN.js → chunk-2ND7US2I.js} +1 -1
- package/dist/{chunk-EYDA6Q6C.js → chunk-3ZSPRHR3.js} +63 -12
- package/dist/{chunk-X7WBPCEU.js → chunk-67Q6KSVV.js} +4578 -3383
- package/dist/{chunk-UHHMVBLU.cjs → chunk-6AYJRUGP.cjs} +7 -50
- package/dist/{chunk-FEDX7B6T.cjs → chunk-6FUHF73F.cjs} +5 -5
- package/dist/{chunk-NWFMBLSQ.js → chunk-7KY4K4PH.js} +1 -1
- package/dist/{chunk-FHWSBGWE.cjs → chunk-ARZ5C3FS.cjs} +7 -7
- package/dist/{chunk-SPLNGUFF.js → chunk-AX6MQAWU.js} +2 -2
- package/dist/{chunk-IGO5XSPS.js → chunk-BSXEX2SH.js} +3 -3
- package/dist/{chunk-44YJPMQC.js → chunk-CHGY6B7L.js} +34 -81
- package/dist/{chunk-IUKKNJ2R.cjs → chunk-DFK5GCJP.cjs} +55 -72
- package/dist/{chunk-PZZK3O3S.cjs → chunk-E4IV4M4E.cjs} +4598 -3403
- package/dist/{chunk-A4DCEE33.js → chunk-GHGF65LN.js} +16 -12
- package/dist/{chunk-TWT3STIX.js → chunk-K3R27WX4.js} +8 -46
- package/dist/{chunk-GADGBQJO.js → chunk-KJUNBOJQ.js} +52 -71
- package/dist/{chunk-MM5BV5CS.cjs → chunk-PO3A2AQX.cjs} +4 -4
- package/dist/{chunk-EBLBPUPI.cjs → chunk-QHDMPT7I.cjs} +72 -19
- package/dist/{chunk-3YHBO2DL.cjs → chunk-S47IBDTA.cjs} +36 -83
- package/dist/{chunk-UG5RKLU2.cjs → chunk-SUYBAF27.cjs} +1 -1
- package/dist/{chunk-WJMEBBU7.js → chunk-TWU7L5H7.js} +5 -48
- package/dist/{chunk-WJLECC22.cjs → chunk-UUSSWOPR.cjs} +9 -47
- package/dist/{chunk-AREQJHKA.cjs → chunk-VHKMWWBA.cjs} +428 -22
- package/dist/{chunk-FT5H2Q7Y.cjs → chunk-YAL6JSAZ.cjs} +16 -12
- package/dist/{chunk-VW356KR3.js → chunk-YMWMIWBP.js} +421 -25
- package/dist/core/addresses.d.ts +4 -4
- package/dist/core/errors.d.ts +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/pending.d.ts +57 -0
- package/dist/core/version.d.ts +1 -1
- package/dist/fhe/operators.d.ts +6 -5
- package/dist/fhe/types.d.ts +1 -1
- package/dist/fhe-airdrop/abis/airdrop-base.d.ts +97 -1
- package/dist/fhe-airdrop/abis/ecdsa.d.ts +117 -1
- package/dist/fhe-airdrop/abis/factory.d.ts +332 -1
- package/dist/fhe-airdrop/abis/merkle.d.ts +116 -1
- package/dist/fhe-airdrop/advanced/index.cjs +8 -4
- package/dist/fhe-airdrop/advanced/index.d.cts +1 -0
- package/dist/fhe-airdrop/advanced/index.d.ts +1 -0
- package/dist/fhe-airdrop/advanced/index.js +1 -1
- package/dist/fhe-airdrop/advanced/react/index.cjs +145 -137
- package/dist/fhe-airdrop/advanced/react/index.d.cts +1 -0
- package/dist/fhe-airdrop/advanced/react/index.d.ts +1 -0
- package/dist/fhe-airdrop/advanced/react/index.js +85 -78
- package/dist/fhe-airdrop/advanced/react/useClearCompliancePolicy.d.ts +3 -1
- package/dist/fhe-airdrop/advanced/react/useDisableCustomFee.d.ts +4 -1
- package/dist/fhe-airdrop/advanced/react/useFactoryComplianceDelegate.d.ts +2 -4
- package/dist/fhe-airdrop/advanced/react/useFactoryRenounceRole.d.ts +4 -3
- package/dist/fhe-airdrop/advanced/react/useFactoryRevokeRole.d.ts +9 -7
- package/dist/fhe-airdrop/advanced/react/useFactoryRoleMembers.d.ts +6 -5
- package/dist/fhe-airdrop/advanced/react/useSetComplianceDelegate.d.ts +7 -7
- package/dist/fhe-airdrop/advanced/react/useSetComplianceManagerImpl.d.ts +3 -1
- package/dist/fhe-airdrop/advanced/react/useSetCompliancePolicy.d.ts +2 -1
- package/dist/fhe-airdrop/advanced/react/useSetCustomFee.d.ts +4 -1
- package/dist/fhe-airdrop/advanced/react/useSetDefaultDelegateToCompliance.d.ts +5 -4
- package/dist/fhe-airdrop/advanced/react/useSetDefaultGasFee.d.ts +7 -3
- package/dist/fhe-airdrop/advanced/react/useSetMaxGasFee.d.ts +37 -0
- package/dist/fhe-airdrop/airdrop-base.d.ts +142 -18
- package/dist/fhe-airdrop/campaign.d.ts +37 -73
- package/dist/fhe-airdrop/compliance-clone.d.ts +21 -0
- package/dist/fhe-airdrop/constants.d.ts +11 -1
- package/dist/fhe-airdrop/ecdsa.d.ts +79 -26
- package/dist/fhe-airdrop/encryption.d.ts +19 -6
- package/dist/fhe-airdrop/errors.d.ts +136 -2
- package/dist/fhe-airdrop/factory-params.d.ts +2361 -0
- package/dist/fhe-airdrop/factory.d.ts +189 -75
- package/dist/fhe-airdrop/guards.d.ts +183 -19
- package/dist/fhe-airdrop/index.cjs +88 -56
- package/dist/fhe-airdrop/index.d.cts +12 -10
- package/dist/fhe-airdrop/index.d.ts +12 -10
- package/dist/fhe-airdrop/index.js +5 -5
- package/dist/fhe-airdrop/merkle-tree.d.ts +9 -9
- package/dist/fhe-airdrop/merkle.d.ts +32 -11
- package/dist/fhe-airdrop/react/_shared.d.ts +12 -6
- package/dist/fhe-airdrop/react/index.cjs +336 -240
- package/dist/fhe-airdrop/react/index.d.cts +19 -9
- package/dist/fhe-airdrop/react/index.d.ts +19 -9
- package/dist/fhe-airdrop/react/index.js +158 -97
- package/dist/fhe-airdrop/react/keys.d.ts +54 -7
- package/dist/fhe-airdrop/react/useAccessEcdsaClaimAmount.d.ts +6 -3
- package/dist/fhe-airdrop/react/useAccessMerkleClaimAmount.d.ts +2 -2
- package/dist/fhe-airdrop/react/useAirdropConfig.d.ts +8 -3
- package/dist/fhe-airdrop/react/useAirdropPause.d.ts +5 -0
- package/dist/fhe-airdrop/react/useBuildMerkleCampaign.d.ts +4 -6
- package/dist/fhe-airdrop/react/useComplianceManager.d.ts +2 -2
- package/dist/fhe-airdrop/react/useComplianceManagerOf.d.ts +1 -2
- package/dist/fhe-airdrop/react/useCreateAndFundEcdsaAirdrop.d.ts +16 -11
- package/dist/fhe-airdrop/react/useCreateAndFundMerkleAirdrop.d.ts +23 -7
- package/dist/fhe-airdrop/react/useCreateEcdsaAirdrop.d.ts +13 -8
- package/dist/fhe-airdrop/react/useCreateMerkleAirdrop.d.ts +27 -7
- package/dist/fhe-airdrop/react/useDedupMode.d.ts +16 -0
- package/dist/fhe-airdrop/react/useDiscloseHandleToParty.d.ts +4 -3
- package/dist/fhe-airdrop/react/useEcdsaClaim.d.ts +6 -4
- package/dist/fhe-airdrop/react/useEcdsaClaimAndUnwrap.d.ts +15 -8
- package/dist/fhe-airdrop/react/useEcdsaDomain.d.ts +1 -1
- package/dist/fhe-airdrop/react/useEncryptCampaignAmounts.d.ts +5 -7
- package/dist/fhe-airdrop/react/useExtendClaimWindow.d.ts +4 -1
- package/dist/fhe-airdrop/react/useFactoryFees.d.ts +11 -4
- package/dist/fhe-airdrop/react/useFundAirdrop.d.ts +3 -4
- package/dist/fhe-airdrop/react/useGrantInstanceRoles.d.ts +2 -1
- package/dist/fhe-airdrop/react/useIsAirdrop.d.ts +44 -0
- package/dist/fhe-airdrop/react/useIsSignatureValid.d.ts +5 -4
- package/dist/fhe-airdrop/react/useMerkleClaim.d.ts +4 -1
- package/dist/fhe-airdrop/react/useMerkleClaimAndUnwrap.d.ts +14 -3
- package/dist/fhe-airdrop/react/usePlanMerkleCampaign.d.ts +18 -3
- package/dist/fhe-airdrop/react/usePreflightClaim.d.ts +1 -1
- package/dist/fhe-airdrop/react/usePreflightCreateAirdrop.d.ts +34 -13
- package/dist/fhe-airdrop/react/useRefreshComplianceBalance.d.ts +36 -0
- package/dist/fhe-airdrop/react/useRescueERC20.d.ts +3 -3
- package/dist/fhe-airdrop/react/useRescueNativeToken.d.ts +23 -0
- package/dist/fhe-airdrop/react/useResolveGasFee.d.ts +30 -0
- package/dist/fhe-airdrop/react/useRotateMerkleRoot.d.ts +5 -2
- package/dist/fhe-airdrop/react/useSignClaimAuthorization.d.ts +4 -0
- package/dist/fhe-airdrop/react/useTokenOf.d.ts +29 -0
- package/dist/fhe-airdrop/react/useUnwrapRequest.d.ts +25 -0
- package/dist/fhe-airdrop/react/useWithdrawConfidential.d.ts +4 -0
- package/dist/fhe-airdrop/roles.d.ts +82 -7
- package/dist/fhe-airdrop/types.d.ts +122 -14
- package/dist/fhe-disperse/errors.d.ts +3 -3
- package/dist/fhe-disperse/index.cjs +22 -22
- package/dist/fhe-disperse/index.d.cts +2 -1
- package/dist/fhe-disperse/index.d.ts +2 -1
- package/dist/fhe-disperse/index.js +3 -3
- package/dist/fhe-disperse/react/index.cjs +27 -25
- package/dist/fhe-disperse/react/index.d.cts +2 -1
- package/dist/fhe-disperse/react/index.d.ts +2 -1
- package/dist/fhe-disperse/react/index.js +8 -6
- package/dist/fhe-disperse/react/useDisperse.d.ts +6 -2
- package/dist/fhe-disperse/react/useRegister.d.ts +9 -3
- package/dist/fhe-disperse/react/useSingletonWithdrawTokenFee.d.ts +7 -2
- package/dist/fhe-disperse/react/useWithdrawTokenFee.d.ts +7 -2
- package/dist/fhe-disperse/singleton.d.ts +33 -19
- package/dist/fhe-disperse/types.d.ts +48 -8
- package/dist/fhe-vesting/advanced/index.cjs +6 -6
- package/dist/fhe-vesting/advanced/index.js +4 -4
- package/dist/fhe-vesting/advanced/react/index.cjs +9 -9
- package/dist/fhe-vesting/advanced/react/index.js +6 -6
- package/dist/fhe-vesting/factory.d.ts +31 -8
- package/dist/fhe-vesting/index.cjs +23 -23
- package/dist/fhe-vesting/index.d.cts +3 -2
- package/dist/fhe-vesting/index.d.ts +3 -2
- package/dist/fhe-vesting/index.js +4 -4
- package/dist/fhe-vesting/manager.d.ts +27 -2
- package/dist/fhe-vesting/react/index.cjs +126 -126
- package/dist/fhe-vesting/react/index.d.cts +3 -2
- package/dist/fhe-vesting/react/index.d.ts +3 -2
- package/dist/fhe-vesting/react/index.js +5 -5
- package/dist/fhe-vesting/react/useCreateManager.d.ts +16 -9
- package/dist/fhe-vesting/react/useCreateManagerAndGetAddress.d.ts +9 -5
- package/dist/fhe-vesting/react/useSplitVesting.d.ts +9 -3
- package/dist/index.cjs +18 -18
- package/dist/index.js +1 -1
- package/dist/testnet-faucet/faucet.d.ts +3 -0
- package/dist/testnet-faucet/index.cjs +15 -15
- package/dist/testnet-faucet/index.js +3 -3
- package/dist/testnet-faucet/react/index.cjs +9 -9
- package/dist/testnet-faucet/react/index.js +4 -4
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ import type { Address } from "viem";
|
|
|
3
3
|
import type { AirdropVariant } from "../errors.js";
|
|
4
4
|
import { type AirdropInstanceHookOptions } from "./_shared.js";
|
|
5
5
|
/**
|
|
6
|
-
* Create-time-immutable instance configuration - combines
|
|
6
|
+
* Create-time-immutable instance configuration - combines seven `AirdropBaseClient`
|
|
7
7
|
* reads into one.
|
|
8
8
|
*
|
|
9
9
|
* @alpha
|
|
@@ -21,13 +21,18 @@ export interface AirdropConfig {
|
|
|
21
21
|
complianceManager: Address;
|
|
22
22
|
/** Per-claim ETH fee in wei; `0` on a fee-free campaign. */
|
|
23
23
|
gasFee: bigint;
|
|
24
|
+
/** Whether `extendClaimWindow` is permitted; frozen at create. */
|
|
25
|
+
canExtendClaimWindow: boolean;
|
|
26
|
+
/** The block the instance was initialized in (L2 block on Arbitrum). */
|
|
27
|
+
deploymentBlockNumber: bigint;
|
|
24
28
|
}
|
|
25
29
|
/** @alpha */
|
|
26
30
|
export type UseAirdropConfigArgs = AirdropInstanceHookOptions<AirdropConfig>;
|
|
27
31
|
/**
|
|
28
32
|
* Read an airdrop instance's immutable configuration in one round trip.
|
|
29
33
|
*
|
|
30
|
-
* Bundles `token` / `airdropType` / `unwrappable` / `complianceManager` / `gasFee`
|
|
34
|
+
* Bundles `token` / `airdropType` / `unwrappable` / `complianceManager` / `gasFee` /
|
|
35
|
+
* `canExtendClaimWindow` / `deploymentBlockNumber` -
|
|
31
36
|
* what a UI needs before it can render anything else about a campaign, and how
|
|
32
37
|
* `airdropType` and `unwrappable` get covered without shipping two more one-line hooks
|
|
33
38
|
* nobody would call separately. `variant` is derived from the ordinal so a consumer can
|
|
@@ -38,7 +43,7 @@ export type UseAirdropConfigArgs = AirdropInstanceHookOptions<AirdropConfig>;
|
|
|
38
43
|
*
|
|
39
44
|
* The existing {@link useAirdropToken}, {@link useAirdropGasFee} and
|
|
40
45
|
* {@link useComplianceManager} overlap this bundle and stay: they are one `eth_call`
|
|
41
|
-
* rather than
|
|
46
|
+
* rather than seven, which is cheaper for a UI that needs exactly one value.
|
|
42
47
|
*
|
|
43
48
|
* @example
|
|
44
49
|
* const { data: config } = useAirdropConfig({ address: airdropAddress });
|
|
@@ -21,6 +21,11 @@ export interface AirdropPauseArgs extends WriteAccountOverride {
|
|
|
21
21
|
* `window.isActive`, so a mounted `useAirdropWindow` consumer would otherwise
|
|
22
22
|
* keep showing a stale `isActive` after a pause/unpause.
|
|
23
23
|
*
|
|
24
|
+
* Not invalidated: {@link usePreflightClaim} (its `PausedError` blocker) and
|
|
25
|
+
* {@link useIsSignatureValid} (which answers `false` while paused) also move with
|
|
26
|
+
* the flag. Refetch them if the same session renders both the admin toggle and a
|
|
27
|
+
* claim form.
|
|
28
|
+
*
|
|
24
29
|
* @example
|
|
25
30
|
* const setPause = useAirdropPause({ address: airdropAddress });
|
|
26
31
|
* await setPause.mutateAsync({ paused: true });
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type UseMutationResult } from "@tanstack/react-query";
|
|
2
2
|
import type { Address } from "viem";
|
|
3
|
-
import { type CampaignSubmitterOption } from "../campaign.js";
|
|
4
3
|
import { type EncryptorSource } from "../encryption.js";
|
|
5
4
|
import type { BuiltCampaign, CampaignRecipient } from "../types.js";
|
|
6
5
|
/**
|
|
@@ -23,7 +22,7 @@ export interface UseBuildMerkleCampaignOptions {
|
|
|
23
22
|
*
|
|
24
23
|
* @alpha
|
|
25
24
|
*/
|
|
26
|
-
export interface UseBuildMerkleCampaignArgs
|
|
25
|
+
export interface UseBuildMerkleCampaignArgs {
|
|
27
26
|
/** The LIVE `MerkleConfidentialAirdrop` instance every input is bound to. Not the factory, not the implementation. */
|
|
28
27
|
instance: Address;
|
|
29
28
|
/** CUMULATIVE totals per account, never per-drop tranches. */
|
|
@@ -48,10 +47,9 @@ export interface UseBuildMerkleCampaignArgs extends CampaignSubmitterOption {
|
|
|
48
47
|
* A mutation rather than a query: encryption is randomised, so the same roster
|
|
49
48
|
* builds a different root every call and there is no cache identity to key.
|
|
50
49
|
*
|
|
51
|
-
* Each entry is `{ account,
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* `submitter` was set.
|
|
50
|
+
* Each entry is `{ account, handle, inputProof, merkleProof }` - `account`
|
|
51
|
+
* selects the leaf and the cumulative accounting. One relayer request per 32
|
|
52
|
+
* recipients, issued concurrently; every leaf is submittable by any address.
|
|
55
53
|
*
|
|
56
54
|
* **Invalidates:** nothing. Off-chain work only; the root is not published here.
|
|
57
55
|
*
|
|
@@ -5,8 +5,8 @@ import { type AirdropInstanceHookOptions } from "./_shared.js";
|
|
|
5
5
|
export type UseComplianceManagerArgs = AirdropInstanceHookOptions<Address>;
|
|
6
6
|
/**
|
|
7
7
|
* Read an airdrop instance's own compliance-manager clone — the only
|
|
8
|
-
* contract
|
|
9
|
-
*
|
|
8
|
+
* contract the instance itself grants persistent ACL on its pool and claim
|
|
9
|
+
* handles.
|
|
10
10
|
*
|
|
11
11
|
* @example
|
|
12
12
|
* const { data: complianceManager } = useComplianceManager({ address: airdropAddress });
|
|
@@ -15,8 +15,7 @@ export interface UseComplianceManagerOfArgs extends AirdropHookOptions<Address>
|
|
|
15
15
|
* instances it deployed, so a zero address means the instance did not come
|
|
16
16
|
* from this factory - do not mount the compliance hooks on it.
|
|
17
17
|
*
|
|
18
|
-
*
|
|
19
|
-
* the mapping is written once, inside `createX`, and never changes.
|
|
18
|
+
* Caching follows the same write-once policy as {@link useTokenOf}.
|
|
20
19
|
*
|
|
21
20
|
* @remarks
|
|
22
21
|
* {@link useComplianceManager} answers the same question from the other side,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type UseMutationResult } from "@tanstack/react-query";
|
|
2
|
+
import type { ReceiptMode } from "../../core/pending.js";
|
|
2
3
|
import type { WriteAccountOverride } from "../airdrop-base.js";
|
|
3
4
|
import type { FundInput } from "../factory.js";
|
|
4
|
-
import type { CreateAirdropArgs, CreateAirdropResult, EcdsaAirdropParams } from "../types.js";
|
|
5
|
+
import type { CreateAirdropArgs, CreateAirdropResult, EcdsaAirdropParams, PendingCreateAirdropResult } from "../types.js";
|
|
5
6
|
import { type AirdropClientOptions } from "./_shared.js";
|
|
6
7
|
/**
|
|
7
8
|
* Variables for {@link useCreateAndFundEcdsaAirdrop} — the create arguments plus
|
|
@@ -9,7 +10,7 @@ import { type AirdropClientOptions } from "./_shared.js";
|
|
|
9
10
|
*
|
|
10
11
|
* @alpha
|
|
11
12
|
*/
|
|
12
|
-
export type UseCreateAndFundEcdsaAirdropArgs = CreateAirdropArgs<EcdsaAirdropParams> & FundInput & WriteAccountOverride;
|
|
13
|
+
export type UseCreateAndFundEcdsaAirdropArgs = CreateAirdropArgs<EcdsaAirdropParams> & FundInput & WriteAccountOverride & ReceiptMode;
|
|
13
14
|
/**
|
|
14
15
|
* Deploy an ECDSA-authorised airdrop instance and seed its pool in one
|
|
15
16
|
* transaction.
|
|
@@ -20,19 +21,23 @@ export type UseCreateAndFundEcdsaAirdropArgs = CreateAirdropArgs<EcdsaAirdropPar
|
|
|
20
21
|
* (plaintext, encrypted against the hook-level `encryptor`) or a pre-built
|
|
21
22
|
* `encryptedInput`, never both.
|
|
22
23
|
*
|
|
23
|
-
* Returns `CreateAirdropResult` unflattened
|
|
24
|
-
* complianceManager }`; the caller
|
|
25
|
-
* with the campaign afterwards.
|
|
24
|
+
* Returns `CreateAirdropResult` (or `PendingCreateAirdropResult` with `waitForReceipt: false`; both carry every address) unflattened - `{ hash, airdrop,
|
|
25
|
+
* complianceManager, managerImplementation, complianceDelegate }`; the caller
|
|
26
|
+
* needs the instance address to do anything with the campaign afterwards.
|
|
26
27
|
*
|
|
27
28
|
* **A successful receipt does not prove the pool was funded.** An ERC-7984
|
|
28
29
|
* transfer moves an encrypted zero instead of reverting when the funder is
|
|
29
30
|
* short, because reverting would leak the balance.
|
|
30
31
|
*
|
|
31
|
-
* **
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
32
|
+
* **Safe / multisig signers:** pass `waitForReceipt: false`; see
|
|
33
|
+
* {@link ReceiptMode}.
|
|
34
|
+
*
|
|
35
|
+
* **Invalidates:** the factory's registry pages, every cached `isAirdrop` answer, every
|
|
36
|
+
* cached create preflight (the salt is now consumed), and the {@link useTokenOf} /
|
|
37
|
+
* {@link useComplianceManagerOf} entries for the new address, which may hold a zero
|
|
38
|
+
* read before the create.
|
|
39
|
+
* No read hook here caches the confidential pool balance, so the fund leg moves nothing
|
|
40
|
+
* else.
|
|
36
41
|
*
|
|
37
42
|
* **Never log `amount`.** It is the one plaintext confidential value this
|
|
38
43
|
* hook sees — keep it out of telemetry, `onError` context and console.
|
|
@@ -52,4 +57,4 @@ export type UseCreateAndFundEcdsaAirdropArgs = CreateAirdropArgs<EcdsaAirdropPar
|
|
|
52
57
|
*
|
|
53
58
|
* @alpha
|
|
54
59
|
*/
|
|
55
|
-
export declare function useCreateAndFundEcdsaAirdrop(options?: AirdropClientOptions): UseMutationResult<CreateAirdropResult, Error, UseCreateAndFundEcdsaAirdropArgs>;
|
|
60
|
+
export declare function useCreateAndFundEcdsaAirdrop(options?: AirdropClientOptions): UseMutationResult<CreateAirdropResult | PendingCreateAirdropResult, Error, UseCreateAndFundEcdsaAirdropArgs>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type UseMutationResult } from "@tanstack/react-query";
|
|
2
|
+
import type { ReceiptMode } from "../../core/pending.js";
|
|
2
3
|
import type { WriteAccountOverride } from "../airdrop-base.js";
|
|
3
4
|
import type { FundInput } from "../factory.js";
|
|
4
|
-
import type {
|
|
5
|
+
import type { CreateAirdropResult, CreateMerkleAirdropArgs, PendingCreateAirdropResult } from "../types.js";
|
|
5
6
|
import { type AirdropClientOptions } from "./_shared.js";
|
|
6
7
|
/**
|
|
7
8
|
* Variables for {@link useCreateAndFundMerkleAirdrop} — the create arguments plus
|
|
@@ -9,7 +10,7 @@ import { type AirdropClientOptions } from "./_shared.js";
|
|
|
9
10
|
*
|
|
10
11
|
* @alpha
|
|
11
12
|
*/
|
|
12
|
-
export type UseCreateAndFundMerkleAirdropArgs =
|
|
13
|
+
export type UseCreateAndFundMerkleAirdropArgs = CreateMerkleAirdropArgs & FundInput & WriteAccountOverride & ReceiptMode;
|
|
13
14
|
/**
|
|
14
15
|
* Deploy a Merkle-proof airdrop instance and seed its pool in one transaction.
|
|
15
16
|
*
|
|
@@ -20,23 +21,37 @@ export type UseCreateAndFundMerkleAirdropArgs = CreateAirdropArgs<MerkleAirdropP
|
|
|
20
21
|
*
|
|
21
22
|
* `mode: "uups"` is rejected before the wallet is even looked up, so the
|
|
22
23
|
* mutation rejects without prompting for a signature. Returns
|
|
23
|
-
* `CreateAirdropResult` unflattened
|
|
24
|
+
* `CreateAirdropResult` (or `PendingCreateAirdropResult` with `waitForReceipt: false`; both carry every address) unflattened - `{ hash, airdrop, complianceManager,
|
|
25
|
+
* managerImplementation, complianceDelegate }`.
|
|
24
26
|
*
|
|
25
27
|
* **A successful receipt does not prove the pool was funded.** An ERC-7984
|
|
26
28
|
* transfer moves an encrypted zero instead of reverting when the funder is
|
|
27
29
|
* short, because reverting would leak the balance.
|
|
28
30
|
*
|
|
29
|
-
* **
|
|
30
|
-
*
|
|
31
|
-
*
|
|
31
|
+
* **Safe / multisig signers:** pass `waitForReceipt: false`; see
|
|
32
|
+
* {@link ReceiptMode}.
|
|
33
|
+
*
|
|
34
|
+
* **Invalidates:** the factory's registry pages, every cached `isAirdrop` answer, every
|
|
35
|
+
* cached create preflight (the salt is now consumed), and the {@link useTokenOf} /
|
|
36
|
+
* {@link useComplianceManagerOf} entries for the new address, which may hold a zero
|
|
37
|
+
* read before the create.
|
|
32
38
|
*
|
|
33
39
|
* **Never log `amount`.** It is the one plaintext confidential value this
|
|
34
40
|
* hook sees — keep it out of telemetry, `onError` context and console.
|
|
35
41
|
*
|
|
42
|
+
* **Creating from a plan.** Pass the {@link PlannedCampaign} as `plan`, with
|
|
43
|
+
* `merkleRoot: plan.root`. The create then pins `plan.predictedAddress`, refuses a root that
|
|
44
|
+
* differs from the plan's, and refuses to send once the factory's Merkle implementation has
|
|
45
|
+
* moved since the plan ({@link PredictionDriftError}). Both are checked before anything is
|
|
46
|
+
* encrypted. `expected: { airdrop: plan.predictedAddress }` is the lower-level equivalent of
|
|
47
|
+
* the pin alone.
|
|
48
|
+
*
|
|
36
49
|
* @throws {@link MerkleUupsUnsupportedError} when `mode` is `"uups"`.
|
|
37
50
|
* @throws {@link DeploymentAddressUnavailableError} when no factory is deployed for the connected chain.
|
|
38
51
|
* @throws {@link MissingEncryptorError} when `amount` is given and no encryptor resolves.
|
|
39
52
|
* @throws {@link SaltCollisionError} when this `(mode, deployer, userSalt)` tuple already deployed an instance.
|
|
53
|
+
* @throws {@link PredictionDriftError} when `plan` is given and the factory's Merkle implementation moved since it was taken.
|
|
54
|
+
* @throws {@link InvalidArgumentError} when `params.merkleRoot` or `expected.airdrop` disagrees with `plan`.
|
|
40
55
|
*
|
|
41
56
|
* @example
|
|
42
57
|
* const createAndFund = useCreateAndFundMerkleAirdrop({ encryptor: () => sdk.relayer });
|
|
@@ -44,9 +59,10 @@ export type UseCreateAndFundMerkleAirdropArgs = CreateAirdropArgs<MerkleAirdropP
|
|
|
44
59
|
* params: { common, merkleRoot: plan.root, isMerkleRootMutable: false },
|
|
45
60
|
* mode: "clone",
|
|
46
61
|
* userSalt,
|
|
62
|
+
* plan,
|
|
47
63
|
* amount: 1_000_000n,
|
|
48
64
|
* });
|
|
49
65
|
*
|
|
50
66
|
* @alpha
|
|
51
67
|
*/
|
|
52
|
-
export declare function useCreateAndFundMerkleAirdrop(options?: AirdropClientOptions): UseMutationResult<CreateAirdropResult, Error, UseCreateAndFundMerkleAirdropArgs>;
|
|
68
|
+
export declare function useCreateAndFundMerkleAirdrop(options?: AirdropClientOptions): UseMutationResult<CreateAirdropResult | PendingCreateAirdropResult, Error, UseCreateAndFundMerkleAirdropArgs>;
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
import { type UseMutationResult } from "@tanstack/react-query";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ReceiptMode } from "../../core/pending.js";
|
|
3
|
+
import type { CreateAirdropArgs, CreateAirdropResult, EcdsaAirdropParams, PendingCreateAirdropResult } from "../types.js";
|
|
3
4
|
import type { WriteAccountOverride } from "../airdrop-base.js";
|
|
4
5
|
import { type AirdropClientOptions } from "./_shared.js";
|
|
5
6
|
/**
|
|
6
7
|
* Deploy an ECDSA-authorised airdrop instance via the factory.
|
|
7
8
|
*
|
|
8
|
-
* Returns the headless client's `CreateAirdropResult` unchanged
|
|
9
|
-
* airdrop, complianceManager }`
|
|
9
|
+
* Returns the headless client's `CreateAirdropResult` (or `PendingCreateAirdropResult` with `waitForReceipt: false`; both carry every address) unchanged - `{ hash,
|
|
10
|
+
* airdrop, complianceManager, managerImplementation, complianceDelegate }` -
|
|
11
|
+
* never flattened to just a hash: a caller
|
|
10
12
|
* needs the deployed instance address to do anything with the campaign
|
|
11
13
|
* afterwards.
|
|
12
14
|
*
|
|
13
|
-
* **
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* **Safe / multisig signers:** pass `waitForReceipt: false`; see
|
|
16
|
+
* {@link ReceiptMode}.
|
|
17
|
+
*
|
|
18
|
+
* **Invalidates:** the factory's registry pages, every cached `isAirdrop` answer, every
|
|
19
|
+
* cached create preflight (the salt is now consumed), and the {@link useTokenOf} /
|
|
20
|
+
* {@link useComplianceManagerOf} entries for the new address, which may hold a zero
|
|
21
|
+
* read before the create.
|
|
17
22
|
*
|
|
18
23
|
* @example
|
|
19
24
|
* const create = useCreateEcdsaAirdrop();
|
|
@@ -25,4 +30,4 @@ import { type AirdropClientOptions } from "./_shared.js";
|
|
|
25
30
|
*
|
|
26
31
|
* @alpha
|
|
27
32
|
*/
|
|
28
|
-
export declare function useCreateEcdsaAirdrop(options?: AirdropClientOptions): UseMutationResult<CreateAirdropResult, Error, CreateAirdropArgs<EcdsaAirdropParams> & WriteAccountOverride>;
|
|
33
|
+
export declare function useCreateEcdsaAirdrop(options?: AirdropClientOptions): UseMutationResult<CreateAirdropResult | PendingCreateAirdropResult, Error, CreateAirdropArgs<EcdsaAirdropParams> & WriteAccountOverride & ReceiptMode>;
|
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
import { type UseMutationResult } from "@tanstack/react-query";
|
|
2
|
+
import type { ReceiptMode } from "../../core/pending.js";
|
|
2
3
|
import type { WriteAccountOverride } from "../airdrop-base.js";
|
|
3
|
-
import type {
|
|
4
|
+
import type { CreateAirdropResult, CreateMerkleAirdropArgs, PendingCreateAirdropResult } from "../types.js";
|
|
4
5
|
import { type AirdropClientOptions } from "./_shared.js";
|
|
5
6
|
/**
|
|
6
7
|
* Deploy a Merkle-proof airdrop instance via the factory.
|
|
7
8
|
*
|
|
8
|
-
* Returns the headless client's `CreateAirdropResult` unchanged
|
|
9
|
-
* airdrop, complianceManager }`.
|
|
9
|
+
* Returns the headless client's `CreateAirdropResult` (or `PendingCreateAirdropResult` with `waitForReceipt: false`; both carry every address) unchanged - `{ hash,
|
|
10
|
+
* airdrop, complianceManager, managerImplementation, complianceDelegate }`.
|
|
10
11
|
*
|
|
11
|
-
* **
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* **Safe / multisig signers:** pass `waitForReceipt: false`; see
|
|
13
|
+
* {@link ReceiptMode}.
|
|
14
|
+
*
|
|
15
|
+
* **Invalidates:** the factory's registry pages, every cached `isAirdrop` answer, every
|
|
16
|
+
* cached create preflight (the salt is now consumed), and the {@link useTokenOf} /
|
|
17
|
+
* {@link useComplianceManagerOf} entries for the new address, which may hold a zero
|
|
18
|
+
* read before the create.
|
|
19
|
+
*
|
|
20
|
+
* **Creating from a plan.** Pass the {@link PlannedCampaign} as `plan`, with
|
|
21
|
+
* `merkleRoot: plan.root`. The create then pins `plan.predictedAddress`, refuses a root that
|
|
22
|
+
* differs from the plan's, and refuses to send once the factory's Merkle implementation has
|
|
23
|
+
* moved since the plan ({@link PredictionDriftError}). `expected: { airdrop: plan.predictedAddress }`
|
|
24
|
+
* is the lower-level equivalent of the pin alone.
|
|
14
25
|
*
|
|
15
26
|
* @example
|
|
16
27
|
* const create = useCreateMerkleAirdrop();
|
|
@@ -20,6 +31,15 @@ import { type AirdropClientOptions } from "./_shared.js";
|
|
|
20
31
|
* userSalt,
|
|
21
32
|
* });
|
|
22
33
|
*
|
|
34
|
+
* @example
|
|
35
|
+
* // From a plan (immutable root):
|
|
36
|
+
* await create.mutateAsync({
|
|
37
|
+
* params: { ...params, merkleRoot: plan.root, isMerkleRootMutable: false },
|
|
38
|
+
* mode: "clone",
|
|
39
|
+
* userSalt,
|
|
40
|
+
* plan,
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
23
43
|
* @alpha
|
|
24
44
|
*/
|
|
25
|
-
export declare function useCreateMerkleAirdrop(options?: AirdropClientOptions): UseMutationResult<CreateAirdropResult, Error,
|
|
45
|
+
export declare function useCreateMerkleAirdrop(options?: AirdropClientOptions): UseMutationResult<CreateAirdropResult | PendingCreateAirdropResult, Error, CreateMerkleAirdropArgs & WriteAccountOverride & ReceiptMode>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type UseQueryResult } from "@tanstack/react-query";
|
|
2
|
+
import type { DedupMode } from "../constants.js";
|
|
3
|
+
import { type AirdropInstanceHookOptions } from "./_shared.js";
|
|
4
|
+
/** @alpha */
|
|
5
|
+
export type UseDedupModeArgs = AirdropInstanceHookOptions<DedupMode>;
|
|
6
|
+
/**
|
|
7
|
+
* Read an ECDSA airdrop instance's replay-protection policy from the chain.
|
|
8
|
+
*
|
|
9
|
+
* The mode is frozen at creation, so `staleTime: Infinity`.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* const { data: mode } = useDedupMode({ address: airdropAddress });
|
|
13
|
+
*
|
|
14
|
+
* @alpha
|
|
15
|
+
*/
|
|
16
|
+
export declare function useDedupMode(args: UseDedupModeArgs): UseQueryResult<DedupMode, Error>;
|
|
@@ -18,9 +18,10 @@ export interface UseDiscloseHandleToPartyArgs extends WriteAccountOverride {
|
|
|
18
18
|
* returns the transaction hash rather than an `EncryptedViewResult`; there is
|
|
19
19
|
* no ACL event to parse.
|
|
20
20
|
*
|
|
21
|
-
* Two gates apply on-chain: the
|
|
22
|
-
*
|
|
23
|
-
*
|
|
21
|
+
* Two gates apply on-chain: the handle must be persistently user-decryptable by
|
|
22
|
+
* the caller in this instance's context (a transient allowance from a fresh FHE op
|
|
23
|
+
* does not count; `DISCLOSURE_ADMIN_ROLE` bypasses this gate), and the *instance*
|
|
24
|
+
* must be allowed on it, so a handle minted by an unrelated contract cannot be laundered through
|
|
24
25
|
* this campaign. A failure of the first surfaces as `FheHandleNotAllowedError`.
|
|
25
26
|
*
|
|
26
27
|
* **Invalidates:** nothing. ACL is append-only and no read hook in this
|
|
@@ -6,9 +6,11 @@ import { type EcdsaAirdropInstanceClientOptions } from "./_shared.js";
|
|
|
6
6
|
* Claim a signed encrypted allocation on an `ECDSAConfidentialAirdrop`
|
|
7
7
|
* instance.
|
|
8
8
|
*
|
|
9
|
-
* `
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* An empty `inputProof` is accepted only for a zero handle or one the sender and the
|
|
10
|
+
* instance already hold ACL on; see `EcdsaClaimArgs.encryptedInput`.
|
|
11
|
+
*
|
|
12
|
+
* `dedupMode` is deprecated - no call branches on it. Read the
|
|
13
|
+
* instance's actual policy with `useDedupMode`.
|
|
12
14
|
*
|
|
13
15
|
* **Invalidates:** the `fn "isSignatureValid"` PREFIX for this instance. A successful
|
|
14
16
|
* claim consumes the EIP-712 digest, so every cached signature check on this instance
|
|
@@ -16,7 +18,7 @@ import { type EcdsaAirdropInstanceClientOptions } from "./_shared.js";
|
|
|
16
18
|
* that can no longer be claimed. Per-claim dedup state itself remains unqueryable.
|
|
17
19
|
*
|
|
18
20
|
* @example
|
|
19
|
-
* const claim = useEcdsaClaim({ address: airdropAddress
|
|
21
|
+
* const claim = useEcdsaClaim({ address: airdropAddress });
|
|
20
22
|
* await claim.mutateAsync({ encryptedInput, dedupId, deadline, signer, signature });
|
|
21
23
|
*
|
|
22
24
|
* @alpha
|
|
@@ -8,18 +8,25 @@ import { type EcdsaAirdropInstanceClientOptions } from "./_shared.js";
|
|
|
8
8
|
*
|
|
9
9
|
* Reverts {@link FeatureDisabledError} on a non-unwrappable campaign - gate the button
|
|
10
10
|
* on `useAirdropConfig().unwrappable`. Consumes the same replay guards and EIP-712
|
|
11
|
-
* digest as {@link useEcdsaClaim}.
|
|
11
|
+
* digest as {@link useEcdsaClaim}, and the same empty-proof rule.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* **The amount is public from the claim transaction.** With the stock wrapper the unwrapped
|
|
14
|
+
* amount is publicly decryptable at once (the emitted `unwrapRequestId` is its handle);
|
|
15
|
+
* `finalizeUnwrap` only releases the ERC-20. Only a plain claim keeps it confidential.
|
|
15
16
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* `dedupMode` is deprecated - no call branches on it. Read the
|
|
18
|
+
* instance's actual policy with `useDedupMode`.
|
|
19
|
+
*
|
|
20
|
+
* Resolves to the claim's transaction hash; the underlying ERC-20 moves only at the
|
|
21
|
+
* wrapper's later `finalizeUnwrap`. Pass the hash to `useUnwrapRequest` for the
|
|
22
|
+
* `unwrapRequestId` that call takes.
|
|
23
|
+
*
|
|
24
|
+
* **Invalidates:** the `fn "isSignatureValid"` PREFIX for this instance, exactly as
|
|
25
|
+
* {@link useEcdsaClaim} does: the claim consumes the EIP-712 digest, so a cached `true`
|
|
26
|
+
* is now a guaranteed replay. Per-claim dedup state itself remains unqueryable.
|
|
20
27
|
*
|
|
21
28
|
* @example
|
|
22
|
-
* const unwrapClaim = useEcdsaClaimAndUnwrap({ address: airdropAddress
|
|
29
|
+
* const unwrapClaim = useEcdsaClaimAndUnwrap({ address: airdropAddress });
|
|
23
30
|
* await unwrapClaim.mutateAsync({ encryptedInput, dedupId, deadline, signer, signature, to });
|
|
24
31
|
*
|
|
25
32
|
* @alpha
|
|
@@ -33,7 +33,7 @@ export type UseEcdsaDomainArgs = EcdsaAirdropInstanceHookOptions<EcdsaDomain>;
|
|
|
33
33
|
* All three are bytecode/deploy constants, so `staleTime: Infinity`.
|
|
34
34
|
*
|
|
35
35
|
* @example
|
|
36
|
-
* const { data } = useEcdsaDomain({ address: airdropAddress
|
|
36
|
+
* const { data } = useEcdsaDomain({ address: airdropAddress });
|
|
37
37
|
* const built = data?.claimTypehash === CLAIM_TYPEHASH;
|
|
38
38
|
*
|
|
39
39
|
* @alpha
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type UseMutationResult } from "@tanstack/react-query";
|
|
2
2
|
import type { Address } from "viem";
|
|
3
|
-
import { type
|
|
3
|
+
import { type EncryptedCampaignLeaf } from "../campaign.js";
|
|
4
4
|
import { type EncryptorSource } from "../encryption.js";
|
|
5
5
|
import type { CampaignRecipient } from "../types.js";
|
|
6
6
|
/**
|
|
@@ -22,7 +22,7 @@ export interface UseEncryptCampaignAmountsOptions {
|
|
|
22
22
|
*
|
|
23
23
|
* @alpha
|
|
24
24
|
*/
|
|
25
|
-
export interface UseEncryptCampaignAmountsArgs
|
|
25
|
+
export interface UseEncryptCampaignAmountsArgs {
|
|
26
26
|
/** The LIVE `MerkleConfidentialAirdrop` instance every input is bound to. Not the factory, not the implementation. */
|
|
27
27
|
instance: Address;
|
|
28
28
|
/** CUMULATIVE totals per account, never per-drop tranches. */
|
|
@@ -38,11 +38,9 @@ export interface UseEncryptCampaignAmountsArgs extends CampaignSubmitterOption {
|
|
|
38
38
|
* cache identity to key. **Persist what resolves** — nothing here is
|
|
39
39
|
* recoverable or reproducible.
|
|
40
40
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* a single batched request bound to that one address, one shared `inputProof`
|
|
45
|
-
* for the whole roster, and only that address can submit.
|
|
41
|
+
* One relayer request per 32 recipients, issued concurrently; every leaf is
|
|
42
|
+
* submittable by any address. Split the roster yourself if your relayer
|
|
43
|
+
* rate-limits.
|
|
46
44
|
*
|
|
47
45
|
* **Invalidates:** nothing. Pure off-chain relayer work — no contract state
|
|
48
46
|
* moves, so no cached read goes stale.
|
|
@@ -8,7 +8,10 @@ import { type AirdropInstanceClientOptions } from "./_shared.js";
|
|
|
8
8
|
* `canExtendClaimWindow: true`.
|
|
9
9
|
*
|
|
10
10
|
* **Invalidates:** only this instance's `useAirdropWindow` entry — `endTime`
|
|
11
|
-
* is one of the five fields that hook bundles.
|
|
11
|
+
* is one of the five fields that hook bundles. Not invalidated: the window
|
|
12
|
+
* blockers of {@link usePreflightClaim} and a cached `false` from
|
|
13
|
+
* {@link useIsSignatureValid}, both of which a later `endTime` can move; refetch
|
|
14
|
+
* them if the same session renders a claim form.
|
|
12
15
|
*
|
|
13
16
|
* @example
|
|
14
17
|
* const extend = useExtendClaimWindow({ address: airdropAddress });
|
|
@@ -11,14 +11,21 @@ export interface FactoryFees {
|
|
|
11
11
|
feeCollector: Address;
|
|
12
12
|
/** Wei charged per claim on a fee-charging campaign, absent a per-creator custom fee. */
|
|
13
13
|
defaultGasFee: bigint;
|
|
14
|
+
/**
|
|
15
|
+
* The factory's own ceiling, in wei. Bounds both fee setters and the fee
|
|
16
|
+
* resolved at create, so it is the upper bound a `maxAcceptedGasFee` ever
|
|
17
|
+
* has to clear.
|
|
18
|
+
*/
|
|
19
|
+
maxGasFee: bigint;
|
|
14
20
|
}
|
|
15
21
|
/** @alpha */
|
|
16
22
|
export type UseFactoryFeesArgs = AirdropHookOptions<FactoryFees>;
|
|
17
23
|
/**
|
|
18
|
-
* Read the airdrop factory's
|
|
19
|
-
* `defaultGasFee` in one round trip. For a specific
|
|
20
|
-
*
|
|
21
|
-
*
|
|
24
|
+
* Read the airdrop factory's chain-wide fee configuration: `feeCollector`,
|
|
25
|
+
* `defaultGasFee` and `maxGasFee` in one round trip. For the number a specific
|
|
26
|
+
* creator's `maxAcceptedGasFee` is actually checked against, use
|
|
27
|
+
* `factory.resolveGasFee(creator)` from the headless client: it folds in that
|
|
28
|
+
* creator's `getCustomFee` override, which this hook does not read.
|
|
22
29
|
*
|
|
23
30
|
* @example
|
|
24
31
|
* const { data: fees } = useFactoryFees();
|
|
@@ -15,10 +15,9 @@ import { type AirdropClientOptions } from "./_shared.js";
|
|
|
15
15
|
* `MissingEncryptorError` only if neither resolves — no encryptor
|
|
16
16
|
* indirection needs duplicating here.
|
|
17
17
|
*
|
|
18
|
-
* **Invalidates:** nothing. No read hook in this subpath
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* write could leave stale.
|
|
18
|
+
* **Invalidates:** nothing. No read hook in this subpath caches the confidential
|
|
19
|
+
* pool balance (`useAdminGetCurrentBalance` is a mutation, so there is nothing to
|
|
20
|
+
* invalidate).
|
|
22
21
|
*
|
|
23
22
|
* **Never log `amount`.** It is the one plaintext confidential value this
|
|
24
23
|
* hook ever sees — do not pass it to telemetry, `onError` context, or a
|
|
@@ -22,7 +22,8 @@ export interface GrantInstanceRolesArgs {
|
|
|
22
22
|
* (regardless of which role/holder pair), since a role split can touch
|
|
23
23
|
* several roles across several accounts in one call and the SDK does not
|
|
24
24
|
* duplicate the on-chain role-constant lookup client-side to invalidate more
|
|
25
|
-
* narrowly.
|
|
25
|
+
* narrowly. It also invalidates every `useAirdropRoleMembers` entry for this
|
|
26
|
+
* instance. Scoped to this instance only - other campaigns' role caches are
|
|
26
27
|
* untouched.
|
|
27
28
|
*
|
|
28
29
|
* @example
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type UseQueryResult } from "@tanstack/react-query";
|
|
2
|
+
import type { Address } from "viem";
|
|
3
|
+
import { type AirdropHookOptions } from "./_shared.js";
|
|
4
|
+
/** @alpha */
|
|
5
|
+
export interface UseIsAirdropArgs extends AirdropHookOptions<boolean> {
|
|
6
|
+
/** The address to check against the factory's registry. */
|
|
7
|
+
candidate?: Address;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Ask the canonical factory whether it created `candidate` - the genuineness
|
|
11
|
+
* check (audit-10).
|
|
12
|
+
*
|
|
13
|
+
* **Run this before trusting an address a user pasted, a link carried, or an
|
|
14
|
+
* indexer returned.** A look-alike instance with the same ABI, the same events
|
|
15
|
+
* and a pool the attacker controls is cheap to deploy, and nothing readable at
|
|
16
|
+
* the instance tells it apart. A claim against one succeeds and delivers
|
|
17
|
+
* nothing.
|
|
18
|
+
*
|
|
19
|
+
* The factory this asks is the one resolved from `src/core/addresses.ts` for
|
|
20
|
+
* the connected chain, which is what makes the answer worth anything: an
|
|
21
|
+
* instance that names its own factory names a fake one.
|
|
22
|
+
*
|
|
23
|
+
* **Only a `true` is cached.** The registry is append-only, so a `true` can
|
|
24
|
+
* never become `false` and is safe to hold forever. A `false` is not stable:
|
|
25
|
+
* the address can be created later by another tab, another service, or the
|
|
26
|
+
* headless client, none of which reaches this hook's invalidations - so caching
|
|
27
|
+
* it would serve a stale false negative indefinitely and, for a security check,
|
|
28
|
+
* in the direction that blocks a legitimate claim. Negative answers therefore
|
|
29
|
+
* stay fresh and refetch normally. Override either with `query.staleTime`.
|
|
30
|
+
*
|
|
31
|
+
* **The `address` override is the trust root.** Like every factory hook this
|
|
32
|
+
* accepts `address`, and `useMemoAirdropFactoryClient` prefers it over
|
|
33
|
+
* `src/core/addresses.ts`. That is what makes the hook usable on a local chain,
|
|
34
|
+
* but it also means an attacker-supplied factory address would answer `true`
|
|
35
|
+
* for its own look-alike. Pass `address` only from a source you trust at least
|
|
36
|
+
* as much as the registry; when in doubt, omit it.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* const { data: genuine } = useIsAirdrop({ candidate: fromUrl });
|
|
40
|
+
* if (genuine === false) return <Warning address={fromUrl} />;
|
|
41
|
+
*
|
|
42
|
+
* @alpha
|
|
43
|
+
*/
|
|
44
|
+
export declare function useIsAirdrop(args?: UseIsAirdropArgs): UseQueryResult<boolean, Error>;
|
|
@@ -24,20 +24,21 @@ export interface UseIsSignatureValidArgs extends EcdsaAirdropInstanceHookOptions
|
|
|
24
24
|
* past `deadline`, `signer` lacking `SIGNER_ROLE`, an invalid signature, a consumed
|
|
25
25
|
* digest, or an already-deduped claim). `recipient` is load-bearing and part of the
|
|
26
26
|
* cache key: the read is an `eth_call` FROM that address, so passing the wrong one
|
|
27
|
-
* returns `false` for a signature that would otherwise succeed.
|
|
27
|
+
* returns `false` for a signature that would otherwise succeed. A `SIGNER_ROLE` key that
|
|
28
|
+
* has been EIP-7702-delegated makes every voucher read `false`; see
|
|
29
|
+
* `EcdsaAirdropClient.isSignatureValid`.
|
|
28
30
|
*
|
|
29
31
|
* Stays disabled until all six signature fields are defined, so a UI can call it
|
|
30
32
|
* unconditionally while a form fills in.
|
|
31
33
|
*
|
|
32
34
|
* @remarks
|
|
33
35
|
* A successful {@link useEcdsaClaim} / {@link useEcdsaClaimAndUnwrap} flips this to
|
|
34
|
-
* `false` by consuming the digest
|
|
35
|
-
*
|
|
36
|
+
* `false` by consuming the digest; both invalidate it on success. A claim sent outside
|
|
37
|
+
* these hooks (headless client, another tab) does not, so refetch in that case.
|
|
36
38
|
*
|
|
37
39
|
* @example
|
|
38
40
|
* const { data: claimable } = useIsSignatureValid({
|
|
39
41
|
* address: airdropAddress,
|
|
40
|
-
* dedupMode: "perAddress",
|
|
41
42
|
* recipient, encryptedAmountHandle, dedupId, deadline, signer, signature,
|
|
42
43
|
* });
|
|
43
44
|
*
|
|
@@ -13,9 +13,12 @@ import { type AirdropInstanceClientOptions } from "./_shared.js";
|
|
|
13
13
|
* than the relayer's. Other accounts' cached reads, and every other instance's cache,
|
|
14
14
|
* are left untouched.
|
|
15
15
|
*
|
|
16
|
+
* Anyone may submit an entry; see {@link MerkleClaimArgs.entry} for what a third-party
|
|
17
|
+
* submission costs the recipient, and check `useClaimedAmount` first.
|
|
18
|
+
*
|
|
16
19
|
* @example
|
|
17
20
|
* const claim = useMerkleClaim({ address: airdropAddress });
|
|
18
|
-
* await claim.mutateAsync({ entry }); //
|
|
21
|
+
* await claim.mutateAsync({ entry }); // any address may pass the entry unchanged
|
|
19
22
|
*
|
|
20
23
|
* @alpha
|
|
21
24
|
*/
|