The shape#
DEPLOYED_ADDRESSES is a nested object indexed by product → contract → chainId. Sepolia (11155111) and mainnet (1) are the two chains with entries. Anvil (31337) is intentionally absent — local chains get their addresses from .cache/local-deploys.json written by pnpm fhevm:deploy in the SDK monorepo.
import {
DEPLOYED_ADDRESSES,
getFheVestingFactoryAddress,
} from "@tokenops/sdk";
import { sepolia } from "viem/chains";
const addr = getFheVestingFactoryAddress(sepolia.id);
// → "0xA87701CE9A52D43681600583a99c85b50DbE3150"
// Or read the raw map:
const raw = DEPLOYED_ADDRESSES.fheVesting.confidentialVestingFactory[sepolia.id];The matrix#
fhe-vesting: Sepolia live. Mainnet pending audit close + Zama KMS readiness.
fhe-airdrop: Sepolia live. Mainnet pending audit close + Zama KMS readiness.
fhe-disperse: Sepolia and Ethereum mainnet both live. Lower audit surface; the disperse singleton went mainnet first.
Always check Resources for the canonical list — it reads from this same export at build time, so the page is never out of date with the SDK.
Accessors vs raw map#
The typed accessors (getFheVestingFactoryAddress,getFheAirdropFactoryAddress,getFheDisperseSingletonAddress) collapse the "explicitly null" and "missing key" cases to undefined. Use them in product code; reach into the raw map only if you need to distinguish "known chain, not deployed yet" from "unknown chain."
Custom RPCs#
The SDK takes a viem PublicClient and WalletClient as input. You configure RPC at the viem layer; the SDK is RPC-agnostic. Public RPCs work; Alchemy / Infura / your own works the same.