@tokenops/sdk 1.5.1 → 2.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +198 -2
- package/CONTRIBUTING.md +4 -2
- package/README.md +146 -90
- package/SECURITY.md +7 -1
- package/SUPPORT.md +47 -0
- package/dist/{chunk-YQIBBEFJ.js → chunk-335Z2W67.js} +1 -1
- package/dist/{chunk-2NCLOQ56.cjs → chunk-3QHNYEQD.cjs} +77 -0
- package/dist/chunk-456VDDA3.js +370 -0
- package/dist/{chunk-SG65XWH7.js → chunk-4RAAATVY.js} +1 -3
- package/dist/{chunk-6BMP4ICG.js → chunk-4TSDNZQ3.js} +60 -2
- package/dist/{chunk-PUPKNW3R.cjs → chunk-5576FRT3.cjs} +30 -6
- package/dist/{chunk-AOP6HMPW.js → chunk-6GNR22OV.js} +75 -1
- package/dist/{chunk-NTZY6IB7.js → chunk-6NAVMWZQ.js} +4 -3
- package/dist/{chunk-C7BRZXJA.cjs → chunk-6PXXGACR.cjs} +8 -7
- package/dist/{chunk-IJFQ5L4I.js → chunk-74QFZ5MK.js} +4 -3
- package/dist/chunk-7AFPOE7N.cjs +59 -0
- package/dist/chunk-AXIPOR3C.js +56 -0
- package/dist/chunk-CTED3MTR.cjs +380 -0
- package/dist/{chunk-XGGTQQFH.js → chunk-DZHYSUGY.js} +28 -7
- package/dist/{chunk-OXTLPTO3.js → chunk-EAJ7SYHE.js} +4 -3
- package/dist/{chunk-V2PXZVBF.cjs → chunk-FGEB7RMY.cjs} +4 -4
- package/dist/chunk-GKKDAW44.js +8823 -0
- package/dist/{chunk-2PWNH3UE.js → chunk-H5POPGOZ.js} +63 -5
- package/dist/{chunk-W7IGCOVL.cjs → chunk-JQYC66TO.cjs} +9 -8
- package/dist/{chunk-PFXURMBZ.cjs → chunk-JZLGCTGK.cjs} +68 -8
- package/dist/{chunk-JYOTGRSO.cjs → chunk-KFRDLKMA.cjs} +61 -1
- package/dist/chunk-M4IT6DNJ.cjs +608 -0
- package/dist/{chunk-KLKI352M.cjs → chunk-MVDQMV25.cjs} +0 -3
- package/dist/chunk-NCVX3K2N.cjs +161 -0
- package/dist/chunk-NWFMBLSQ.js +4 -0
- package/dist/chunk-O5676ZWY.js +585 -0
- package/dist/chunk-PUX5VXDB.cjs +8845 -0
- package/dist/{chunk-IXLO7GO5.js → chunk-TWT3STIX.js} +46 -80
- package/dist/chunk-UG5RKLU2.cjs +6 -0
- package/dist/chunk-VP2B4WM2.js +154 -0
- package/dist/{chunk-5X5WL5CU.cjs → chunk-WJLECC22.cjs} +51 -88
- package/dist/{chunk-WENHUPZC.cjs → chunk-XAYGD4E4.cjs} +9 -8
- package/dist/core/addresses.d.ts +15 -3
- package/dist/core/brands.d.ts +8 -2
- package/dist/core/errors.d.ts +71 -10
- package/dist/core/preflight.d.ts +1 -0
- package/dist/fhe/erc7984-abi.d.ts +1 -0
- package/dist/fhe/index.cjs +34 -13
- package/dist/fhe/index.d.cts +1 -0
- package/dist/fhe/index.d.ts +1 -0
- package/dist/fhe/index.js +19 -6
- package/dist/fhe/mock-erc7984.d.ts +4 -4
- package/dist/fhe/operators.d.ts +160 -3
- package/dist/fhe/react/index.cjs +14 -0
- package/dist/fhe/react/index.d.cts +2 -0
- package/dist/fhe/react/index.d.ts +2 -0
- package/dist/fhe/react/index.js +6 -0
- package/dist/fhe/react/useEnsureOperator.d.ts +56 -0
- package/dist/fhe/react/useIsOperator.d.ts +54 -0
- package/dist/fhe/sepolia-encryptor-web.d.ts +18 -3
- package/dist/fhe/types.d.ts +6 -0
- package/dist/fhe-airdrop/abis/{cloneable.d.ts → airdrop-base.d.ts} +254 -396
- package/dist/fhe-airdrop/abis/compliance.d.ts +422 -0
- package/dist/fhe-airdrop/abis/ecdsa.d.ts +1316 -0
- package/dist/fhe-airdrop/abis/factory.d.ts +1319 -190
- package/dist/fhe-airdrop/abis/index.d.ts +5 -2
- package/dist/fhe-airdrop/abis/merkle.d.ts +1238 -0
- package/dist/fhe-airdrop/advanced/index.cjs +10 -12
- package/dist/fhe-airdrop/advanced/index.d.cts +34 -11
- package/dist/fhe-airdrop/advanced/index.d.ts +34 -11
- package/dist/fhe-airdrop/advanced/index.js +2 -8
- package/dist/fhe-airdrop/advanced/react/index.cjs +34 -48
- package/dist/fhe-airdrop/advanced/react/index.d.cts +9 -3
- package/dist/fhe-airdrop/advanced/react/index.d.ts +9 -3
- package/dist/fhe-airdrop/advanced/react/index.js +33 -48
- package/dist/fhe-airdrop/advanced/react/usePredictEcdsaAirdropAddress.d.ts +33 -0
- package/dist/fhe-airdrop/advanced/react/usePredictMerkleAirdropAddress.d.ts +27 -0
- package/dist/fhe-airdrop/airdrop-base.d.ts +600 -0
- package/dist/fhe-airdrop/campaign.d.ts +297 -0
- package/dist/fhe-airdrop/compliance.d.ts +302 -0
- package/dist/fhe-airdrop/constants.d.ts +33 -0
- package/dist/fhe-airdrop/ecdsa.d.ts +263 -0
- package/dist/fhe-airdrop/encryption.d.ts +92 -14
- package/dist/fhe-airdrop/errors.d.ts +245 -15
- package/dist/fhe-airdrop/factory.d.ts +533 -274
- package/dist/fhe-airdrop/guards.d.ts +273 -0
- package/dist/fhe-airdrop/index.cjs +1089 -33
- package/dist/fhe-airdrop/index.d.cts +46 -8
- package/dist/fhe-airdrop/index.d.ts +46 -8
- package/dist/fhe-airdrop/index.js +929 -7
- package/dist/fhe-airdrop/merkle-tree.d.ts +103 -0
- package/dist/fhe-airdrop/merkle.d.ts +180 -0
- package/dist/fhe-airdrop/react/_shared.d.ts +144 -71
- package/dist/fhe-airdrop/react/index.cjs +364 -413
- package/dist/fhe-airdrop/react/index.d.cts +53 -72
- package/dist/fhe-airdrop/react/index.d.ts +53 -72
- package/dist/fhe-airdrop/react/index.js +258 -369
- package/dist/fhe-airdrop/react/useAirdropGasFee.d.ts +10 -5
- package/dist/fhe-airdrop/react/useAirdropHasRole.d.ts +15 -6
- package/dist/fhe-airdrop/react/useAirdropPause.d.ts +30 -0
- package/dist/fhe-airdrop/react/useAirdropPaused.d.ts +17 -0
- package/dist/fhe-airdrop/react/useAirdropToken.d.ts +11 -4
- package/dist/fhe-airdrop/react/useAirdropWindow.d.ts +37 -0
- package/dist/fhe-airdrop/react/useClaimedAmount.d.ts +29 -0
- package/dist/fhe-airdrop/react/useComplianceManager.d.ts +16 -0
- package/dist/fhe-airdrop/react/useCreateEcdsaAirdrop.d.ts +28 -0
- package/dist/fhe-airdrop/react/useCreateMerkleAirdrop.d.ts +25 -0
- package/dist/fhe-airdrop/react/useEcdsaClaim.d.ts +23 -0
- package/dist/fhe-airdrop/react/useEffectiveUpgradeable.d.ts +20 -0
- package/dist/fhe-airdrop/react/useExtendClaimWindow.d.ts +17 -12
- package/dist/fhe-airdrop/react/useFactoryFees.d.ts +28 -0
- package/dist/fhe-airdrop/react/useFactoryRegistry.d.ts +35 -0
- package/dist/fhe-airdrop/react/useFundAirdrop.d.ts +35 -0
- package/dist/fhe-airdrop/react/useGrantInstanceRoles.d.ts +35 -0
- package/dist/fhe-airdrop/react/useMerkleClaim.d.ts +34 -0
- package/dist/fhe-airdrop/react/useMerkleRoot.d.ts +15 -0
- package/dist/fhe-airdrop/react/useSetMerkleRoot.d.ts +22 -0
- package/dist/fhe-airdrop/react/useWithdrawConfidential.d.ts +23 -0
- package/dist/fhe-airdrop/roles.d.ts +147 -0
- package/dist/fhe-airdrop/types.d.ts +68 -55
- package/dist/fhe-disperse/errors.d.ts +55 -0
- package/dist/fhe-disperse/index.cjs +34 -25
- package/dist/fhe-disperse/index.d.cts +1 -1
- package/dist/fhe-disperse/index.d.ts +1 -1
- package/dist/fhe-disperse/index.js +6 -5
- package/dist/fhe-disperse/react/index.cjs +42 -23
- package/dist/fhe-disperse/react/index.d.cts +3 -1
- package/dist/fhe-disperse/react/index.d.ts +3 -1
- package/dist/fhe-disperse/react/index.js +9 -6
- package/dist/fhe-vesting/advanced/index.cjs +8 -7
- package/dist/fhe-vesting/advanced/index.js +6 -5
- package/dist/fhe-vesting/advanced/react/index.cjs +12 -11
- package/dist/fhe-vesting/advanced/react/index.js +9 -8
- package/dist/fhe-vesting/index.cjs +35 -34
- package/dist/fhe-vesting/index.js +7 -6
- package/dist/fhe-vesting/manager.d.ts +19 -0
- package/dist/fhe-vesting/react/index.cjs +160 -140
- package/dist/fhe-vesting/react/index.d.cts +6 -4
- package/dist/fhe-vesting/react/index.d.ts +6 -4
- package/dist/fhe-vesting/react/index.js +24 -16
- package/dist/fhe-vesting/react/useAccessClaimableAmount.d.ts +11 -3
- package/dist/fhe-vesting/react/useAccessSettledAmount.d.ts +11 -3
- package/dist/fhe-vesting/react/useAccessTotalAllocation.d.ts +11 -3
- package/dist/fhe-vesting/react/useAccessVestedAmount.d.ts +11 -3
- package/dist/fhe-vesting/react/useAdminGetClaimableAmount.d.ts +1 -1
- package/dist/fhe-vesting/react/useAdminGetSettledAmount.d.ts +1 -1
- package/dist/fhe-vesting/react/useAdminGetTotalAllocation.d.ts +1 -1
- package/dist/fhe-vesting/react/useAdminGetVestedAmount.d.ts +1 -1
- package/dist/fhe-vesting/react/useAdminPartialClaim.d.ts +8 -0
- package/dist/fhe-vesting/react/useClaim.d.ts +1 -1
- package/dist/fhe-vesting/react/useDiscloseHandleToParty.d.ts +1 -1
- package/dist/fhe-vesting/react/useManagerDiscloseHandleToParty.d.ts +1 -1
- package/dist/fhe-vesting/react/usePartialClaim.d.ts +1 -1
- package/dist/fhe-vesting/react/useVestingInfo.d.ts +1 -1
- package/dist/fhe-vesting/types.d.ts +12 -1
- package/dist/index.cjs +27 -15
- package/dist/index.js +1 -1
- package/dist/testnet-faucet/index.cjs +17 -16
- package/dist/testnet-faucet/index.js +5 -4
- package/dist/testnet-faucet/react/index.cjs +11 -10
- package/dist/testnet-faucet/react/index.js +6 -5
- package/package.json +18 -9
- package/dist/chunk-4WPGQSNT.cjs +0 -44
- package/dist/chunk-6R4KNAPK.js +0 -1630
- package/dist/chunk-DUZIIRPF.js +0 -1655
- package/dist/chunk-MCRBVJGZ.cjs +0 -1637
- package/dist/chunk-ODLTEGHB.js +0 -41
- package/dist/chunk-ORFTDNFZ.js +0 -105
- package/dist/chunk-T46YXSBP.cjs +0 -109
- package/dist/chunk-TIUKIY5V.cjs +0 -1663
- package/dist/fhe-airdrop/advanced/factory-advanced.d.ts +0 -53
- package/dist/fhe-airdrop/advanced/react/usePredictAirdropAddress.d.ts +0 -49
- package/dist/fhe-airdrop/airdrop.d.ts +0 -310
- package/dist/fhe-airdrop/react/useAccessClaimAmount.d.ts +0 -31
- package/dist/fhe-airdrop/react/useAirdropCanExtendClaimWindow.d.ts +0 -7
- package/dist/fhe-airdrop/react/useAirdropClaim.d.ts +0 -27
- package/dist/fhe-airdrop/react/useAirdropClaimTypehash.d.ts +0 -10
- package/dist/fhe-airdrop/react/useAirdropClaimedSignatures.d.ts +0 -16
- package/dist/fhe-airdrop/react/useAirdropDeploymentBlockNumber.d.ts +0 -6
- package/dist/fhe-airdrop/react/useAirdropDomainSeparator.d.ts +0 -8
- package/dist/fhe-airdrop/react/useAirdropEndTime.d.ts +0 -10
- package/dist/fhe-airdrop/react/useAirdropFactoryCustomFee.d.ts +0 -17
- package/dist/fhe-airdrop/react/useAirdropFactoryDefaultGasFee.d.ts +0 -10
- package/dist/fhe-airdrop/react/useAirdropFactoryDisableCustomFee.d.ts +0 -15
- package/dist/fhe-airdrop/react/useAirdropFactoryFeeCollector.d.ts +0 -11
- package/dist/fhe-airdrop/react/useAirdropFactoryInitCodeHash.d.ts +0 -17
- package/dist/fhe-airdrop/react/useAirdropFactorySetCustomFee.d.ts +0 -17
- package/dist/fhe-airdrop/react/useAirdropFactorySetDefaultGasFee.d.ts +0 -16
- package/dist/fhe-airdrop/react/useAirdropFactorySetFeeCollector.d.ts +0 -15
- package/dist/fhe-airdrop/react/useAirdropGrantRole.d.ts +0 -16
- package/dist/fhe-airdrop/react/useAirdropHasClaimEnded.d.ts +0 -7
- package/dist/fhe-airdrop/react/useAirdropHasClaimStarted.d.ts +0 -7
- package/dist/fhe-airdrop/react/useAirdropIsClaimWindowActive.d.ts +0 -9
- package/dist/fhe-airdrop/react/useAirdropIsPaused.d.ts +0 -8
- package/dist/fhe-airdrop/react/useAirdropIsSignatureClaimed.d.ts +0 -22
- package/dist/fhe-airdrop/react/useAirdropIsSignatureValid.d.ts +0 -51
- package/dist/fhe-airdrop/react/useAirdropRevokeRole.d.ts +0 -15
- package/dist/fhe-airdrop/react/useAirdropStartTime.d.ts +0 -10
- package/dist/fhe-airdrop/react/useAirdropWithdrawGasFee.d.ts +0 -15
- package/dist/fhe-airdrop/react/useAirdropWithdrawOtherConfidentialToken.d.ts +0 -14
- package/dist/fhe-airdrop/react/useAirdropWithdrawOtherToken.d.ts +0 -14
- package/dist/fhe-airdrop/react/useClaim.d.ts +0 -31
- package/dist/fhe-airdrop/react/useConfidentialAirdropFactoryImplementation.d.ts +0 -11
- package/dist/fhe-airdrop/react/useCreateAndFundConfidentialAirdrop.d.ts +0 -41
- package/dist/fhe-airdrop/react/useCreateAndFundConfidentialAirdropAndGetAddress.d.ts +0 -48
- package/dist/fhe-airdrop/react/useCreateConfidentialAirdrop.d.ts +0 -29
- package/dist/fhe-airdrop/react/useCreateConfidentialAirdropAndGetAddress.d.ts +0 -31
- package/dist/fhe-airdrop/react/useDisableCustomFee.d.ts +0 -14
- package/dist/fhe-airdrop/react/useFactoryCustomFee.d.ts +0 -17
- package/dist/fhe-airdrop/react/useFactoryDefaultGasFee.d.ts +0 -10
- package/dist/fhe-airdrop/react/useFactoryFeeCollector.d.ts +0 -11
- package/dist/fhe-airdrop/react/useFactoryInitCodeHash.d.ts +0 -17
- package/dist/fhe-airdrop/react/useFundConfidentialAirdrop.d.ts +0 -33
- package/dist/fhe-airdrop/react/useGetClaimAmount.d.ts +0 -30
- package/dist/fhe-airdrop/react/usePreflightCreateAirdrop.d.ts +0 -51
- package/dist/fhe-airdrop/react/useSetCustomFee.d.ts +0 -16
- package/dist/fhe-airdrop/react/useSetDefaultGasFee.d.ts +0 -15
- package/dist/fhe-airdrop/react/useSetFeeCollector.d.ts +0 -14
- package/dist/fhe-airdrop/react/useSetPaused.d.ts +0 -14
- package/dist/fhe-airdrop/react/useSignClaimAuthorization.d.ts +0 -31
- package/dist/fhe-airdrop/react/useWithdraw.d.ts +0 -12
- package/dist/fhe-airdrop/react/useWithdrawOtherConfidentialToken.d.ts +0 -13
- package/dist/fhe-airdrop/react/useWithdrawOtherToken.d.ts +0 -13
- package/dist/fhe-vesting/react/useGetClaimableAmount.d.ts +0 -13
- package/dist/fhe-vesting/react/useGetSettledAmount.d.ts +0 -14
- package/dist/fhe-vesting/react/useGetTotalAllocation.d.ts +0 -13
- package/dist/fhe-vesting/react/useGetVestedAmount.d.ts +0 -25
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,192 @@ 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
|
+
## [1.6.0](https://github.com/VestingLabs/tokenops-sdk/compare/v1.5.1...v1.6.0) (2026-07-28)
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
- **fhe:** add operator prerequisite DX helpers (S2, TOK-75) ([#63](https://github.com/VestingLabs/tokenops-sdk/issues/63)) ([ef45c2e](https://github.com/VestingLabs/tokenops-sdk/commit/ef45c2e61529f57a2b2338c7573b466e57fbf2cf))
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
- **airdrop:** stop preflightCreateAirdrop throwing on a non-ERC7984 token (TOK-436) ([b650324](https://github.com/VestingLabs/tokenops-sdk/commit/b6503243cb430fe224913fbbb39251586a4d4925))
|
|
17
|
+
- correct operator-deadline guidance in SECURITY.md, record advisory rationale ([b09273d](https://github.com/VestingLabs/tokenops-sdk/commit/b09273d7d911a4dcfdfe8e2ae7f4e3a24c2130e8))
|
|
18
|
+
- **fhe-vesting:** point Sepolia factory at the redeployed address ([0888404](https://github.com/VestingLabs/tokenops-sdk/commit/08884040987d0ebb4326d1fb80a2c2d630a6e3a6))
|
|
19
|
+
- **vesting:** stop preflightCreateVesting throwing on a non-ERC7984 token ([dfbc795](https://github.com/VestingLabs/tokenops-sdk/commit/dfbc795fa7f0fd2aee9e1abfb711e82bca22ec4c))
|
|
20
|
+
|
|
21
|
+
## [2.0.0-alpha.1] - 2026-09-07
|
|
22
|
+
|
|
23
|
+
> **Pre-release built against unaudited contracts.** `/fhe-airdrop` in this build targets `tokenops-fhe-airdrop-v2`, frozen at commit `8e5b144bdbcdf35b9f36b62f5257d795bf954e8e`, which has not completed a final security audit. Deployed addresses may change before `2.0.0` GA, and 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.**
|
|
24
|
+
>
|
|
25
|
+
> Migration guide: [`docs/migration/airdrop-v1-to-v2.md`](docs/migration/airdrop-v1-to-v2.md). Support policy: [`SUPPORT.md`](SUPPORT.md).
|
|
26
|
+
|
|
27
|
+
### Changed — BREAKING
|
|
28
|
+
|
|
29
|
+
- **`/fhe-airdrop` now targets confidential airdrop v2.** The subpath name is unchanged; everything behind it is new. v1 and v2 are different contract systems, not two versions of one — there is no in-place upgrade path for a deployed v1 airdrop. `AIRDROP_CONTRACTS_COMMIT` pins the contract commit the vendored ABIs were generated from.
|
|
30
|
+
- **`DEPLOYED_ADDRESSES.fheAirdrop` reshaped from one key to four.** Previously a single `confidentialAirdropFactory`; now `{ airdropFactory, ecdsaImplementation, merkleImplementation, complianceManagerImplementation }`. Code reading `DEPLOYED_ADDRESSES.fheAirdrop[chainId]` must read `.airdropFactory[chainId]`. Note this member is `@public`, not `@alpha` — it is the one breaking change outside the alpha-tagged surface.
|
|
31
|
+
- **The EIP-712 claim typehash gained two fields.** A v1 signature will not verify against a v2 instance, or vice versa. Re-issue authorizations from the v2 signing surface; do not port stored signatures.
|
|
32
|
+
- **Claim entrypoints take an explicit `signer`.** The claiming account is no longer inferred from the wallet client, because a Merkle leaf commits the _claimant_ — inferring it silently produced proofs bound to the wrong address.
|
|
33
|
+
- **Role-constant getters renamed to SCREAMING_SNAKE** across all five clients (`DEFAULT_ADMIN_ROLE`, `PAUSER_ROLE`, `MERKLE_ADMIN_ROLE`, `DISCLOSURE_ADMIN_ROLE`, `DELEGATION_ADMIN_ROLE`, `COMPLIANCE_WIRING_ROLE`, `FEE_MANAGER_ROLE`, `FEE_COLLECTOR_ROLE`, `IMPL_MANAGER_ROLE`, `RESCUER_ROLE`). They are contract function names and now read as such.
|
|
34
|
+
|
|
35
|
+
### Removed — BREAKING
|
|
36
|
+
|
|
37
|
+
- **The entire v1 `/fhe-airdrop` module** — clients, types, errors, ABIs, advanced surface and examples. There is no deprecation window on the v1 _shape_: it is deleted, not aliased. `1.x` remains fully supported for consumers not ready to migrate; see [`SUPPORT.md`](SUPPORT.md).
|
|
38
|
+
- **44 airdrop-specific React hooks** — 43 from `@tokenops/sdk/fhe-airdrop/react`, and `usePredictAirdropAddress` from `@tokenops/sdk/fhe-airdrop/advanced/react`. The v2 surface is 23 hooks (21 + 2 advanced); the reduction is deliberate, since several v1 hooks wrapped a single contract read with no added value.
|
|
39
|
+
- **`useIsOperator` and `useEnsureOperator` are NOT removed.** They live at `@tokenops/sdk/fhe/react` and are unaffected. If you imported them _via_ `@tokenops/sdk/fhe-airdrop/react`, change the import path; the hooks themselves are unchanged.
|
|
40
|
+
|
|
41
|
+
### Added — confidential airdrop v2
|
|
42
|
+
|
|
43
|
+
- **Split clients per variant.** `EcdsaAirdropClient` (signature-authorized claims) and `MerkleAirdropClient` (proof-authorized claims) over a shared `AirdropBaseClient`, plus `ConfidentialAirdropFactoryClient` for creation, funding, fee administration and address prediction.
|
|
44
|
+
- **Merkle campaign construction, in two independently usable stages.** `encryptCampaignAmounts()` is the relayer-only half — one request per recipient, no tree. `buildMerkleTree()` is the pure half: no relayer, no chain access, deterministic, and generic over its leaf type (`L extends MerkleLeafInput`), so an `inputProof` or any caller-defined field rides through onto the returned entry at the same index with no re-correlation. `buildMerkleCampaign()` is unchanged in signature and behaviour and is now the composition of the two. This is what lets a consumer who already holds encrypted handles build a claimable campaign without re-encrypting — necessary because FHE encryption is randomised, so re-encrypting produces a tree committing to handles nobody holds.
|
|
45
|
+
- **`planMerkleCampaign()`** for the immutable-root path, which is otherwise circular: the root must exist before creation, yet every ciphertext binds to the instance address creation has not produced. It uses the factory's CREATE2 prediction and brackets that prediction with two init-code-hash reads, throwing `PredictionDriftError` rather than returning a plan bound to a stale address.
|
|
46
|
+
- **`rotateMerkleRoot()`** — re-encrypt and republish as a top-up. A claim pays `total − min(total, alreadyDelivered)`, so `recipients` must carry each account's new _cumulative_ total, never an increment.
|
|
47
|
+
- **`ComplianceManagerClient`** for the compliance clone: wiring, party disclosure, and role administration.
|
|
48
|
+
- **Instance role splitting and full role administration** — `planInstanceRoleSplit()` and `grantInstanceRoles()`, which confirms each step's receipt before advancing so a dependent revoke cannot be simulated against state that lacks the preceding grant.
|
|
49
|
+
- **Guardrails and preflights** — typed, pre-transaction failures for salt collisions, wrapper assumptions and window state, instead of an opaque revert.
|
|
50
|
+
- **`deploymentMode()`** on `AirdropBaseClient`, reading the ERC-1967 implementation slot. Necessary because `proxiableUUID()` cannot discriminate a clone from a UUPS proxy: OpenZeppelin's `notDelegated` makes it revert through _any_ proxy.
|
|
51
|
+
- **`upgradeToAndCall()`** on `AirdropBaseClient`, and **`eip712Domain()`** on `EcdsaAirdropClient` (EIP-5267 domain discovery).
|
|
52
|
+
- **23 React hooks** across `/fhe-airdrop/react` and `/fhe-airdrop/advanced/react`, wagmi + TanStack Query, sharing the `"tokenops-sdk"` query-key prefix used by every sibling subpath.
|
|
53
|
+
- **Typed error mapping** from v2 revert selectors, and encrypted-view reads that extract handles from the executed receipt's ACL `Allowed` event rather than from `simulateContract()` — a simulated handle carries no ACL and fails later, at the decrypt, far from its cause.
|
|
54
|
+
- **Docs and examples** — [`docs/fhe-airdrop/README.md`](docs/fhe-airdrop/README.md) with measured live-relayer throughput, per-recipient storage sizing, and a "bring your own handles" guide; [`docs/migration/airdrop-v1-to-v2.md`](docs/migration/airdrop-v1-to-v2.md); a README compatibility matrix; and three runnable examples (`fhe-airdrop-merkle-campaign.ts`, `fhe-airdrop-external-handles.ts`, `fhe-airdrop-ecdsa-claim.ts`).
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
- **`release.yml` no longer defaults a prerelease onto the `latest` dist-tag.** The npm dist-tag is derived from the package version (`alpha` / `beta` / `rc` / `next` / `latest`), and the `workflow_dispatch` override input now defaults to blank so it cannot mask that derivation.
|
|
59
|
+
- **`useAirdropPause` invalidates the `window` query as well as `paused`.** `isClaimWindowActive()` ANDs the pause flag with the window check, so mounted `useAirdropWindow` consumers previously kept a stale `isActive` after either pause transition.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
_The sections below were developed against `1.x` and had not yet shipped when `2.0.0-alpha.1` was cut. They are unrelated to the airdrop rewrite, and none of them are breaking._
|
|
64
|
+
|
|
65
|
+
### Added — operator prerequisite DX helpers (TOK-75)
|
|
66
|
+
|
|
67
|
+
- **`isOperator()` and `ensureOperator()`** — new headless operator-prerequisite helpers on `@tokenops/sdk/fhe`. `isOperator({ publicClient, token, holder, spender })` is a read-only check of `spender`'s ERC-7984 operator status for `holder` on `token` (an expired grant reads `false` — expiry needs no revoke tx). `ensureOperator({ publicClient, walletClient, token, spender, deadline, account?, waitForReceipt? })` is the idempotent check-then-set: it resolves `{ alreadyOperator: true, hash: null }` without sending a transaction when the grant is already active (cost: one `eth_call`), and otherwise performs the `setOperator` write and returns its hash. `deadline` is **required** — unlike `setOperator`, `ensureOperator` refuses to silently default a security-sensitive approval window to the never-expiring `ERC7984_OPERATOR_MAX_DEADLINE`; pass that constant explicitly if forever is what you want. Out-of-range deadlines (`<= 0` or `> 2**48 - 1`) and unresolvable accounts throw `TokenOpsContractError` before any RPC call. Caveat (documented in TSDoc): the pre-check confirms the grant is currently active, not until when — `ensureOperator` does not refresh a grant that expires mid-flow; call `setOperator` directly to extend a window.
|
|
68
|
+
- **`useIsOperator` and `useEnsureOperator` React hooks** — the same prerequisite pair for wagmi + TanStack Query apps, exported from `@tokenops/sdk/fhe/react` and re-exported from `@tokenops/sdk/fhe-vesting/react`, `@tokenops/sdk/fhe-airdrop/react`, and `@tokenops/sdk/fhe-disperse/react`. `useIsOperator({ token, spender, holder?, chainId?, enabled? })` returns `UseQueryResult<boolean, Error>` — `holder` defaults to the connected account and the query stays disabled until `token`, `holder`, and `spender` are all present. Query key: `["tokenops-sdk", "fhe", "isOperator", chainId, token, holder, spender]` (lowercased addresses) — invalidate it after a successful grant. `useEnsureOperator({ chainId? })` returns `UseMutationResult<EnsureOperatorResult, Error, EnsureOperatorVariables>` and throws `MissingPublicClientError` / `MissingWalletClientError` when the wagmi clients are unavailable.
|
|
69
|
+
- New exported types: `IsOperatorArgs`, `EnsureOperatorArgs`, `EnsureOperatorResult` from `@tokenops/sdk/fhe`; `UseIsOperatorOptions`, `UseEnsureOperatorOptions`, `EnsureOperatorVariables` from `@tokenops/sdk/fhe/react` and the three product `/react` subpaths.
|
|
70
|
+
- `ConfidentialVestingManagerClient.createVesting` and `.batchCreateVesting` TSDoc now documents the operator prerequisite (set the manager as operator via `token.setOperator(...)` or `ensureOperator()`) and the `OperatorNotApprovedError` thrown when it is skipped. Documentation only; no runtime change.
|
|
71
|
+
|
|
72
|
+
### Added — typed approval blockers in `preflightDisperse` (TOK-69)
|
|
73
|
+
|
|
74
|
+
- **`SubwalletsNotApprovedError` and `SingletonNotApprovedError`** — `ConfidentialDisperseClient.preflightDisperse` now pushes typed errors into `PreflightReport.blockerErrors[]` for the two approval checks that were previously string-only entries in the deprecated `blockers: string[]`: `SubwalletsNotApprovedError` (`TOKENOPS_SUBWALLETS_NOT_APPROVED`, `context.{wallet0Approved,wallet1Approved}`; emitted in `"wallet"` / `"wallet-token-fee"` modes when the **registered** sub-wallet pair is not fully approved — unregistered users get only `NotRegisteredError`, with approval state still reported informationally via `hasApprovedSubwallets`) and `SingletonNotApprovedError` (`TOKENOPS_SINGLETON_NOT_APPROVED`; emitted in `"direct"` mode when the sender has not approved the singleton as ERC-7984 operator). Both classes are exported from `@tokenops/sdk/fhe-disperse` and `/fhe-disperse/react`; both codes join the `TokenOpsSdkErrorCode` union. Errors are collected, never thrown — the preflight contract is unchanged.
|
|
75
|
+
|
|
76
|
+
### Added
|
|
77
|
+
|
|
78
|
+
- **`Encryptor`, `EncryptorSource`, and `FheValueInput` re-exported from `@tokenops/sdk/fhe`** — next to the `createSepoliaEncryptor*` / `createMockEncryptor` factories that produce them. Previously these types were only importable from the product subpaths even though the factories live on `/fhe` (TOK-69).
|
|
79
|
+
- **Opt-in `threads` option on `createSepoliaEncryptorWeb`** — `CreateSepoliaEncryptorWebOpts.threads?: number` is forwarded to the Zama relayer's WASM worker pool for multi-threaded encryption (~2–3× faster at 4–8 threads). Requires a cross-origin-isolated page (`Cross-Origin-Opener-Policy: same-origin` + `Cross-Origin-Embedder-Policy: require-corp`); when `threads > 1` is set on a non-isolated page the SDK logs a warning (configured logger or `console.warn`) explaining that encryption will silently run single-threaded and which headers to add. Omitting `threads` keeps the single-threaded default (TOK-69).
|
|
80
|
+
|
|
81
|
+
### Changed
|
|
82
|
+
|
|
83
|
+
- **Sepolia `confidentialVestingFactory` address updated to `0x059d6Bb8ff9a13E794fe416d4757d7310CdC69ab`** (was `0xA87701CE9A52D43681600583a99c85b50DbE3150`). The factory was redeployed with the post-audit fix that packs a constant zero as the clone's deployment-block-number immutable arg (the `DEPLOYMENT_BLOCK_NUMBER` getter surfaced as `ConfidentialVestingManagerClient.deploymentBlockNumber()`), and with `defaultGasFee = 0` instead of `3500000000000`. `getFheVestingFactoryAddress(sepolia.id)` and `DEPLOYED_ADDRESSES.fheVesting.confidentialVestingFactory[11155111]` now resolve to the new address. Managers already created through the old factory are unaffected and remain usable — construct their clients with an explicit `address`. Side effect of the constant-zero packing: `predictManagerAddress` against the new factory is block-stable (predict-then-deploy works on Sepolia again), unlike the old factory where the packed `block.number` made predictions single-block.
|
|
84
|
+
- **`createMockEncryptor` / `createSepoliaEncryptor` peer-dependency errors now carry `cause`** — the `Error` thrown when a required peer dependency fails to dynamically import now attaches the original import failure as `error.cause`, restoring the error chain for programmatic inspection. Message unchanged; no migration needed.
|
|
85
|
+
|
|
86
|
+
### Deprecated
|
|
87
|
+
|
|
88
|
+
- **`useGet*` encrypted-view hooks renamed to `useAccess*`** (TOK-69) — the encrypted-view hooks are mutations that submit a transaction, and the `useGet*` names read as free queries, which misled integrators. `@tokenops/sdk/fhe-vesting/react` now exports `useAccessVestedAmount`, `useAccessClaimableAmount`, `useAccessTotalAllocation`, `useAccessSettledAmount` (plus `UseAccess*Args` types); `@tokenops/sdk/fhe-airdrop/react` now exports `useAccessClaimAmount`. The old `useGetVestedAmount` / `useGetClaimableAmount` / `useGetTotalAllocation` / `useGetSettledAmount` / `useGetClaimAmount` names (and `UseGet*Args` types) remain exported as `@deprecated` aliases of the same function objects — identical behavior, arguments, and thrown errors — and will be removed in the next major. Migration: rename the import; nothing else changes. Only visible delta: the `MissingClientError` raised when no client is available now names the `useAccess*` hook in its message and `context.hook`, even when called via the alias.
|
|
89
|
+
|
|
90
|
+
### Fixed
|
|
91
|
+
|
|
92
|
+
- **`preflightCreateAirdrop` no longer throws on a non-ERC-7984 token** (TOK-436). Passing a `params.token` that is not a confidential token — a deployed contract without the `isOperator(address,address)` selector, or an EOA/undeployed address — previously rejected the preflight's internal `Promise.all` and threw the raw viem error out of `ConfidentialAirdropFactoryClient.preflightCreateAirdrop`. It now resolves with `ready: false` and a typed `InvalidArgumentError` (`TOKENOPS_INVALID_ARGUMENT`, `context.argument: "params.token"`) in `blockers`/`blockerErrors`; `isFactoryOperator` reports `false` (undetermined). Infrastructure failures (HTTP errors, timeouts) still propagate, so an RPC outage is never misreported as a bad token. `usePreflightCreateAirdrop` now resolves with the report instead of entering its query error state.
|
|
93
|
+
- **`preflightCreateVesting` no longer throws on a non-ERC-7984 token.** Same fix on `ConfidentialVestingManagerClient.preflightCreateVesting`: a failed `isOperator` read on the manager's bound distribution token becomes a typed `InvalidArgumentError` blocker instead of a thrown error; `isOperatorSet` reports `false` (undetermined). Affects `usePreflightCreateVesting` the same way.
|
|
94
|
+
- **Duplicate operator blocker suppressed in both create-preflights.** An invalid token previously produced two blockers in `preflightCreateAirdrop` — the token `InvalidArgumentError` plus a spurious `OperatorNotApprovedError` telling the user to approve an operator on an address that cannot hold a token (and the same double-report would have appeared in `preflightCreateVesting` once its `isOperator` failure became a blocker). Both preflights now emit the operator blocker only when the token was actually readable, so checklist UIs get exactly one actionable item. Migration note: consumers who caught a thrown error from these preflights to detect a bad token must switch to inspecting `report.blockerErrors`; don't render approve-operator prompts from `isFactoryOperator` / `isOperatorSet` alone — check `blockerErrors` for `TOKENOPS_OPERATOR_NOT_APPROVED`.
|
|
95
|
+
|
|
96
|
+
### Fixed — docs sweep
|
|
97
|
+
|
|
98
|
+
- `CreateAirdropPreflightReport.isFactoryOperator` TSDoc: clarified that `false` also covers "could not be determined" (structurally invalid token address, or a non-ERC-7984 token whose operator read failed and became a blocker), not just "not approved" (TOK-436).
|
|
99
|
+
- `ConfidentialAirdropClient.claim` + `useClaim` TSDoc: the silent-zero note (insufficient encrypted balance moves an encrypted zero rather than reverting) must not be generalized to a never-funded pool — that claim reverts with `FheHandleNotAllowedError`, and `preflightClaim` cannot detect it because the pool balance is an encrypted `euint64` the SDK cannot read. Previously this warning appeared only on the preflight surface (TOK-434).
|
|
100
|
+
- `useAdminPartialClaim` TSDoc: documents the 6-decimals convention of TokenOps confidential (ERC-7984) tokens (1 token = 1_000_000 base units); the hook shares `PartialClaimArgs` with `usePartialClaim`, and an 18-decimals assumption over-claims by 10^12 (TOK-435).
|
|
101
|
+
- Deleted the dead, never-exported `useAirdropClaim` hook file — it was absent from the `@tokenops/sdk/fhe-airdrop/react` barrel so no consumer could reach it, and its JSDoc described a plaintext-`amount` re-encryption flow the SDK deliberately does not implement (the admin signature commits to a specific handle). The exported `useClaim` is the real claim hook. No API change (TOK-437).
|
|
102
|
+
- Fixed four `@example` blocks on `@tokenops/sdk/fhe` (`mintMockERC7984`, `createMockErc7984Client`, `setOperator`, `revokeOperator`) that referenced the nonexistent `DEPLOYED_ADDRESSES.tokens.testConfidential[...]` path (the registry has no `tokens` key) — two also imported symbols from entry points that don't export them. Examples now use placeholder addresses and every import specifier resolves.
|
|
103
|
+
- `SECURITY.md` operator-deadline guidance corrected: the old text misspelled the constant (`ERC_7984_OPERATOR_MAX_DEADLINE`), recommended the never-expiring deadline for production (the inverse of the `setOperator` TSDoc guidance), and claimed a past-deadline warning that does not exist. It now matches actual behavior: the SDK validates only that the deadline is within uint48 range; use `ERC7984_OPERATOR_MAX_DEADLINE` for dev loops and fixtures, scope deadlines (and `revokeOperator`) in production.
|
|
104
|
+
- `SECURITY.md` gains a "Known Advisories" section: remaining open Dependabot alerts (`axios` via `wagmi` → `@wagmi/connectors` → `@base-org/account` → `@coinbase/cdp-sdk`; `hono` via `porto`) are reachable only through the consumer's own `wagmi` peer tree, not through the SDK's sole runtime dependency (`abitype`); the repo's `pnpm.overrides` protect only this repo's lockfile, so consumer-side `npm audit` findings there are remediated upstream in wagmi.
|
|
105
|
+
|
|
106
|
+
### Security
|
|
107
|
+
|
|
108
|
+
- Development-tree dependency floors raised to clear 20+ Dependabot alerts — brace-expansion CVE-2026-14257 across the 1.x / 2.x / 5.x lines (floors 1.1.16 / 2.1.3 / 5.0.8), postcss GHSA-r28c-9q8g-f849 (pinned 8.5.23), plus axios / fast-uri / hono / js-yaml / linkify-it advisories — and eslint upgraded 9 → 10. **Dev-tree only:** all of these live in `devDependencies` / `pnpm.overrides`; the published package's runtime dependency (`abitype ^1.0.8`) and every peerDependency range are unchanged, so consumer dependency trees are unaffected.
|
|
109
|
+
|
|
110
|
+
## [1.5.1] - 2026-07-23
|
|
111
|
+
|
|
112
|
+
_Republish baseline._ No code or API changes — the package content is identical to 1.5.0 apart from the version number. Published minutes after 1.5.0 as the last release of the same 2026-07-23 per-merge auto-publish run; later that day 1.2.0–1.5.0 were unpublished from npm (burned versions; npm forbids reusing them), leaving **1.5.1 as the first npm-installable version that actually delivers everything from [1.2.0] through [1.5.0]** to consumers. (The repo-only `BOUNTY_DX_TRIAGE.md` added in #56 is not part of the npm tarball.)
|
|
113
|
+
|
|
114
|
+
## [1.5.0] - 2026-07-23 [YANKED]
|
|
115
|
+
|
|
116
|
+
_Published and unpublished from npm the same day; its changes reach consumers via [1.5.1]._
|
|
117
|
+
|
|
118
|
+
### Added
|
|
119
|
+
|
|
120
|
+
- **wagmi v3 peer support** (S7, TOK-70, #57) — the `wagmi` peer dependency range widens from `^2.0.0` to `^2.0.0 || ^3.0.0`; wagmi v2 remains fully supported and no other peer range changes. wagmi v3 renamed `useAccount` to `useConnection`, and the SDK now resolves the installed major's account hook internally, so the three hooks that default to the connected wallet — `useAirdropIsSignatureValid` (`@tokenops/sdk/fhe-airdrop/react`), `useConfidentialBalance` and `useUnderlyingBalance` (`@tokenops/sdk/testnet-faucet/react`) — work under either major with no code change; all hook signatures and return types are unchanged, and `usePublicClient` / `useWalletClient` usage is unaffected. README gains a "wagmi v2 and v3" section documenting dual-major support and how to diagnose `ERESOLVE` errors after a wagmi v3 upgrade (`npm ls wagmi` / `pnpm why wagmi` — the offending peer range usually belongs to another package, not `@tokenops/sdk`).
|
|
121
|
+
|
|
122
|
+
## [1.4.2] - 2026-07-23 [YANKED]
|
|
123
|
+
|
|
124
|
+
_Published and unpublished from npm the same day; its changes reach consumers via [1.5.1]._
|
|
125
|
+
|
|
126
|
+
### Docs
|
|
127
|
+
|
|
128
|
+
- **6-decimals amount convention surfaced at every amount-taking entry point** (S6, TOK-71, #65) — a canonical TSDoc note now ships on each public API that takes a token amount: TokenOps confidential (ERC-7984) tokens use a 6-decimals convention (1 token = 1_000_000 base units), not the 18 decimals typical of ERC-20; amount parameters are base units of the token's actual decimals — for the CTTT test token (6 decimals) `1_000_000n` = 1 CTTT, while the transparent TTT test token uses 18 decimals. Surfaced on the exported `encryptUint64` helpers of all three products (covering `encryptUint64Batch` values), `computeSubtotals`, `ConfidentialVestingManagerClient.{createVesting, batchCreateVesting, partialClaim, adminPartialClaim, withdrawAdmin, withdrawTokenFee}`, `ConfidentialAirdropFactoryClient.{createAndFundConfidentialAirdrop, fundConfidentialAirdrop, createAndFundConfidentialAirdropAndGetAddress}`, `ConfidentialDisperseClient.{calculateFee, preflightDisperse, disperse, withdrawTokenFee}`, and the corresponding amount-taking React hooks in `/fhe-vesting/react`, `/fhe-airdrop/react`, and `/fhe-disperse/react`. Documentation-only; no branded decimals type was introduced and no runtime behavior changed.
|
|
129
|
+
|
|
130
|
+
## [1.4.1] - 2026-07-23 [YANKED]
|
|
131
|
+
|
|
132
|
+
_Published and unpublished from npm the same day; its changes reach consumers via [1.5.1]._
|
|
133
|
+
|
|
134
|
+
### Docs
|
|
135
|
+
|
|
136
|
+
- **Silent-zero transfer warning** (S5, TOK-72, #58) — every public method and React mutation hook that moves confidential tokens or funds a contract now carries a canonical TSDoc warning: ERC-7984 transfers do not revert when the sender's encrypted balance is insufficient — the transfer succeeds and moves an encrypted zero instead (by design: reverting would leak balance information), so the transaction receipt alone cannot tell you whether value actually moved. Applied to `ConfidentialVestingManagerClient.{createVesting, batchCreateVesting, claim, adminClaim, partialClaim, adminPartialClaim}`, `ConfidentialAirdropClient.claim`, `ConfidentialAirdropFactoryClient.{createAndFundConfidentialAirdrop, fundConfidentialAirdrop, createAndFundConfidentialAirdropAndGetAddress}`, `ConfidentialDisperseClient.disperse`, and the corresponding claim / fund / disperse mutation hooks in the three `/react` subpaths. Documentation-only; no runtime behavior changed.
|
|
137
|
+
|
|
138
|
+
## [1.4.0] - 2026-07-23 [YANKED]
|
|
139
|
+
|
|
140
|
+
_Published and unpublished from npm the same day; its changes reach consumers via [1.5.1]._
|
|
141
|
+
|
|
142
|
+
### Added
|
|
143
|
+
|
|
144
|
+
- **`EncryptorInitPhase` and the `onPhase` init-phase callback** (S4, TOK-73, #61) — new exported type on `@tokenops/sdk/fhe`: the union `"initializing" | "downloading-params" | "ready"`, plus an optional `onPhase?: (phase: EncryptorInitPhase) => void` option on both `createSepoliaEncryptorWeb` (`CreateSepoliaEncryptorWebOpts`) and `createSepoliaEncryptor` (`CreateSepoliaEncryptorOptions`). Motivation: the first in-browser encryption downloads several MB of FHE public material with no signal — `onPhase` gives UIs a loading-state hook. Web semantics: `"initializing"` fires during relayer construction, `"downloading-params"` when the Web Worker's lazy init and FHE key/params download actually begin (near-instant on a warm IndexedDB cache), `"ready"` on completion; the last two can re-fire if the relayer re-initializes (e.g. chain switch). Node semantics: `RelayerNode` exposes no status events, so phases bracket the first `encrypt()` call; a failed first attempt re-fires `"downloading-params"` on the next call. Deliberate design points: no fake progress (the Zama SDKs expose no download-progress API), no error phase (init failures surface as rejections from the pending operation), and callback exceptions are swallowed so a throwing UI observer can never break the encryption path.
|
|
145
|
+
|
|
146
|
+
## [1.3.0] - 2026-07-23 [YANKED]
|
|
147
|
+
|
|
148
|
+
_Published and unpublished from npm the same day; its changes reach consumers via [1.5.1]._
|
|
149
|
+
|
|
150
|
+
### Added — create-side preflight for vesting and airdrop (S3, TOK-74, #59)
|
|
151
|
+
|
|
152
|
+
- **`ConfidentialVestingManagerClient.preflightCreateVesting({ params, creator })`** (`@tokenops/sdk/fhe-vesting`) — read-only, opt-in create-side preflight for `createVesting` / `batchCreateVesting`. Returns the new `CreateVestingPreflightReport` (`token`, `hasCreatorRole`, `isOperatorSet`, `ready`, `blockers`, `blockerErrors`) reporting structural param violations (`InvalidArgumentError`, mirroring the contract's `_validateVestingParams` invariants), missing `VESTING_CREATOR_ROLE` (`AccessDeniedError`), and missing ERC-7984 operator approval of the manager on the distribution token (`OperatorNotApprovedError`). `blockerErrors` are typed `TokenOpsSdkError`s index-aligned with the human-readable `blockers` strings — branch on `error.code`. RPC failures propagate rather than producing a false report; paused state is deliberately not a blocker (pause only blocks claims). Documented not-detectable: the creator's encrypted `euint64` balance (an underfunded create silently zeroes amounts via `FHE.select` instead of reverting) and `batchCreateVesting`'s `maxBatchSize()`.
|
|
153
|
+
- **`ConfidentialAirdropFactoryClient.preflightCreateAirdrop(args)`** (`@tokenops/sdk/fhe-airdrop`) — same for `createConfidentialAirdrop` / `createAndFundConfidentialAirdrop`, with new `PreflightCreateAirdropArgs` (`params`, `creator`, optional `userSalt`, optional `funding`) and `CreateAirdropPreflightReport` (`isFactoryOperator`, `gasFee`, `predictedAirdrop?`, `alreadyDeployed?`, `ready`, `blockers`, `blockerErrors`) types. Validates params structurally (non-zero `token` / `admin`, timestamp ordering, `endTimestamp` in the future), reports the resolved per-claim `gasFee` (creator's custom fee when enabled, else `defaultGasFee`), treats a missing factory-operator approval as a blocker only with `funding: true` (informational via `isFactoryOperator` otherwise), and — when `userSalt` is supplied — predicts the CREATE2 clone address and flags an existing deployment as an `AlreadyInitializedError` blocker.
|
|
154
|
+
- **`usePreflightCreateVesting`** (`@tokenops/sdk/fhe-vesting/react`) and **`usePreflightCreateAirdrop`** (`@tokenops/sdk/fhe-airdrop/react`) — TanStack Query wrappers over the two preflights (disabled until `params` and `creator` are set, `staleTime: 0`), with new `UsePreflightCreateVestingArgs` / `UsePreflightCreateAirdropArgs` types; the report types are re-exported from the `/react` subpaths.
|
|
155
|
+
|
|
156
|
+
### Changed
|
|
157
|
+
|
|
158
|
+
- **`OperatorNotApprovedError` gains optional `tokenAddress`** — constructor args and `context` now carry `tokenAddress?: Address` identifying the ERC-7984 token whose operator approval is missing; populated by the new create-side preflights where the token is statically known. Additive and optional — no migration needed.
|
|
159
|
+
|
|
160
|
+
## [1.2.0] - 2026-07-23 [YANKED]
|
|
161
|
+
|
|
162
|
+
_Published and unpublished from npm the same day; its changes reach consumers via [1.5.1]._
|
|
163
|
+
|
|
164
|
+
### Added — ERC-7984 reverts translated into actionable errors (S1, TOK-76, #60)
|
|
165
|
+
|
|
166
|
+
- **`OperatorNotApprovedError`** — new typed error with code `TOKENOPS_OPERATOR_NOT_APPROVED` (new member of the `TokenOpsSdkErrorCode` union), thrown when an ERC-7984 confidential token rejects a TokenOps contract as spender (`ERC7984UnauthorizedSpender`, selector `0x79f2cb38`) because the holder never called `setOperator()` — the common failure in vesting creation, airdrop funding, and disperse token pulls. Carries `context.holder` and `context.spender` decoded from the revert, and a remediation-first message telling you to call `setOperator()` via the `/fhe` operator helpers. Exported from the root entrypoint and from `/fhe`, `/fhe-vesting`, `/fhe-airdrop`, `/fhe-disperse`, `/testnet-faucet`, and each product's `/react` subpath.
|
|
167
|
+
- **`OPERATOR_NOT_APPROVED_REMEDIATION`** — exported string constant (root entrypoint) holding the canonical `OperatorNotApprovedError` message, for surfaces that need the exact remediation copy.
|
|
168
|
+
|
|
169
|
+
### Changed
|
|
170
|
+
|
|
171
|
+
- **ERC-7984 revert decoding across all clients** — `ConfidentialVestingManagerClient`, `ConfidentialVestingFactoryClient`, `ConfidentialAirdropClient`, `ConfidentialAirdropFactoryClient`, `ConfidentialDisperseClient`, and `TestnetFaucetClient` now decode token-originated ERC-7984 standard reverts that appear in none of the vesting / airdrop / disperse product ABIs (the testnet faucet's confidential test-token ABI already declared most of them; 1.2.0 adds the shared decode set and the name-based mapping for every client). Besides `ERC7984UnauthorizedSpender` → `OperatorNotApprovedError`, the sibling errors `ERC7984UnauthorizedCaller`, `ERC7984UnauthorizedUseOfEncryptedAmount`, `ERC7984InvalidReceiver`, `ERC7984InvalidSender`, `ERC7984ZeroBalance`, and `ERC7984InvalidGatewayRequest` now surface as `ContractRevertError` with `context.revertName` / `revertArgs` populated instead of a raw selector hex string (exception: `ERC7984InvalidReceiver` on `TestnetFaucetClient` keeps its pre-existing `InvalidArgumentError` mapping via the faucet product mapper). Works across the simulate, wallet-transport, and raw-RPC error paths; errors declared in the product ABI keep precedence (e.g. `EnforcedPause` still maps to `PausedError`). Migration: code matching raw `0x79f2cb38` data or selector-hex `ContractRevertError` messages should switch to `instanceof OperatorNotApprovedError` / `error.code === "TOKENOPS_OPERATOR_NOT_APPROVED"`, or to `context.revertName`.
|
|
172
|
+
|
|
173
|
+
## [1.1.1] - 2026-06-23
|
|
174
|
+
|
|
175
|
+
Release-pipeline fixes only (npm OIDC trusted publishing via npm >= 11.5.1; `--provenance` dropped because npm rejects it for private packages); no consumer-facing changes relative to [1.1.0] — the published contents are identical apart from the version field and dev-only package.json fields (`devDependencies` / `pnpm.overrides`). Because 1.1.0 never reached npm, **1.1.1 is the first published release of the 1.1.x line** and the version that delivered the testnet-faucet subpath to npm consumers. Dev-tree dependency bumps only (`vitest` 2 → 3, `pnpm.overrides` churn); `dependencies` / `peerDependencies` unchanged.
|
|
176
|
+
|
|
177
|
+
## [1.1.0] - 2026-06-22
|
|
178
|
+
|
|
179
|
+
_Tagged but never published — the release workflow failed on this tag; the content first reached npm in [1.1.1]._
|
|
180
|
+
|
|
181
|
+
### Added
|
|
182
|
+
|
|
183
|
+
- **New `@tokenops/sdk/testnet-faucet` subpath** — a headless, viem-first client for the testnet-only TokenOps test-token pair: `TokenopsTestToken` (TTT, plain 18-decimal ERC-20 with an open mint) and its ERC-7984 confidential wrapper `ConfidentialTokenopsTestToken` (CTTT, 6-decimal, open fully-backed faucet mint). Exports `TestnetFaucetClient` / `createTestnetFaucetClient` (config: `publicClient`, optional `walletClient`, optional CTTT proxy `address` override, `chainId`, `telemetry`); reads `underlyingToken`, `confidentialBalanceOf` (euint64 ciphertext handle), `underlyingBalanceOf`, `rate` (10^12), `decimals` (6), `underlyingDecimals` (18), `inferredTotalSupply`, `maxTotalSupply`, `getMetadata`; writes `mintConfidential` (returns `{ hash, to, amount, underlyingMinted, handle }` decoded from the `ConfidentialMint` event) and `mintUnderlying` (returns `{ hash, to, amount }`). Faucet mint amounts are **public plaintext** (`uint64` in CTTT 6-decimal units / `uint256` in TTT 18-decimal units) — no encryptor and no `@zama-fhe/sdk` peer is needed anywhere in the faucet subpaths. The backing TTT is never supplied by the consumer: it resolves from the registry for the canonical CTTT, or from a custom CTTT's own authoritative `underlying()` getter.
|
|
184
|
+
- **Testnet-only chain guard** — `TESTNET_FAUCET_SUPPORTED_CHAIN_IDS` (Sepolia `11155111` and local dev chain `31337`), `isTestnetFaucetChainId`, and `assertTestnetFaucetChain`. `TestnetFaucetClient` throws `UnsupportedChainError` at construction on any other chain — the faucet can never run on mainnet.
|
|
185
|
+
- **New `@tokenops/sdk/testnet-faucet/react` subpath** — wagmi + TanStack Query hooks mirroring every client method: reads `useConfidentialBalance`, `useUnderlyingBalance`, `useFaucetRate`, `useFaucetDecimals`, `useUnderlyingDecimals`, `useUnderlyingTokenAddress`, `useInferredTotalSupply`, `useMaxTotalSupply`, `useFaucetMetadata`; mutations `useMintConfidential`, `useMintUnderlying`. All hooks accept `BaseHookOptions` (`{ address?, chainId? }`); query keys follow `["tokenops-sdk", "testnet-faucet", method, chainId, address, ...args]` with exported constants `TESTNET_FAUCET_KEY` / `TESTNET_FAUCET_NAMESPACE`. On an unsupported chain the hooks never construct a client during render, and mutations surface the typed `UnsupportedChainError` / `DeploymentAddressUnavailableError` rather than a generic `MissingClientError`. Mutations do not auto-invalidate read queries — invalidate `["tokenops-sdk", "testnet-faucet"]` yourself. Requires only the `wagmi` and `@tanstack/react-query` peers, not `@zama-fhe/react-sdk`.
|
|
186
|
+
- **New error `FaucetSupplyExhaustedError`** (code `TOKENOPS_FAUCET_SUPPLY_EXHAUSTED`, new member of the `TokenOpsSdkErrorCode` union) — thrown when the confidential wrapper's backing reaches `maxTotalSupply` (`type(uint64).max`), mapped from the on-chain `ERC7984TotalSupplyOverflow` revert. Both faucet subpaths also re-export the full canonical TokenOps error vocabulary for parity with the other product subpaths.
|
|
187
|
+
- **`DEPLOYED_ADDRESSES.testnetFaucet` registry and address accessors** — Sepolia deployments for TTT (`0x37a057Fa8C201a7bf8caF32dfa9A0878f577D92b`) and the CTTT UUPS proxy (`0x258F9D60dc023870e4E3109c894D834D5377361a`), with new functions `getTestTokenAddress`, `requireTestTokenAddress`, `getConfidentialTestTokenAddress`, `requireConfidentialTestTokenAddress` on the root `@tokenops/sdk` and re-exported from `/testnet-faucet`. ABIs `tokenopsTestTokenAbi` and `confidentialTokenopsTestTokenAbi` are exported too.
|
|
188
|
+
|
|
189
|
+
### Docs
|
|
190
|
+
|
|
191
|
+
- README: new "Quickstart — testnet faucet" sections (headless and React hooks) and subpath-table entries for `@tokenops/sdk/testnet-faucet` and `@tokenops/sdk/testnet-faucet/react`.
|
|
192
|
+
- TSDoc cleanup in published typings: internal audit-pipeline codenames removed from doc comments across 23 modules, so the `.d.ts` documentation shipped in the package no longer references internal process artifacts.
|
|
193
|
+
|
|
8
194
|
## [1.0.0] - 2026-05-27
|
|
9
195
|
|
|
10
196
|
### Changed — factory create methods now block on receipt before returning
|
|
@@ -202,6 +388,16 @@ The package has not been published to npm yet (`npm view @tokenops/sdk` returns
|
|
|
202
388
|
- Sepolia factory address wired in `src/core/addresses.ts` (`0xA87701CE9A52D43681600583a99c85b50DbE3150`).
|
|
203
389
|
- Three-surface test rig: unit, local FHEVM (anvil + forge-fhevm host contracts + `@fhevm/mock-utils`), Sepolia smoke.
|
|
204
390
|
|
|
205
|
-
[
|
|
206
|
-
[1.
|
|
391
|
+
[unreleased]: https://github.com/VestingLabs/tokenops-sdk/compare/v1.5.1...HEAD
|
|
392
|
+
[1.5.1]: https://github.com/VestingLabs/tokenops-sdk/compare/v1.5.0...v1.5.1
|
|
393
|
+
[1.5.0]: https://github.com/VestingLabs/tokenops-sdk/compare/v1.4.2...v1.5.0
|
|
394
|
+
[1.4.2]: https://github.com/VestingLabs/tokenops-sdk/compare/v1.4.1...v1.4.2
|
|
395
|
+
[1.4.1]: https://github.com/VestingLabs/tokenops-sdk/compare/v1.4.0...v1.4.1
|
|
396
|
+
[1.4.0]: https://github.com/VestingLabs/tokenops-sdk/compare/v1.3.0...v1.4.0
|
|
397
|
+
[1.3.0]: https://github.com/VestingLabs/tokenops-sdk/compare/v1.2.0...v1.3.0
|
|
398
|
+
[1.2.0]: https://github.com/VestingLabs/tokenops-sdk/compare/v1.1.1...v1.2.0
|
|
399
|
+
[1.1.1]: https://github.com/VestingLabs/tokenops-sdk/compare/v1.1.0...v1.1.1
|
|
400
|
+
[1.1.0]: https://github.com/VestingLabs/tokenops-sdk/compare/efda6cd...v1.1.0
|
|
401
|
+
[1.0.0]: https://github.com/VestingLabs/tokenops-sdk/commit/efda6cd
|
|
402
|
+
[1.0.0-rc.1]: https://github.com/VestingLabs/tokenops-sdk/releases/tag/v1.0.0-rc.1
|
|
207
403
|
[1.0.0-alpha.0]: https://github.com/VestingLabs/tokenops-sdk/releases/tag/v1.0.0-alpha.0
|
package/CONTRIBUTING.md
CHANGED
|
@@ -108,6 +108,8 @@ Pattern: `<type>(<scope>): <imperative description>`. Scope is optional; use the
|
|
|
108
108
|
|
|
109
109
|
## Claude Code Setup
|
|
110
110
|
|
|
111
|
-
The `claude-setup/` directory contains a `settings.json` and skill definitions that configure Claude Code for this repository.
|
|
111
|
+
The `claude-setup/` directory contains a `settings.json` and skill definitions (jsdoc, tanstack-best-practices, fhevm-security) that configure Claude Code for this repository. Run `pnpm setup:claude` to install them into your local `.claude/`. It copies on a first run and merges on later ones, so re-running after a pull picks up repo changes without discarding your own settings.
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
`.claude/` is gitignored, so adoption is opt-in and nothing you put there is shared. `.codex/` and `.agents/` are ignored on the same basis - this repo does not assume which agent you use.
|
|
114
|
+
|
|
115
|
+
See the `claude-setup/` directory and Anthropic's [Claude Code plugin model](https://docs.claude.ai/en/docs/claude-code) for details.
|