2.0 RC docsView 1.x docs
Vesting 2.0 · @tokenops/sdk/fhe-vesting

Confidential vesting on the 2.0 line

The same vesting contracts as 1.6, on the Zama 3.6 encryptor, with receipt-free creates and gas headroom.

v2.0.0-rc.1 release candidate
The API is frozen and later candidates carry fixes only, except the receipt-free and Safe create surface of /fhe-airdrop, which is @beta. Published on the next dist-tag; latest stays on 1.6.0 until 2.0.0.

Where to start

Deployment

The vesting factory is deployed on Sepolia only, at the same address as on 1.6. The clients resolve it from DEPLOYED_ADDRESSES.fheVesting.confidentialVestingFactory by chain id, so you do not pass address on Sepolia. Each operator then deploys a per-user manager clone through it.

ChainconfidentialVestingFactory
Sepolia (11155111)0x059d6Bb8ff9a13E794fe416d4757d7310CdC69ab
Ethereum mainnet (1)null - registry-not-deployed

Breaking changes since 1.6

Most of these fail at typecheck. The holder rename is a deprecation, and the telemetry event is a runtime removal. The vesting contracts did not change, so an existing manager clone keeps working; only your call sites move.

  • Zama SDK peers move to ~3.6.0

    The encryptor is a ZamaSDK: pass encryptor: () => zamaSDK in React, or build one with createSepoliaEncryptor in Node. Client signatures and the encryptUint64 / encryptUint64Batch outputs are unchanged.

    Encryptors
  • Encrypted views keep only their useAccess* names

    Read an encrypted amount with useAccessVestedAmount, useAccessClaimableAmount, useAccessTotalAllocation and useAccessSettledAmount (args UseAccess*Args). The older aliases, deprecated in 1.6, are removed; the functions are the same.

    From 1.x
  • CreateVestingPreflightReport reports blockerErrors only

    The string[] field is gone. preflightCreateVesting and usePreflightCreateVesting return blockerErrors: TokenOpsSdkError[]; branch on error.code or render error.message. ready is unchanged.

    Types
  • PartialClaimArgs is discriminated by feeType

    Like ClaimArgs: { feeType: FeeType.Gas, value } on a gas-fee manager, { feeType: FeeType.DistributionToken } without value otherwise. A mismatched msg.value now fails at typecheck for partialClaim, adminPartialClaim, usePartialClaim and useAdminPartialClaim.

    Claim flow
  • Create and split hooks resolve Mined | Pending

    useCreateManager, useCreateManagerAndGetAddress and useSplitVesting accept waitForReceipt, so data.manager / data.newVestingId type as X | undefined. Narrow with if (data.pending) return;. Headless calls that never pass the option keep the mined type.

    Receipt-free writes
  • PredictManagerArgs moves to /fhe-vesting/advanced/react

    It is no longer exported from /fhe-vesting/react. Import it from /fhe-vesting/advanced or /fhe-vesting/advanced/react, next to predictManagerAddress / usePredictManagerAddress.

    Factory client
  • Role hooks name the grantee holder

    useHasRole({ role, holder }) and mutate({ role, holder }) on useGrantRole / useRevokeRole. account (read) and accountTarget (write) still compile, are deprecated, and cannot be combined with holder.

    Roles
  • The fhe-vesting.react.hook.fired telemetry event is gone

    Its hookName carried a family label, not the hook. The headless fhe-vesting.client.init event and the write spans are unchanged; drop any dashboard keyed on the removed event.

    Telemetry

Added

  • Gas headroom on every write, plus per-call gas

    Each write estimates gas and pads it by DEFAULT_GAS_HEADROOM_PERCENT (25) unless the client or hook sets gasHeadroomPercent. Every argument-object write takes gas (GasOverride), sent as is. Hooks over positional setters use the client headroom.

    Gas headroom
  • Receipt-free createManager and splitVesting

    waitForReceipt: false on createManager, createManagerAndGetAddress and splitVesting returns on submission with PendingCreateManagerResult / PendingSplitVestingResult (pending: true), for Safe and multisig signers. Read the address or id from the executed transaction's logs.

    Receipt-free writes
  • query on every read hook

    Read hooks take query (ReadHookQueryOptions): TanStack options minus queryKey / queryFn. query.enabled can turn a ready query off, never an unready one on. Immutable manager reads now default to staleTime: Infinity.

    Query options
  • Operator helpers on /fhe-vesting

    setOperator, revokeOperator, ERC7984_OPERATOR_MAX_DEADLINE, SetOperatorArgs and RevokeOperatorArgs are exported from the vesting subpath, as on /fhe-disperse and /fhe-airdrop. The React subpath re-exports useIsOperator and useEnsureOperator.

    Operators
  • FHE_VESTING_KEY and FHE_VESTING_NAMESPACE

    The query-key prefix every vesting hook uses, exported from /fhe-vesting/react so you can invalidate the whole subpath without hand-typing strings.

    Hooks
  • MAX_EUINT64_PER_INPUT_PROOF (32)

    The most euint64 values one input proof carries. batchCreateVesting refuses more items with InvalidArgumentError before encrypting; the manager's on-chain maxBatchSize still applies.

    Manager client
  • Telemetry spans on every manager write

    Claims, transfers, disclosures, withdrawals, role writes and the encrypted views are each bracketed with a named span on ConfidentialVestingManagerClient, not only some admin writes.

    Telemetry
  • Error classes on the React subpath

    /fhe-vesting/react re-exports the error palette, including TokenOpsValidationError, the vesting errors and the wallet errors, so a component can instanceof without a second import path.

    Errors

Changed and fixed

  • WithdrawAdminArgs / WithdrawTokenFeeArgs unions

    withdrawAdmin and withdrawTokenFee take exactly one of amount or encryptedInput. useWithdrawAdmin and useWithdrawTokenFee now accept encryptedInput alone (it always threw before), a lazy per-call encryptor, and gas.

  • batchRevokeVesting sorts its ids

    The contract requires strictly ascending ids. The SDK now sorts a copy, so pass them in selection order; duplicates throw InvalidArgumentError instead of reverting VestingIdsNotStrictlyAsc.

  • Hooks return resolutionError instead of throwing in render

    A client constructor that rejects its config (a malformed address, a bad gasHeadroomPercent) no longer crashes the component: read hooks stay disabled and mutation hooks throw it when called.

  • Mainnet is a known chain without a deployment

    The vesting factory registry records mainnet as null. A registry miss reports DeploymentAddressUnavailableError with context.reason registry-not-deployed for that entry and registry-unknown-chain for a chain with no entry.

    Deployments
  • preflightClaim reports a short wallet as InsufficientBalanceError

    A claimant whose ETH balance is below the gas fee gets InsufficientBalanceError (balanceKind: "eth"), not InsufficientFeeError. Code branching on TOKENOPS_INSUFFICIENT_FEE for this blocker needs the new code.

    Errors
  • Receipt and wallet checks

    createManager throws ReceiptEventNotFoundError / ReceiptEventAmbiguousError for a missing or repeated ManagerCreated event. Every write refuses a wallet on a different chain than the public client with WalletChainMismatchError, before estimating.

  • Batch disclosure matches handles correctly

    batchDiscloseToParty and adminBatchDiscloseToParty pair each AmountDisclosed event with its input by vestingId and disclosure type, so a vestingId repeated with different types gets the right handle at each position.

  • Errors stop leaking confidential inputs

    Split errors no longer repeat the encrypted numerator, and encryptUint64 / encryptUint64Batch range errors no longer copy the amount into context.value, which reaches the telemetry sink. MissingEncryptorError names the method you called.

Reference

Generated or derived from v2.0.0-rc.1 of the package: ABIs, events and hooks come from the installed artifact.