@tokenops/sdk 2.0.0-alpha.3 → 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 +53 -0
- package/README.md +71 -35
- package/SUPPORT.md +1 -1
- package/dist/{chunk-NGU4JYIR.js → chunk-2ND7US2I.js} +1 -1
- package/dist/{chunk-U3TBQRT7.js → chunk-3ZSPRHR3.js} +55 -12
- package/dist/{chunk-BXX5TETM.js → chunk-67Q6KSVV.js} +4114 -3267
- package/dist/{chunk-JVNJSDQ4.cjs → chunk-6AYJRUGP.cjs} +7 -50
- package/dist/{chunk-AHU2HMNE.cjs → chunk-6FUHF73F.cjs} +5 -5
- package/dist/{chunk-NWFMBLSQ.js → chunk-7KY4K4PH.js} +1 -1
- package/dist/{chunk-YABHXJNH.cjs → chunk-ARZ5C3FS.cjs} +7 -7
- package/dist/{chunk-4IB4IY5Y.js → chunk-AX6MQAWU.js} +2 -2
- package/dist/{chunk-BPIVVCSQ.js → chunk-BSXEX2SH.js} +3 -3
- package/dist/{chunk-PK6Q6J5F.js → chunk-CHGY6B7L.js} +34 -81
- package/dist/{chunk-GKYZQJGP.cjs → chunk-DFK5GCJP.cjs} +55 -72
- package/dist/{chunk-4AWQJQXY.cjs → chunk-E4IV4M4E.cjs} +4126 -3279
- package/dist/{chunk-6HCT4QIX.js → chunk-GHGF65LN.js} +16 -13
- package/dist/{chunk-TWT3STIX.js → chunk-K3R27WX4.js} +8 -46
- package/dist/{chunk-GCJFAY4X.js → chunk-KJUNBOJQ.js} +52 -71
- package/dist/{chunk-6XOAYDC6.cjs → chunk-PO3A2AQX.cjs} +4 -4
- package/dist/{chunk-TND5NDV7.cjs → chunk-QHDMPT7I.cjs} +64 -19
- package/dist/{chunk-IEKTGJ4J.cjs → chunk-S47IBDTA.cjs} +36 -83
- package/dist/{chunk-UG5RKLU2.cjs → chunk-SUYBAF27.cjs} +1 -1
- package/dist/{chunk-WRWRA4TN.js → chunk-TWU7L5H7.js} +5 -48
- package/dist/{chunk-WJLECC22.cjs → chunk-UUSSWOPR.cjs} +9 -47
- package/dist/{chunk-YTIYTV4K.cjs → chunk-VHKMWWBA.cjs} +319 -40
- package/dist/{chunk-PG3WXT3K.cjs → chunk-YAL6JSAZ.cjs} +16 -13
- package/dist/{chunk-LEYYG4RF.js → chunk-YMWMIWBP.js} +315 -42
- 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 +81 -4
- package/dist/fhe-airdrop/abis/ecdsa.d.ts +101 -4
- package/dist/fhe-airdrop/abis/factory.d.ts +222 -4
- package/dist/fhe-airdrop/abis/merkle.d.ts +100 -4
- 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 +121 -143
- package/dist/fhe-airdrop/advanced/react/index.js +55 -77
- package/dist/fhe-airdrop/advanced/react/useClearCompliancePolicy.d.ts +3 -1
- package/dist/fhe-airdrop/advanced/react/useDisableCustomFee.d.ts +3 -1
- package/dist/fhe-airdrop/advanced/react/useFactoryComplianceDelegate.d.ts +2 -4
- 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 +3 -1
- package/dist/fhe-airdrop/advanced/react/useSetDefaultDelegateToCompliance.d.ts +5 -4
- package/dist/fhe-airdrop/advanced/react/useSetDefaultGasFee.d.ts +3 -1
- package/dist/fhe-airdrop/advanced/react/useSetMaxGasFee.d.ts +7 -3
- package/dist/fhe-airdrop/airdrop-base.d.ts +95 -10
- 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 +3 -1
- package/dist/fhe-airdrop/ecdsa.d.ts +67 -27
- package/dist/fhe-airdrop/encryption.d.ts +19 -6
- package/dist/fhe-airdrop/errors.d.ts +77 -2
- package/dist/fhe-airdrop/factory-params.d.ts +2361 -0
- package/dist/fhe-airdrop/factory.d.ts +142 -68
- package/dist/fhe-airdrop/guards.d.ts +110 -31
- package/dist/fhe-airdrop/index.cjs +79 -59
- package/dist/fhe-airdrop/index.d.cts +11 -9
- package/dist/fhe-airdrop/index.d.ts +11 -9
- 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 +294 -258
- package/dist/fhe-airdrop/react/index.d.cts +16 -9
- package/dist/fhe-airdrop/react/index.d.ts +16 -9
- package/dist/fhe-airdrop/react/index.js +114 -110
- package/dist/fhe-airdrop/react/keys.d.ts +46 -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/useFundAirdrop.d.ts +3 -4
- package/dist/fhe-airdrop/react/useGrantInstanceRoles.d.ts +2 -1
- 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/useRescueERC20.d.ts +3 -3
- package/dist/fhe-airdrop/react/useRescueNativeToken.d.ts +23 -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 +109 -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
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,59 @@ All notable changes to `@tokenops/sdk` will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.0.0-alpha.4] - 2026-10-01
|
|
9
|
+
|
|
10
|
+
> **Pre-release built against external-audit fixes that have not merged yet.** Continues the `2.0.0-alpha` line. `/fhe-airdrop` in this build targets `tokenops-fhe-airdrop-v2` at commit `005980df194e0dc66053bd517e9759bd4d580047` (branch `fix/external-audit-2026-09`), which carries the fixes for the external audit on top of the internal round but is still under review. Every Sepolia `fheAirdrop` address moved again in this build, to a preview deployment from `005980d` with the CREATE3 salt version `sdk-preview-13cad511`, set at deploy time; the contracts branch is unchanged and still names `2.0.2`, which is already consumed on Sepolia, so a redeploy needs its own fresh salt version. The factory is now `0xD5906f366Ff50909F403c8EDfDe680015563046a`. Breaking changes may land between any two alpha builds without a major bump (SemVer prerelease semantics). Published on the `alpha` dist-tag; `latest` stays on `1.6.0`. **For internal testing, not production value.**
|
|
11
|
+
>
|
|
12
|
+
> Migration guide: [`docs/migration/airdrop-v1-to-v2.md`](docs/migration/airdrop-v1-to-v2.md). Support policy: [`SUPPORT.md`](SUPPORT.md).
|
|
13
|
+
|
|
14
|
+
### Changed - BREAKING
|
|
15
|
+
|
|
16
|
+
- **Every Merkle leaf input is bound to `(instance, instance)`, and anyone may submit a claim** (ext-audit-17). The contract now verifies each input against the airdrop itself, so the campaign builders encrypt every roster the same way: batched `MERKLE_BATCH_LIMIT` (32) values per proof, one relayer request per chunk, chunks concurrent. The payout still goes to `entry.account`, only `account` may redirect with `to`, and `claimAndUnwrap` stays self-only. A stranger who submits first settles the leaf confidentially, so a redirect or unwrap the recipient intended no longer happens; integrators check `getClaimedAmount` before offering a claim. ECDSA claims are unchanged.
|
|
17
|
+
- **Removed `submitter`, `CampaignSubmitterOption` and `CampaignEntry.boundTo`**, from `encryptCampaignAmounts`, `buildMerkleCampaign`, `planMerkleCampaign`, `rotateMerkleRoot` and their hooks. Removed rather than deprecated: the contract rejects any other binding, so an ignored option would mislead. Entries built under earlier alphas were bound differently and cannot be claimed against this factory.
|
|
18
|
+
- **`CreateAirdropResult` gained `managerImplementation` and `complianceDelegate`.** All three compliance fields are now read from the create receipt's `ComplianceManagerCloned` log instead of a follow-up registry call.
|
|
19
|
+
- **Indexers: two event topics moved.** `AirdropInitialized` was reshaped (it drops `deploymentBlockNumber`, now a getter, and gains the window, `canExtendClaimWindow`, `unwrappable` and `complianceManager`; the variant-specific fields arrive in the new `ECDSAAirdropInitialized(dedupMode)` and `MerkleAirdropInitialized(merkleRoot, isMerkleRootMutable)`), and the factory's `ComplianceManagerCloned` gained `managerImplementation`. A filter on either old signature matches nothing. The SDK resolves creates from `ConfidentialAirdropCreated` and is unaffected.
|
|
20
|
+
- **Factory compliance is ON from construction** (ext-audit-16). The constructor seeds a non-zero platform delegate with the default ON, so there is no post-deploy wiring step; `setComplianceDelegate` rotates but can never clear it, and `setDefaultDelegateToCompliance(true)` no longer depends on a prior delegate write.
|
|
21
|
+
- **Local fixtures: the factory constructor takes the compliance delegate** as a trailing argument and starts with compliance ON (ext-audit-16). `test/fhe-airdrop/helpers/deploy-v2.ts` passes it; a fixture that deploys the factory itself must do the same.
|
|
22
|
+
- **The React create, register, split and disperse hooks resolve `Mined | Pending`.** `useCreateManager`, `useCreateManagerAndGetAddress`, `useSplitVesting`, `useRegister`, `useDisperse`, `useWithdrawTokenFee`, `useSingletonWithdrawTokenFee` and the four airdrop create hooks accept `waitForReceipt`, and a hook cannot overload on it, so `data` / `mutateAsync` now resolve to the union of the mined result and its `Pending*Result`. Those fields now type as `X | undefined` on `data`, so code that used `data.manager`, `data.newVestingId`, `data.wallets` or `data.distributions` as `Address` / `Hex` / arrays no longer compiles. Headless calls are unaffected: the option is not on the base argument types, so a call or wrapper that never passes it keeps the mined result type. Migration: `if (data.pending) return;` before the read narrows to the mined result.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **Receipt-free writes for Safe / multisig signers.** A threshold Safe's `safeTxHash` never mines until owners co-sign, so every write that waited for its receipt hung. These now take `waitForReceipt?: boolean` (default `true`) and, with `false`, return on submission without polling: `/fhe-vesting` `createManager`, `createManagerAndGetAddress`, `splitVesting`; `/fhe-disperse` `register`, `disperse` (all three modes), `withdrawTokenFee`; `/fhe-airdrop` `createEcdsaAirdrop`, `createMerkleAirdrop`, `createAndFundEcdsaAirdrop`, `createAndFundMerkleAirdrop`. Their hooks pass the option through. The option stays off the exported argument types (`CreateManagerArgs`, `SplitVestingArgs`, `RegisterArgs`, `DisperseArgs`, `WithdrawTokenFeeArgs`, `CreateAirdropArgs`, `CreateMerkleAirdropArgs`): each method takes `Args & ReceiptMode<...>` instead, with the new `ReceiptMode` exported from the root and each product subpath, so a value typed as one of those types still resolves to the mined overload, and a runtime `boolean` is typed `Args & ReceiptMode`. Each method is overloaded on the literal: without `waitForReceipt: false` it returns the mined result exactly as before, every receipt-derived field set; with it, a new `Pending*Result` (`PendingCreateManagerResult`, `PendingSplitVestingResult`, `PendingRegisterResult`, `PendingDisperseResult`, `PendingWithdrawTokenFeeResult`, `PendingCreateAirdropResult`) whose receipt-derived field is `undefined`. Every pending result carries `pending: true` (the shared `PendingWrite` type, exported from the root and each product subpath) and every mined result declares `pending?: never` (`MinedWrite`), so `if (result.pending)` narrows the same way in all three products. A pending airdrop create still carries every address, built from its commitments, because the factory reverts unless it deploys exactly there. Encrypted views and disclosures are deliberately excluded: a Safe cannot user-decrypt in-session. `register` now takes the exported `RegisterArgs`, and `WithdrawTokenFeeArgs` is exported from `/fhe-disperse`. The ERC-7984 operator approval the funding flows need (`setOperator`, `ensureOperator`, `useEnsureOperator`) already took `waitForReceipt`; a Safe passes `false` there too.
|
|
27
|
+
- **`predictComplianceManagerClone`** (`/fhe-airdrop/advanced`), the compliance clone the factory deploys for an instance address.
|
|
28
|
+
- **`encodeInstanceRoleSplit`** with `InstanceRoleCall` and `InstanceRoleConstants`: a `planInstanceRoleSplit` plan as the ordered `grantRole` / `revokeRole` calls a Safe submits as one MultiSend batch. `grantInstanceRoles` stays receipt-bound, since each step must mine before the next simulates.
|
|
29
|
+
- **Create commitments** (ext-audit-09, -12). Every create now commits to the instance address, the compliance-manager implementation and the compliance delegate, and the factory reverts before consuming the salt when any of them drifted. The SDK quotes all three at send time; new `CreateCommitments` type, `CreateAirdropArgs.expected?: Partial<CreateCommitments>` to pin any of them instead, `factory.quoteCreateCommitments(...)`, `factory.resolveComplianceDelegate(creator)`, and a new `PreflightCreateResult` (what `preflightCreate` now returns) whose `commitments` is what the create would be sent with (`usePreflightCreateAirdrop` accepts `expected`). `quoteCreateCommitments` takes the new `AirdropVariantParams`, which ties `variant` to its params type. `preflightCreate` reports a pinned field that differs from the fresh quote as a `CreateCommitmentMismatchError` blocker. A planned Merkle campaign is created from its plan (next entry); `expected: { airdrop: plan.predictedAddress }` remains the lower-level way to pin the address alone.
|
|
30
|
+
- **Create a planned Merkle campaign from its plan.** `createMerkleAirdrop`, `createAndFundMerkleAirdrop`, their hooks, and the Merkle arm of `preflightCreate` / `usePreflightCreateAirdrop` take `plan?: PlannedCampaign` (new `CreateMerkleAirdropArgs`). A plan pins `expected.airdrop` to `plan.predictedAddress`, so the instance can no longer land at a fresh prediction its leaves are not bound to after an implementation rotation. The write path refuses before any RPC when `params.merkleRoot` differs from `plan.root` or a caller-supplied `expected.airdrop` differs from `plan.predictedAddress` (`InvalidArgumentError`), and refuses before the send when the factory's live Merkle init-code hash no longer equals `plan.initCodeHashAfter` (`PredictionDriftError`). `preflightCreate` reports the same conditions as blockers, plus an `expectedInitCodeHash` that disagrees with the plan. The ECDSA creates do not take `plan`.
|
|
31
|
+
- **`CreateCommitmentMismatchError`** (`TOKENOPS_CREATE_COMMITMENT_MISMATCH`), mapping `PredictionMismatch`, `ManagerImplementationMismatch` and `ComplianceDelegateMismatch`, with `context.field` (`"airdrop" | "complianceManagerImpl" | "complianceDelegate"`), `expected` and `actual`.
|
|
32
|
+
- **`EcdsaAirdropClient.readDedupMode()`** and **`useDedupMode`** (ext-audit-06). `EcdsaAirdropClientConfig.dedupMode` and the hook options that required it are now optional (see Deprecated).
|
|
33
|
+
- **`TOKENOPS_UNEXPECTED_CONTRACT_RESPONSE`** joins `TokenOpsSdkErrorCode`: a read that succeeded but returned a value this SDK cannot interpret. `readDedupMode()` throws it, with `context.{contractAddress, ordinal}`, for a `DedupMode` ordinal it does not know. Potentially breaking for an exhaustive `switch (err.code)` with a `never` check, which needs a case for it.
|
|
34
|
+
- **`canExtendClaimWindow()`** and **`deploymentBlockNumber()`** on every instance, both also returned by `useAirdropConfig`; **`factory.tokenOf(airdrop)`** and **`useTokenOf`**, the token `fundAirdrop` pulls (ext-audit-03, -06).
|
|
35
|
+
- **`rescueNativeToken({ recipient })`** and **`useRescueNativeToken`** (`RESCUER_ROLE`), sweeping ETH from a zero-fee campaign (ext-audit-07).
|
|
36
|
+
- **`ClawbackRequiresPauseError`** (`TOKENOPS_CLAWBACK_REQUIRES_PAUSE`): `withdrawConfidential` is refused while the campaign is unpaused inside its claim window (ext-audit-11). **`NativeRescueRequiresZeroFeeError`** (`TOKENOPS_NATIVE_RESCUE_REQUIRES_ZERO_FEE`) for a rescue on a fee-charging campaign.
|
|
37
|
+
- `InvalidImplementation` and `UninitializedHandle` map to `InvalidArgumentError`. `InitializationMismatch` and `UninitializedDelivery` are deliberately left to `ContractRevertError`: a platform or token fault, not a state a caller can act on.
|
|
38
|
+
- **`parseUnwrapRequest(receipt | logs)`**, **`readUnwrapRequest(hash)`** (on every instance client) and **`useUnwrapRequest`**, with the new `UnwrapRequest` and `UnwrapRequestSource` types. They decode the instance's `ClaimedAndUnwrapInitiated` event into `{ claimant, beneficiary, claimKey, unwrapRequestId }`, so the `finalizeUnwrap` that releases the underlying ERC-20 can be sent without decoding logs by hand (with Zama's SDK, `sdk.createToken(wrapper).finalizeUnwrap(unwrapRequestId)`). `claimAndUnwrap` itself still returns a bare hash. Only this instance's event counts; two in one transaction throw `ReceiptEventAmbiguousError`.
|
|
39
|
+
- **`MERKLE_BATCH_LIMIT`** is exported.
|
|
40
|
+
- **`/fhe-airdrop/react` now exports `GasFeeNotAcceptedError`, `UnrecognisedAirdropError`, `UINT96_MAX` and `UseDedupModeArgs`**, matching the headless barrel. The hooks could already raise both errors, and `UINT96_MAX` is the accept-any value for `common.maxAcceptedGasFee`.
|
|
41
|
+
|
|
42
|
+
### Deprecated
|
|
43
|
+
|
|
44
|
+
- **`EcdsaAirdropClientConfig.dedupMode`, `EcdsaAirdropClient.dedupMode` and the `dedupMode` option of the ECDSA hooks.** No method branches on them; read the policy from the chain with `readDedupMode()` / `useDedupMode`. They will be removed before `2.0.0`.
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
|
|
48
|
+
- **`preflightCreate` blocks a resolved fee above the factory's `maxGasFee` ceiling.** Lowering the ceiling never rewrites a configured fee, so a create could revert `GasFeeExceedsMaximum` while the preflight reported `ready: true`. The blocker is the same `InvalidArgumentError` (on `gasFee`) that the revert maps to, so a UI sees one code on both paths.
|
|
49
|
+
- **`preflightCreate` blocks params the instance initializer would revert on.** A zero `common.token` (`ZeroToken`), an `endTime` less than 60 seconds ahead of the local clock (`EndTimeInPast`), a `startTime` after `endTime` (`InvalidStartTime`) or equal to it (`InvalidDuration`), a zero `merkleRoot` on an immutable-root campaign (`ZeroMerkleRoot`) and a zero ECDSA `signer` (`ZeroSigner`) are each an `InvalidArgumentError` blocker naming the field. These revert after the factory's own checks, so `ready` was `true` for a create that could never land. The write path still surfaces them through its simulate.
|
|
50
|
+
- **A create whose resolved fee exceeds both the factory's `maxGasFee` ceiling and the creator's `maxAcceptedGasFee` now reports the ceiling.** The factory checks the ceiling first (`GasFeeExceedsMaximum`), but the write path only compared against the creator's bound and threw `GasFeeNotAcceptedError`, so a creator who raised their bound then hit the ceiling. The four `create*` methods now read `maxGasFee()` alongside the resolved fee and throw the ceiling's `InvalidArgumentError` (on `gasFee`) first, matching `preflightCreate`.
|
|
51
|
+
- `setEcdsaImplementation`, `setMerkleImplementation` and `setComplianceManagerImpl` document the `InvalidImplementation` revert (a codeless address or an EIP-7702 designator), not only the zero-address one.
|
|
52
|
+
- **The docs said `dedupMode` could not be read from the chain.** The contract now exposes it, and `docs/fhe-airdrop/README.md`, the root README and the migration guide describe the getter and the init event instead of telling consumers to record the value themselves.
|
|
53
|
+
- The docs now state that `claimAndUnwrap` publishes the unwrapped amount from the claim transaction on, not at `finalizeUnwrap` (ext-audit-13).
|
|
54
|
+
- **`preflightDisperse` checks the sender's singleton approval in every mode.** `DisperseConfidential` pulls from `msg.sender` in the wallet, direct and wallet-token-fee entrypoints and in the token-fee pull, but the preflight only read `isOperator(sender, singleton)` in direct mode, so a wallet-mode sender who had approved only the subwallets got `ready: true` and then an `ERC7984UnauthorizedSpender` revert. It now reads the approval for every mode and reports `SingletonNotApprovedError` whenever it is missing; the subwallet blocker stays for the wallet modes. `PreflightReport.hasApprovedSingleton` narrows from `boolean | null` to `boolean`: code that tested it for truthiness is unaffected, while a check for `=== null` (the old wallet-mode value) no longer matches.
|
|
55
|
+
- Airdrop revert decoding keeps the arguments the ABI carries: `InvalidMerkleProof` puts `{ leaf, merkleRoot }` and `InvalidImplementation` the rejected address in `context.value`, and `EndTimeInPast` / `InvalidDuration` now map in the airdrop mapper with both timestamps in the message and `context.value`, instead of the default mapper's argument-free bucket.
|
|
56
|
+
- **`ClaimNotStartedError` and `ClaimWindowClosedError` now carry their times from a real revert.** The contract's `uint32` start / end time decodes as a `number` in viem, which the mapper dropped, so `startTime` / `endTime` (and the "Opens at" / "Closed at" message detail) were `undefined` on chain-decoded errors; `currentTime` was likewise lost. Both are now read whether viem returns a `number` or a `bigint`.
|
|
57
|
+
- **Docs: ECDSA empty proofs, the signer key and `claimAndUnwrap` disclosure.** The ECDSA claim TSDoc and guide no longer say every input is bound to `(instance, claimant)`: only a non-empty proof is, while an empty proof accepts a zero handle or one the claimant and instance already hold ACL on, and campaigns that may reissue vouchers should use `perDedupId` or `both`. `SIGNER_ROLE` is documented as a key that must never be EIP-7702-delegated, with `isSignatureValid` as the pre-check. `claimAndUnwrap` and its hooks now state that the amount is public from the claim transaction, not at `finalizeUnwrap`.
|
|
58
|
+
- **Create preflights no longer go stale after a write that moves them.** The nine factory-admin hooks that move a create's commitments or fee checks (`useSetComplianceDelegate`, `useSetDefaultDelegateToCompliance`, `useSetCompliancePolicy`, `useClearCompliancePolicy`, `useSetComplianceManagerImpl`, `useSetDefaultGasFee`, `useSetCustomFee`, `useDisableCustomFee`, `useSetMaxGasFee`) and the four create hooks now invalidate every cached `usePreflightCreateAirdrop` report on the factory. A create also consumes its salt, so a cached `ready: true` for it is now invalidated too.
|
|
59
|
+
- **`useComplianceManagerOf` no longer caches a zero answer forever** (the new `useTokenOf` follows the same policy). A non-zero mapping is still held indefinitely, but a zero (not created yet, or not from this factory) stays stale, the same policy as `useIsAirdrop`. The four create hooks also invalidate both entries for the address they deploy, so a zero read of a predicted address updates as soon as the create lands.
|
|
60
|
+
|
|
8
61
|
## [2.0.0-alpha.3] - 2026-09-16
|
|
9
62
|
|
|
10
63
|
> **Pre-release built against internally-audited, externally-unaudited contracts.** Continues the `2.0.0-alpha` line. `/fhe-airdrop` in this build targets `tokenops-fhe-airdrop-v2` at commit `c5c12c2087f61bcd5bd1daa802563ed3cd68f002`, which closes the internal audit round (audit-03 through audit-16) but has not completed an external security audit. Every Sepolia `fheAirdrop` address moved again in this build. Breaking changes may land between any two alpha builds without a major bump (SemVer prerelease semantics). Published on the `alpha` dist-tag; `latest` stays on `1.6.0`. **For internal testing, not production value.**
|
package/README.md
CHANGED
|
@@ -21,24 +21,24 @@ Node `>= 22` is required (constraint from `@zama-fhe/sdk`).
|
|
|
21
21
|
|
|
22
22
|
All subpaths are independently tree-shakeable. The `/react` paths keep React deps out of the server bundle.
|
|
23
23
|
|
|
24
|
-
| Subpath | Status
|
|
25
|
-
| ------------------------------------------ |
|
|
26
|
-
| `@tokenops/sdk` | stable
|
|
27
|
-
| `@tokenops/sdk/telemetry` | stable
|
|
28
|
-
| `@tokenops/sdk/fhe` | stable
|
|
29
|
-
| `@tokenops/sdk/fhe/react` | stable
|
|
30
|
-
| `@tokenops/sdk/fhe-vesting` | factory live on Sepolia
|
|
31
|
-
| `@tokenops/sdk/fhe-vesting/react` | stable
|
|
32
|
-
| `@tokenops/sdk/fhe-vesting/advanced` | stable
|
|
33
|
-
| `@tokenops/sdk/fhe-vesting/advanced/react` | stable
|
|
34
|
-
| `@tokenops/sdk/fhe-airdrop` | **v2,
|
|
35
|
-
| `@tokenops/sdk/fhe-airdrop/react` | **v2,
|
|
36
|
-
| `@tokenops/sdk/fhe-airdrop/advanced` | **v2,
|
|
37
|
-
| `@tokenops/sdk/fhe-airdrop/advanced/react` | **v2,
|
|
38
|
-
| `@tokenops/sdk/fhe-disperse` | singleton live on mainnet + Sepolia
|
|
39
|
-
| `@tokenops/sdk/fhe-disperse/react` | stable
|
|
40
|
-
| `@tokenops/sdk/testnet-faucet` | token pair live on Sepolia
|
|
41
|
-
| `@tokenops/sdk/testnet-faucet/react` | stable
|
|
24
|
+
| Subpath | Status | Description |
|
|
25
|
+
| ------------------------------------------ | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
26
|
+
| `@tokenops/sdk` | stable | Root re-exports (version, core error types) |
|
|
27
|
+
| `@tokenops/sdk/telemetry` | stable | Telemetry sink adapters (`NoopTelemetry`, `ConsoleTelemetry`, `TokenOpsTelemetry`) |
|
|
28
|
+
| `@tokenops/sdk/fhe` | stable | FHE utility helpers (ratio scaling, encrypted-input types, operator helpers) |
|
|
29
|
+
| `@tokenops/sdk/fhe/react` | stable | React hooks for shared FHE utilities |
|
|
30
|
+
| `@tokenops/sdk/fhe-vesting` | factory live on Sepolia | Confidential vesting (LibClone + packed immutable args) |
|
|
31
|
+
| `@tokenops/sdk/fhe-vesting/react` | stable | React/wagmi hooks for confidential vesting |
|
|
32
|
+
| `@tokenops/sdk/fhe-vesting/advanced` | stable | Pre-mine address prediction (`predictManagerAddress`) |
|
|
33
|
+
| `@tokenops/sdk/fhe-vesting/advanced/react` | stable | React hooks for advanced vesting flows |
|
|
34
|
+
| `@tokenops/sdk/fhe-airdrop` | **v2, external-audit fixes unmerged** — `alpha` dist-tag, factory live on Sepolia | ECDSA + Merkle confidential airdrop campaigns — see [Compatibility](#compatibility) |
|
|
35
|
+
| `@tokenops/sdk/fhe-airdrop/react` | **v2, external-audit fixes unmerged** | React/wagmi hooks for recipients, campaign creators, campaign owners and the compliance manager |
|
|
36
|
+
| `@tokenops/sdk/fhe-airdrop/advanced` | **v2, external-audit fixes unmerged** | Prediction-freshness / salt-availability guards and `predictComplianceManagerClone` (instance-address prediction itself is on the headline `ConfidentialAirdropFactoryClient`) |
|
|
37
|
+
| `@tokenops/sdk/fhe-airdrop/advanced/react` | **v2, external-audit fixes unmerged** | Address-prediction hooks plus the factory-admin tier (fee setters, implementation pointers, policy setters) |
|
|
38
|
+
| `@tokenops/sdk/fhe-disperse` | singleton live on mainnet + Sepolia | DisperseConfidential (singleton + per-user wallet-pair clones) |
|
|
39
|
+
| `@tokenops/sdk/fhe-disperse/react` | stable | React/wagmi hooks for confidential disperse |
|
|
40
|
+
| `@tokenops/sdk/testnet-faucet` | token pair live on Sepolia | Testnet faucet for the TokenOps test-token pair — TTT (plain ERC-20) + CTTT (ERC-7984 wrapper); open mint |
|
|
41
|
+
| `@tokenops/sdk/testnet-faucet/react` | stable | React/wagmi hooks for the testnet faucet |
|
|
42
42
|
|
|
43
43
|
The canonical exports map is in [`package.json`](https://github.com/VestingLabs/tokenops-sdk/blob/main/package.json) under `"exports"`.
|
|
44
44
|
|
|
@@ -46,11 +46,13 @@ The canonical exports map is in [`package.json`](https://github.com/VestingLabs/
|
|
|
46
46
|
|
|
47
47
|
Which contract generation a given SDK version talks to, and where that generation is deployed:
|
|
48
48
|
|
|
49
|
-
| SDK
|
|
50
|
-
|
|
|
51
|
-
| `2.0.0-alpha.
|
|
52
|
-
| `2.0.0-alpha.
|
|
53
|
-
| `
|
|
49
|
+
| SDK | Airdrop contracts | Contract commit | Chains |
|
|
50
|
+
| --------------- | --------------------------------------------- | --------------- | ------- |
|
|
51
|
+
| `2.0.0-alpha.4` | v2 (external audit fixes, preview deployment) | `005980d` | Sepolia |
|
|
52
|
+
| `2.0.0-alpha.3` | v2 (internal audit only) | `c5c12c2` | Sepolia |
|
|
53
|
+
| `2.0.0-alpha.2` | v2 (unaudited) | `7175ac8` | Sepolia |
|
|
54
|
+
| `2.0.0-alpha.1` | v2 (unaudited) | `8e5b144` | Sepolia |
|
|
55
|
+
| `1.x` | v1 | n/a | Sepolia |
|
|
54
56
|
|
|
55
57
|
Alpha builds are pinned to a contract generation, and every generation so far has moved every
|
|
56
58
|
deployed address. An instance created through one generation's factory is unreachable from a
|
|
@@ -271,9 +273,10 @@ function DeployManager({
|
|
|
271
273
|
"0x0000000000000000000000000000000000000000000000000000000000000001" as `0x${string}`,
|
|
272
274
|
},
|
|
273
275
|
{
|
|
274
|
-
onSuccess: (
|
|
276
|
+
onSuccess: (result) => {
|
|
275
277
|
queryClient.invalidateQueries({ queryKey: ["tokenops-sdk", "fhe-vesting"] });
|
|
276
|
-
|
|
278
|
+
// A hook resolves `Mined | Pending`; only a pending result lacks `manager`.
|
|
279
|
+
if (!result.pending) onDeployed(result.manager);
|
|
277
280
|
},
|
|
278
281
|
},
|
|
279
282
|
)
|
|
@@ -290,7 +293,7 @@ See [Confidential Vesting — React hooks on docs.tokenops.xyz](https://docs.tok
|
|
|
290
293
|
|
|
291
294
|
## Quickstart — confidential airdrop
|
|
292
295
|
|
|
293
|
-
> **v2,
|
|
296
|
+
> **v2, external-audit fixes not yet merged.** `/fhe-airdrop` targets `tokenops-fhe-airdrop-v2` (`005980d`, a preview deployment on Sepolia only, `alpha` dist-tag) - see [Compatibility](#compatibility). Migrating from `1.x`? See [`docs/migration/airdrop-v1-to-v2.md`](docs/migration/airdrop-v1-to-v2.md).
|
|
294
297
|
|
|
295
298
|
Two claim-authorisation variants share one factory: **ECDSA** (an off-chain signature from a `SIGNER_ROLE` holder) and **Merkle** (inclusion in a published tree). The example below is ECDSA — see [`docs/fhe-airdrop/README.md`](docs/fhe-airdrop/README.md#quickstart--merkle-campaign) for the Merkle flow.
|
|
296
299
|
|
|
@@ -324,9 +327,8 @@ const now = Math.floor(Date.now() / 1000);
|
|
|
324
327
|
const userSalt = "0x0000000000000000000000000000000000000000000000000000000000000001" as const;
|
|
325
328
|
const token = process.env.TOKEN as `0x${string}`;
|
|
326
329
|
|
|
327
|
-
// Create. There is no `admin` field
|
|
328
|
-
// `dedupMode` is
|
|
329
|
-
// it yourself alongside the deployed address.
|
|
330
|
+
// Create. There is no `admin` field - the factory injects `admin = msg.sender`.
|
|
331
|
+
// `dedupMode` is frozen here; read it back later with `readDedupMode()`.
|
|
330
332
|
const { airdrop: airdropAddress } = await factory.createEcdsaAirdrop({
|
|
331
333
|
params: {
|
|
332
334
|
common: {
|
|
@@ -336,6 +338,7 @@ const { airdrop: airdropAddress } = await factory.createEcdsaAirdrop({
|
|
|
336
338
|
canExtendClaimWindow: false,
|
|
337
339
|
unwrappable: false,
|
|
338
340
|
complianceAdmin: zeroAddress, // zero => msg.sender
|
|
341
|
+
maxAcceptedGasFee: 2_000_000_000_000_000n, // 0.002 ETH; a higher resolved fee reverts
|
|
339
342
|
},
|
|
340
343
|
signer: account.address, // SIGNER_ROLE holder authorising claims
|
|
341
344
|
dedupMode: "perAddress",
|
|
@@ -384,12 +387,11 @@ const airdrop = createEcdsaAirdropClient({
|
|
|
384
387
|
publicClient,
|
|
385
388
|
walletClient,
|
|
386
389
|
address: airdropAddress,
|
|
387
|
-
dedupMode: "perAddress", // must match what was passed at create — no getter exists
|
|
388
390
|
});
|
|
389
391
|
await airdrop.claim({ encryptedInput, dedupId, deadline, signer: account.address, signature });
|
|
390
392
|
```
|
|
391
393
|
|
|
392
|
-
See [`docs/fhe-airdrop/README.md`](docs/fhe-airdrop/README.md) for the full API reference, the Merkle campaign flow, guardrails, and the
|
|
394
|
+
See [`docs/fhe-airdrop/README.md`](docs/fhe-airdrop/README.md) for the full API reference, the Merkle campaign flow, guardrails, and the external-audit status warning.
|
|
393
395
|
|
|
394
396
|
### Quickstart — confidential airdrop (React hooks)
|
|
395
397
|
|
|
@@ -451,9 +453,10 @@ function AdminPanel({
|
|
|
451
453
|
canExtendClaimWindow: false,
|
|
452
454
|
unwrappable: false,
|
|
453
455
|
complianceAdmin: "0x0000000000000000000000000000000000000000",
|
|
456
|
+
maxAcceptedGasFee: 2_000_000_000_000_000n, // 0.002 ETH
|
|
454
457
|
},
|
|
455
458
|
signer: "0xYourSignerAddress" as `0x${string}`,
|
|
456
|
-
dedupMode: "perAddress", //
|
|
459
|
+
dedupMode: "perAddress", // frozen at create; `useDedupMode` reads it back
|
|
457
460
|
},
|
|
458
461
|
mode: "clone",
|
|
459
462
|
userSalt:
|
|
@@ -518,9 +521,7 @@ function RecipientClaim({
|
|
|
518
521
|
signature: `0x${string}`;
|
|
519
522
|
};
|
|
520
523
|
}) {
|
|
521
|
-
|
|
522
|
-
// has no on-chain getter, so a consumer must already know it.
|
|
523
|
-
const claim = useEcdsaClaim({ address: airdropAddress, dedupMode: "perAddress" });
|
|
524
|
+
const claim = useEcdsaClaim({ address: airdropAddress });
|
|
524
525
|
|
|
525
526
|
return (
|
|
526
527
|
<button onClick={() => claim.mutate(claimPayload)} disabled={claim.isPending}>
|
|
@@ -780,6 +781,41 @@ function FaucetPanel() {
|
|
|
780
781
|
|
|
781
782
|
See [Testnet Faucet — React hooks on docs.tokenops.xyz](https://docs.tokenops.xyz/sdk/testnet-faucet#react-hooks) for the full hook catalogue (reads, mints, metadata), address overrides, and query-key reference.
|
|
782
783
|
|
|
784
|
+
## Safe and multisig signers
|
|
785
|
+
|
|
786
|
+
A threshold Safe's submission returns a `safeTxHash` that does not mine until the other owners
|
|
787
|
+
co-sign, so a write that waits for its receipt would hang. These writes take
|
|
788
|
+
`waitForReceipt: false` (default `true`) and return as soon as the submission hash is known; their
|
|
789
|
+
React hooks pass the option through.
|
|
790
|
+
|
|
791
|
+
The ERC-7984 operator approval every funding flow needs first is the same: `setOperator`,
|
|
792
|
+
`ensureOperator` and `useEnsureOperator` (`@tokenops/sdk/fhe`) wait for their receipt by default,
|
|
793
|
+
so a Safe passes `waitForReceipt: false` there too and lets the approval execute before the
|
|
794
|
+
funding transaction does. That covers vesting funding, every `disperse` mode and the airdrop
|
|
795
|
+
`createAndFund*` / `fundAirdrop` paths.
|
|
796
|
+
|
|
797
|
+
Each method is overloaded on the literal. Called without `waitForReceipt: false`, it returns the
|
|
798
|
+
mined result with every field set. Called with it, it returns a `Pending*Result` carrying
|
|
799
|
+
`pending: true` (the shared `PendingWrite` shape). The option is not part of the exported `*Args`
|
|
800
|
+
types, so a wrapper typed with one of them still gets the mined result; a runtime `boolean` goes
|
|
801
|
+
through the exported `ReceiptMode` (`args: CreateManagerArgs & ReceiptMode`) and gets the union of
|
|
802
|
+
the two. A hook cannot overload, so its `data` is that union too, and `if (data.pending)` narrows
|
|
803
|
+
it the same way in every product:
|
|
804
|
+
|
|
805
|
+
| Product | Method | Pending result's receipt-derived field |
|
|
806
|
+
| --------------- | ------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------- |
|
|
807
|
+
| `/fhe-vesting` | `createManager`, `createManagerAndGetAddress` | `manager: undefined` - read the executed tx's `ManagerCreated` log |
|
|
808
|
+
| `/fhe-vesting` | `splitVesting` | `newVestingId: undefined` - read the `VestingSplit` log |
|
|
809
|
+
| `/fhe-disperse` | `register` | `wallets: undefined` - read the `UserRegistered` log |
|
|
810
|
+
| `/fhe-disperse` | `disperse` | `distributions: undefined` - read the `WalletDistribution` / `DirectDistribution` logs |
|
|
811
|
+
| `/fhe-disperse` | `withdrawTokenFee` | `transferredHandle: undefined` - read the `TokenFeeWithdrawn` log |
|
|
812
|
+
| `/fhe-airdrop` | `createEcdsaAirdrop`, `createMerkleAirdrop`, `createAndFundEcdsaAirdrop`, `createAndFundMerkleAirdrop` | none: every address is the committed one |
|
|
813
|
+
|
|
814
|
+
Airdrop role splits go through `planInstanceRoleSplit` plus `encodeInstanceRoleSplit` as one
|
|
815
|
+
MultiSend batch; see [Safe and multisig signers](docs/fhe-airdrop/README.md#safe-and-multisig-signers).
|
|
816
|
+
Encrypted views and disclosures have no receipt-free option: their handle is only useful to an
|
|
817
|
+
account that can user-decrypt in-session, so run them from an EOA or a delegate.
|
|
818
|
+
|
|
783
819
|
## Peer dependencies
|
|
784
820
|
|
|
785
821
|
| Package | Range | Required for |
|
package/SUPPORT.md
CHANGED
|
@@ -42,6 +42,6 @@ that cannot be scoped to one subpath.
|
|
|
42
42
|
## Getting help
|
|
43
43
|
|
|
44
44
|
- Migrating off v1 `/fhe-airdrop`: [`docs/migration/airdrop-v1-to-v2.md`](docs/migration/airdrop-v1-to-v2.md).
|
|
45
|
-
- Module docs (v2,
|
|
45
|
+
- Module docs (v2, external-audit fixes unmerged): [`docs/fhe-airdrop/README.md`](docs/fhe-airdrop/README.md).
|
|
46
46
|
- Security issues: see [`SECURITY.md`](SECURITY.md).
|
|
47
47
|
- Everything else: open an issue against `VestingLabs/tokenops-sdk`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfidentialVestingFactoryClient, confidentialVestingFactoryAbi } from './chunk-
|
|
1
|
+
import { ConfidentialVestingFactoryClient, confidentialVestingFactoryAbi } from './chunk-TWU7L5H7.js';
|
|
2
2
|
|
|
3
3
|
// src/fhe-vesting/advanced/factory-advanced.ts
|
|
4
4
|
var ConfidentialVestingFactoryAdvancedClient = class extends ConfidentialVestingFactoryClient {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { createConfidentialAirdropFactoryClient, resolveEncryptor, createAirdropBaseClient, createMerkleAirdropClient, createComplianceManagerClient, createEcdsaAirdropClient } from './chunk-
|
|
2
|
-
import { getFheAirdropFactoryAddress } from './chunk-
|
|
1
|
+
import { createConfidentialAirdropFactoryClient, resolveEncryptor, createAirdropBaseClient, createMerkleAirdropClient, createComplianceManagerClient, createEcdsaAirdropClient } from './chunk-67Q6KSVV.js';
|
|
2
|
+
import { getFheAirdropFactoryAddress } from './chunk-GHGF65LN.js';
|
|
3
3
|
import { DeploymentAddressUnavailableError } from './chunk-QBJ7O2B4.js';
|
|
4
4
|
import { useRef, useMemo } from 'react';
|
|
5
|
+
import { isAddressEqual, zeroAddress } from 'viem';
|
|
5
6
|
import { usePublicClient, useWalletClient } from 'wagmi';
|
|
6
7
|
|
|
7
8
|
var FHE_AIRDROP_KEY = "tokenops-sdk";
|
|
@@ -37,6 +38,10 @@ function normalizeKeyArg(value) {
|
|
|
37
38
|
if (typeof value === "string" && value.startsWith("0x")) return value.toLowerCase();
|
|
38
39
|
return value;
|
|
39
40
|
}
|
|
41
|
+
function staleUntilNonZeroAddress(query) {
|
|
42
|
+
const data = query.state.data;
|
|
43
|
+
return data !== void 0 && !isAddressEqual(data, zeroAddress) ? Infinity : 0;
|
|
44
|
+
}
|
|
40
45
|
function tryResolveAirdropFactoryAddress(override, chainId) {
|
|
41
46
|
if (override) return override;
|
|
42
47
|
if (chainId === void 0) return void 0;
|
|
@@ -161,7 +166,7 @@ function useMemoEcdsaAirdropClient(opts) {
|
|
|
161
166
|
publicClient,
|
|
162
167
|
...walletClient ? { walletClient } : {},
|
|
163
168
|
address: opts.address,
|
|
164
|
-
dedupMode: opts.dedupMode,
|
|
169
|
+
...opts.dedupMode !== void 0 ? { dedupMode: opts.dedupMode } : {},
|
|
165
170
|
...chainId !== void 0 ? { chainId } : {},
|
|
166
171
|
...telemetry ? { telemetry } : {}
|
|
167
172
|
});
|
|
@@ -174,6 +179,7 @@ var AIRDROP_FN = {
|
|
|
174
179
|
// instance reads
|
|
175
180
|
claimedAmount: "getClaimedAmount",
|
|
176
181
|
paused: "paused",
|
|
182
|
+
dedupMode: "dedupMode",
|
|
177
183
|
window: "window",
|
|
178
184
|
config: "config",
|
|
179
185
|
merkleRoot: "merkleRoot",
|
|
@@ -190,20 +196,29 @@ var AIRDROP_FN = {
|
|
|
190
196
|
resolvedGasFee: "resolvedGasFee",
|
|
191
197
|
customFee: "customFee",
|
|
192
198
|
implementations: "implementations",
|
|
199
|
+
tokenOf: "tokenOf",
|
|
200
|
+
complianceManagerOf: "complianceManagerOf",
|
|
193
201
|
compliancePolicy: "compliancePolicy",
|
|
194
202
|
upgradeabilityPolicy: "upgradeabilityPolicy",
|
|
195
203
|
factoryHasRole: "factoryHasRole",
|
|
196
204
|
factoryRoleMembers: "factoryRoleMembers",
|
|
205
|
+
effectiveDelegateToCompliance: "effectiveDelegateToCompliance",
|
|
206
|
+
effectiveUpgradeable: "effectiveUpgradeable",
|
|
207
|
+
complianceDelegate: "complianceDelegate",
|
|
208
|
+
ecdsaInitCodeHash: "getEcdsaInitCodeHash",
|
|
209
|
+
predictEcdsaAddress: "predictEcdsaAirdropAddress",
|
|
210
|
+
merkleInitCodeHash: "getMerkleInitCodeHash",
|
|
211
|
+
predictMerkleAddress: "predictMerkleAirdropAddress",
|
|
197
212
|
// compliance-manager reads
|
|
198
213
|
complianceInfo: "complianceInfo",
|
|
199
214
|
activeDelegate: "isActiveDelegate",
|
|
200
|
-
clientDelegates: "clientDelegates",
|
|
201
215
|
complianceHasRole: "complianceHasRole",
|
|
202
216
|
complianceRoleMembers: "complianceRoleMembers"
|
|
203
217
|
};
|
|
204
218
|
var airdropKeys = {
|
|
205
219
|
/** One account's cumulative delivered total. Keyed on the CLAIM IDENTITY, never the sender. */
|
|
206
220
|
claimedAmount: (s, account) => airdropQueryKey({ ...s, fn: AIRDROP_FN.claimedAmount, args: [account] }),
|
|
221
|
+
dedupMode: (s) => airdropQueryKey({ ...s, fn: AIRDROP_FN.dedupMode, args: [] }),
|
|
207
222
|
paused: (s) => airdropQueryKey({ ...s, fn: AIRDROP_FN.paused, args: [] }),
|
|
208
223
|
window: (s) => airdropQueryKey({ ...s, fn: AIRDROP_FN.window, args: [] }),
|
|
209
224
|
config: (s) => airdropQueryKey({ ...s, fn: AIRDROP_FN.config, args: [] }),
|
|
@@ -221,15 +236,17 @@ var airdropKeys = {
|
|
|
221
236
|
isSignatureValidAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.isSignatureValid }),
|
|
222
237
|
fees: (s) => airdropQueryKey({ ...s, fn: AIRDROP_FN.fees, args: [] }),
|
|
223
238
|
customFee: (s, creator) => airdropQueryKey({ ...s, fn: AIRDROP_FN.customFee, args: [creator] }),
|
|
224
|
-
customFeeAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.customFee }),
|
|
225
239
|
resolvedGasFee: (s, creator) => airdropQueryKey({ ...s, fn: AIRDROP_FN.resolvedGasFee, args: [creator] }),
|
|
226
240
|
/** Every creator's resolved fee; the default and any override both move it. */
|
|
227
241
|
resolvedGasFeeAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.resolvedGasFee }),
|
|
242
|
+
registry: (s, offset, limit) => airdropQueryKey({ ...s, fn: AIRDROP_FN.registry, args: [offset, limit] }),
|
|
228
243
|
/** Every registry page, whatever offset/limit was queried. */
|
|
229
244
|
registryAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.registry }),
|
|
230
245
|
isAirdrop: (s, candidate) => airdropQueryKey({ ...s, fn: AIRDROP_FN.isAirdrop, args: [candidate] }),
|
|
231
246
|
/** Every genuineness answer from this factory; a create adds one address. */
|
|
232
247
|
isAirdropAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.isAirdrop }),
|
|
248
|
+
tokenOf: (s, airdrop) => airdropQueryKey({ ...s, fn: AIRDROP_FN.tokenOf, args: [airdrop] }),
|
|
249
|
+
complianceManagerOf: (s, airdrop) => airdropQueryKey({ ...s, fn: AIRDROP_FN.complianceManagerOf, args: [airdrop] }),
|
|
233
250
|
implementations: (s) => airdropQueryKey({ ...s, fn: AIRDROP_FN.implementations, args: [] }),
|
|
234
251
|
compliancePolicy: (s, creator) => airdropQueryKey({ ...s, fn: AIRDROP_FN.compliancePolicy, args: [creator] }),
|
|
235
252
|
compliancePolicyAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.compliancePolicy }),
|
|
@@ -238,16 +255,42 @@ var airdropKeys = {
|
|
|
238
255
|
factoryHasRole: (s, role, holder) => airdropQueryKey({ ...s, fn: AIRDROP_FN.factoryHasRole, args: [role, holder] }),
|
|
239
256
|
factoryHasRoleAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.factoryHasRole }),
|
|
240
257
|
factoryRoleMembers: (s, role) => airdropQueryKey({ ...s, fn: AIRDROP_FN.factoryRoleMembers, args: [role] }),
|
|
241
|
-
|
|
258
|
+
effectiveDelegateToCompliance: (s, creator) => airdropQueryKey({ ...s, fn: AIRDROP_FN.effectiveDelegateToCompliance, args: [creator] }),
|
|
259
|
+
/** Every creator's effective compliance default; the factory-wide default moves them all. */
|
|
260
|
+
effectiveDelegateToComplianceAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.effectiveDelegateToCompliance }),
|
|
261
|
+
effectiveUpgradeable: (s, creator) => airdropQueryKey({ ...s, fn: AIRDROP_FN.effectiveUpgradeable, args: [creator] }),
|
|
262
|
+
/** Every creator's effective upgradeability; the factory-wide default moves them all. */
|
|
263
|
+
effectiveUpgradeableAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.effectiveUpgradeable }),
|
|
264
|
+
complianceDelegate: (s) => airdropQueryKey({ ...s, fn: AIRDROP_FN.complianceDelegate, args: [] }),
|
|
265
|
+
/** Keyed on `mode` only: `params` does not affect the hash (see `useEcdsaInitCodeHash`). */
|
|
266
|
+
ecdsaInitCodeHash: (s, mode) => airdropQueryKey({ ...s, fn: AIRDROP_FN.ecdsaInitCodeHash, args: [mode] }),
|
|
267
|
+
ecdsaInitCodeHashAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.ecdsaInitCodeHash }),
|
|
268
|
+
predictEcdsaAddress: (s, mode, deployer, userSalt) => airdropQueryKey({ ...s, fn: AIRDROP_FN.predictEcdsaAddress, args: [mode, deployer, userSalt] }),
|
|
269
|
+
predictEcdsaAddressAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.predictEcdsaAddress }),
|
|
270
|
+
merkleInitCodeHash: (s, mode) => airdropQueryKey({ ...s, fn: AIRDROP_FN.merkleInitCodeHash, args: [mode] }),
|
|
271
|
+
merkleInitCodeHashAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.merkleInitCodeHash }),
|
|
272
|
+
predictMerkleAddress: (s, mode, deployer, userSalt) => airdropQueryKey({
|
|
273
|
+
...s,
|
|
274
|
+
fn: AIRDROP_FN.predictMerkleAddress,
|
|
275
|
+
args: [mode, deployer, userSalt]
|
|
276
|
+
}),
|
|
277
|
+
predictMerkleAddressAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.predictMerkleAddress }),
|
|
242
278
|
complianceInfo: (s) => airdropQueryKey({ ...s, fn: AIRDROP_FN.complianceInfo, args: [] }),
|
|
243
279
|
activeDelegate: (s, delegate) => airdropQueryKey({ ...s, fn: AIRDROP_FN.activeDelegate, args: [delegate] }),
|
|
244
|
-
activeDelegateAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.activeDelegate }),
|
|
245
|
-
clientDelegates: (s, index) => airdropQueryKey({ ...s, fn: AIRDROP_FN.clientDelegates, args: [index] }),
|
|
246
|
-
clientDelegatesAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.clientDelegates }),
|
|
247
280
|
complianceHasRole: (s, role, holder) => airdropQueryKey({ ...s, fn: AIRDROP_FN.complianceHasRole, args: [role, holder] }),
|
|
248
281
|
complianceHasRoleAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.complianceHasRole }),
|
|
249
|
-
complianceRoleMembers: (s, role) => airdropQueryKey({ ...s, fn: AIRDROP_FN.complianceRoleMembers, args: [role] })
|
|
250
|
-
complianceRoleMembersAll: (s) => airdropQueryKeyPrefix({ ...s, fn: AIRDROP_FN.complianceRoleMembers })
|
|
282
|
+
complianceRoleMembers: (s, role) => airdropQueryKey({ ...s, fn: AIRDROP_FN.complianceRoleMembers, args: [role] })
|
|
251
283
|
};
|
|
284
|
+
function invalidateAfterCreate(queryClient, scope, airdrop) {
|
|
285
|
+
for (const queryKey of [
|
|
286
|
+
airdropKeys.registryAll(scope),
|
|
287
|
+
airdropKeys.isAirdropAll(scope),
|
|
288
|
+
airdropKeys.preflightCreateAll(scope),
|
|
289
|
+
airdropKeys.tokenOf(scope, airdrop),
|
|
290
|
+
airdropKeys.complianceManagerOf(scope, airdrop)
|
|
291
|
+
]) {
|
|
292
|
+
void queryClient.invalidateQueries({ queryKey });
|
|
293
|
+
}
|
|
294
|
+
}
|
|
252
295
|
|
|
253
|
-
export { AIRDROP_FN, airdropKeys, airdropQueryKey, airdropQueryKeyPrefix, useMemoAirdropBaseClient, useMemoAirdropFactoryClient, useMemoComplianceManagerClient, useMemoEcdsaAirdropClient, useMemoMerkleAirdropClient };
|
|
296
|
+
export { AIRDROP_FN, airdropKeys, airdropQueryKey, airdropQueryKeyPrefix, invalidateAfterCreate, staleUntilNonZeroAddress, useMemoAirdropBaseClient, useMemoAirdropFactoryClient, useMemoComplianceManagerClient, useMemoEcdsaAirdropClient, useMemoMerkleAirdropClient };
|