fhe
Interfaces
CreateMockEncryptorOptions
Defined in: fhe/mock-encryptor.ts:55
Configuration for createMockEncryptor. Most consumers only need
rpcUrl; everything else has deterministic defaults that match what
pnpm fhevm:up deploys.
Properties
| Property | Type | Description | Defined in |
|---|---|---|---|
rpcUrl? | ... | ... | JSON-RPC endpoint of a local Anvil node with FHEVM host contracts already deployed (i.e. pnpm fhevm:up succeeded). Defaults to http://127.0.0.1:8545. | fhe/mock-encryptor.ts:61 |
chainId? | ... | ... | Chain id of the local node. Defaults to 31337 (forge-fhevm default). Override only if you ran pnpm fhevm:up with a non-default --chain-id. | fhe/mock-encryptor.ts:66 |
hostAddresses? | ... | ... | Mock-utils host-contract addresses. Defaults to the Zama HardhatConfig deterministic deployment forge-fhevm produces. Override if you brought the FHEVM host contracts up some other way and they landed at different addresses. | fhe/mock-encryptor.ts:73 |
coprocessorSignerPrivateKey? | ... | ... | Override the coprocessor signer private key. Defaults to the deterministic forge-fhevm signer; you only need this if you deployed the host contracts with a custom KMS / coprocessor signer set. | fhe/mock-encryptor.ts:87 |
MockEncryptor
Defined in: fhe/mock-encryptor.ts:92
Returned by createMockEncryptor. Carries the underlying
MockFhevmInstance so consumers who need user-decrypt can reach it.
Extends
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
instance | readonly | unknown | The underlying MockFhevmInstance. Use this for userDecrypt flows that the SDK's structural Encryptor interface doesn't expose. Process-scoped: handles produced by one instance can only be decrypted by that same instance (the cleartext db lives in memory). | fhe/mock-encryptor.ts:99 |
chainId | readonly | number | Local chain id this encryptor is bound to. | fhe/mock-encryptor.ts:101 |
Methods
encrypt()
encrypt(params): Promise<...>;
Defined in: fhe-vesting/encryption.ts:42
Parameters
| Parameter | Type |
|---|---|
params | { values: ...; contractAddress: ...; userAddress: ...; } |
params.values | ... |
params.contractAddress | ... |
params.userAddress | ... |
Returns
Promise<...>
Inherited from
MintMockERC7984Args
Defined in: fhe/mock-erc7984.ts:56
Arguments for mintMockERC7984. Mirrors the shape of import("./operators.js").SetOperatorArgs so consumers wiring both helpers in sequence reuse the same client / account references.
Properties
| Property | Type | Description | Defined in |
|---|---|---|---|
publicClient | { } | Read-only viem client for receipt waiting. | fhe/mock-erc7984.ts:58 |
walletClient | { } | Wallet client used to send the mint call. | fhe/mock-erc7984.ts:60 |
token | `0x${(...)}` | MockERC7984Token contract address. | fhe/mock-erc7984.ts:62 |
to | `0x${(...)}` | Recipient of the freshly-minted ciphertext balance. | fhe/mock-erc7984.ts:64 |
amount | bigint | Amount to mint, base units. uint64 upper bound (2**64 - 1 ≈ 1.8e+19) is the on-chain ceiling; the helper rejects bigints above that BEFORE viem encodes them so the revert message is the SDK's, not viem's. | fhe/mock-erc7984.ts:70 |
account? | ... | ... | ... | Account paying the mint. Same `Account | Addressshape as import("./operators.js").SetOperatorArgs.account — passing the fullAccount object preserves the local-signing path (eth_sendRawTransaction); passing only an Addressfalls back toeth_sendTransaction` which most public RPCs reject. |
waitForReceipt? | ... | ... | ... | If true (default), waits for the transaction to be mined before returning. Set to false for fire-and-forget flows where the caller waits separately. | fhe/mock-erc7984.ts:84 |
telemetry? | ... | ... | Optional telemetry sink — span emits as fhe.mintMockERC7984. | fhe/mock-erc7984.ts:86 |
MintMockERC7984Result
Defined in: fhe/mock-erc7984.ts:92
Result of mintMockERC7984: the tx hash plus the mined block
number (or 0n when waitForReceipt: false). Shape mirrors the docs-site
stopgap's return so the migration is a drop-in.
Properties
| Property | Type | Defined in |
|---|---|---|
hash | `0x${(...)}` | fhe/mock-erc7984.ts:93 |
blockNumber | bigint | fhe/mock-erc7984.ts:94 |
CreateMockErc7984ClientArgs
Defined in: fhe/mock-erc7984.ts:197
Args for createMockErc7984Client.
Properties
| Property | Type | Description | Defined in |
|---|---|---|---|
publicClient | { } | - | fhe/mock-erc7984.ts:198 |
walletClient | { } | - | fhe/mock-erc7984.ts:199 |
address | `0x${(...)}` | - | fhe/mock-erc7984.ts:200 |
telemetry? | ... | ... | Optional telemetry forwarded to every method call. | fhe/mock-erc7984.ts:202 |
MockErc7984Client
Defined in: fhe/mock-erc7984.ts:208
Small client returned by createMockErc7984Client. Mirrors the
broader SDK client shape ({ address, mint }) so consumers wiring multiple
helpers can stash the client once and reuse the bound address.
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
address | readonly | `0x${(...)}` | fhe/mock-erc7984.ts:209 |
Methods
mint()
mint(args): Promise<...>;
Defined in: fhe/mock-erc7984.ts:216
Mint to to. The bound address is forwarded as the token — pass
everything else inline. Same MintMockERC7984Args shape minus the
token, publicClient, walletClient, telemetry fields the client
already owns.
Parameters
| Parameter | Type |
|---|---|
args | Omit<..., ...> |
Returns
Promise<...>
SetOperatorArgs
Defined in: fhe/operators.ts:71
Properties
| Property | Type | Description | Defined in |
|---|---|---|---|
publicClient | { } | Read-only viem client for receipt waiting. | fhe/operators.ts:73 |
walletClient | { } | Wallet client used to send the setOperator call. | fhe/operators.ts:75 |
account? | ... | ... | ... | Account that owns the tokens being authorized. Accepts either a full viem Account object (e.g. from privateKeyToAccount) or an Address string. Mirrors CreateVestingArgsCommon.account and viem's own writeContract flexibility. Fallback hierarchy when this arg is omitted: 1. walletClient.account — the full account object the wallet was built with (preferred — viem signs locally → eth_sendRawTransaction). 2. throws TokenOpsContractError — no signer available. **Why `Account | Addressand not justAddress:** viem's writeContractcallseth_sendTransaction(custodial-wallet path, rejected by Alchemy / Infura / public RPCs) when handed a string address, andeth_sendRawTransaction(local-signing path) when handed anAccountobject with asignTransactionmethod. Pass the full object you got fromprivateKeyToAccount` to get local signing; pass an address only when the wallet has multiple custodial accounts and you want to pick one by name. |
token | `0x${(...)}` | ERC-7984 token contract address. | fhe/operators.ts:102 |
spender | `0x${(...)}` | Address being authorized to pull tokens — typically a manager clone (/fhe-vesting), an airdrop clone (/fhe-airdrop), or the disperse singleton (/fhe-disperse). | fhe/operators.ts:108 |
deadline? | ... | ... | uint48 unix timestamp after which the operator authorization expires. Defaults to ERC7984_OPERATOR_MAX_DEADLINE ("forever" within uint48). | fhe/operators.ts:114 |
waitForReceipt? | ... | ... | ... | If true (default), waits for the transaction to be mined before returning. Set to false for fire-and-forget flows where the caller waits separately. | fhe/operators.ts:120 |
telemetry? | ... | ... | Optional telemetry sink — span emits as fhe.setOperator. | fhe/operators.ts:122 |
RevokeOperatorArgs
Defined in: fhe/operators.ts:246
Arguments for revokeOperator. Identical to SetOperatorArgs
minus the deadline field — revoke is a fixed until=0 call that cannot
accept a non-zero deadline (the ERC-7984 contract treats 0 as the revoke
convention; any non-zero until would be a re-grant, not a revoke).
Properties
| Property | Type | Description | Defined in |
|---|---|---|---|
publicClient | { } | Read-only viem client for receipt waiting. | fhe/operators.ts:248 |
walletClient | { } | Wallet client used to send the setOperator(..., 0) call. | fhe/operators.ts:250 |
account? | ... | ... | ... | Account that owns the tokens. Same fallback hierarchy as SetOperatorArgs — preserves the Account object when present so viem signs locally via eth_sendRawTransaction rather than the custodial eth_sendTransaction path that public RPCs reject. | fhe/operators.ts:257 |
token | `0x${(...)}` | ERC-7984 token contract address. | fhe/operators.ts:259 |
spender | `0x${(...)}` | Address whose operator authorization should be revoked — typically a stale manager clone (/fhe-vesting), a closed airdrop clone (/fhe-airdrop), or a singleton no longer in use (/fhe-disperse). | fhe/operators.ts:265 |
waitForReceipt? | ... | ... | ... | If true (default), waits for the transaction to be mined before returning. Set to false for fire-and-forget flows where the caller waits separately. | fhe/operators.ts:271 |
telemetry? | ... | ... | Optional telemetry sink — span emits as fhe.revokeOperator. | fhe/operators.ts:273 |
ScaledRatio
Defined in: fhe/scale-ratio.ts:68
Properties
| Property | Type | Defined in |
|---|---|---|
numerator | bigint | fhe/scale-ratio.ts:69 |
denominator | bigint | fhe/scale-ratio.ts:70 |
ScaleRatioArgs
Defined in: fhe/scale-ratio.ts:73
Properties
| Property | Type | Description | Defined in |
|---|---|---|---|
numerator | bigint | - | fhe/scale-ratio.ts:74 |
denominator | bigint | - | fhe/scale-ratio.ts:75 |
minDenominator? | ... | ... | Target denominator for the scaled output. Defaults to FHE_SPLIT_DENOMINATOR (90_090_000) — the privacy-preserving constant every confidential split must agree on. Override only for non-split contract surfaces that have a different precision floor. | fhe/scale-ratio.ts:82 |
width? | ... | ... | Bit-width the scaled values are validated against. Defaults to "uint128". Pass "uint64" for confidential split paths whose encrypted numerator goes through encryptUint64, so the bound the helper reports matches the bound the encryption call would enforce. | fhe/scale-ratio.ts:89 |
CreateSepoliaEncryptorWebOpts
Defined in: fhe/sepolia-encryptor-web.ts:62
Configuration for createSepoliaEncryptorWeb. Minimal by design:
the browser path doesn't expose worker pool sizing or storage knobs (the
Web Worker is single-threaded by default, and RelayerWeb already
defaults to IndexedDBStorage for FHE artifact caching).
Properties
| Property | Type | Description | Defined in |
|---|---|---|---|
publicClient | { } | Viem PublicClient — used only to resolve the chain id for the encryptor's getChainId callback. The encryptor itself never reads from the chain; encrypted handles + proofs are produced locally and the relayer is queried over HTTP. | fhe/sepolia-encryptor-web.ts:67 |
walletClient | { } | Viem WalletClient — kept on the options object for symmetry with the Node helper, even though RelayerWeb doesn't need it. Consumers compose the encryptor with the same client they pass to the SDK's vesting / disperse / airdrop factories. | fhe/sepolia-encryptor-web.ts:72 |
relayerUrl? | ... | ... | Override the Zama relayer URL. Defaults to Zama's public Sepolia testnet relayer (https://relayer.testnet.zama.org/v2) baked into @zama-fhe/sdk's SepoliaConfig. Set this only for private relayer forks (rare; Zama-internal). | fhe/sepolia-encryptor-web.ts:79 |
chainId? | ... | ... | Override the chain id this encryptor binds to. Defaults to SEPOLIA_CHAIN_ID. Pass MAINNET_CHAIN_ID for the mainnet relayer once Zama enables it; pre-mainnet this stays Sepolia. | fhe/sepolia-encryptor-web.ts:85 |
logger? | ... | ... | Optional logger for tracing worker lifecycle and request timing. Same shape as the Node helper. Mirrored here for surface parity — when a consumer migrates a server-side script to a browser app, the logger config moves over unchanged. Any missing methods are filled with no-op stubs before reaching the underlying Zama relayer (see createSepoliaEncryptor for the background on why). | fhe/sepolia-encryptor-web.ts:96 |
SepoliaEncryptorWeb
Defined in: fhe/sepolia-encryptor-web.ts:106
Returned by createSepoliaEncryptorWeb. Same structural
Encryptor contract as the Node version, plus the underlying
RelayerWeb for callers that need userDecrypt / publicDecrypt
(which the structural Encryptor interface doesn't surface) or
explicit terminate() on page unload.
Extends
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
instance | readonly | unknown | The underlying RelayerWeb. Typed unknown to avoid leaking the optional @zama-fhe/sdk peer dep into the SDK's public types. Cast to import("@zama-fhe/sdk").RelayerWeb at the use site. | fhe/sepolia-encryptor-web.ts:112 |
chainId | readonly | number | Chain id this encryptor is bound to (11155111 for Sepolia). | fhe/sepolia-encryptor-web.ts:114 |
Methods
encrypt()
encrypt(params): Promise<...>;
Defined in: fhe-vesting/encryption.ts:42
Parameters
| Parameter | Type |
|---|---|
params | { values: ...; contractAddress: ...; userAddress: ...; } |
params.values | ... |
params.contractAddress | ... |
params.userAddress | ... |
Returns
Promise<...>
Inherited from
terminate()
terminate(): void;
Defined in: fhe/sepolia-encryptor-web.ts:121
Tear down the Web Worker. The browser path doesn't require this — the worker is GC'd when the page unloads — but long-lived SPAs that swap encryptors (chain switch, user logout) should call it to free the WASM heap explicitly.
Returns
void
SepoliaEncryptorLogger
Defined in: fhe/sepolia-encryptor.ts:46
Subset of @zama-fhe/sdk/node's GenericLogger we accept. Mirrored
structurally so consumers don't need to import the optional peer dep just
to type-narrow a logger arg.
Properties
| Property | Type | Defined in |
|---|---|---|
debug? | ... | ... | fhe/sepolia-encryptor.ts:47 |
info? | ... | ... | fhe/sepolia-encryptor.ts:48 |
warn? | ... | ... | fhe/sepolia-encryptor.ts:49 |
error? | ... | ... | fhe/sepolia-encryptor.ts:50 |
SepoliaEncryptorStorage
Defined in: fhe/sepolia-encryptor.ts:58
Subset of @zama-fhe/sdk/node's GenericStorage we accept. Mirrored
structurally for the same reason as SepoliaEncryptorLogger. The
RelayerNode caches FHE public-key + params here across sessions; default is
an in-process memory map. Pass a redis-backed implementation for
cross-restart persistence in long-lived Node servers.
Methods
get()
get<T>(key): Promise<...>;
Defined in: fhe/sepolia-encryptor.ts:59
Type Parameters
| Type Parameter | Default type |
|---|---|
T | unknown |
Parameters
| Parameter | Type |
|---|---|
key | string |
Returns
Promise<...>
set()
set<T>(key, value): Promise<...>;
Defined in: fhe/sepolia-encryptor.ts:60
Type Parameters
| Type Parameter | Default type |
|---|---|
T | unknown |
Parameters
| Parameter | Type |
|---|---|
key | string |
value | T |
Returns
Promise<...>
delete()
delete(key): Promise<...>;
Defined in: fhe/sepolia-encryptor.ts:61
Parameters
| Parameter | Type |
|---|---|
key | string |
Returns
Promise<...>
CreateSepoliaEncryptorOptions
Defined in: fhe/sepolia-encryptor.ts:68
Configuration for createSepoliaEncryptor. All fields are optional; defaults match the Zama public Sepolia relayer.
Properties
| Property | Type | Description | Defined in |
|---|---|---|---|
relayerUrl? | ... | ... | Override the Zama relayer URL. Defaults to Zama's public Sepolia testnet relayer (https://relayer.testnet.zama.org/v2) baked into @zama-fhe/sdk/node's SepoliaConfig. Set this only when running against a private relayer fork (rare; usually only Zama internal). | fhe/sepolia-encryptor.ts:75 |
chainId? | ... | ... | Override the chain id this encryptor binds to. Defaults to SEPOLIA_CHAIN_ID. Pass MAINNET_CHAIN_ID for the mainnet relayer once Zama enables it; pre-mainnet this stays Sepolia. | fhe/sepolia-encryptor.ts:81 |
poolSize? | ... | ... | Worker pool size. Defaults to min(os.availableParallelism(), 4) inside @zama-fhe/sdk. Each worker loads ~50–100 MB of WASM — decrease to 1–2 on memory-constrained hosts, increase to match CPU cores for high-throughput batch encryption. | fhe/sepolia-encryptor.ts:88 |
logger? | ... | ... | Optional logger for tracing worker lifecycle and request timing. Useful during onboarding to see when the relayer round-trips happen; remove for production to avoid noisy logs. | fhe/sepolia-encryptor.ts:94 |
fheArtifactStorage? | ... | ... | Persistent storage for FHE public key + params cache. Defaults to an in-process memory map (lost on restart). Pass a redis-backed GenericStorage for cross-restart persistence in long-lived servers — the public params are several MB; re-fetching on every restart adds seconds of cold start. | fhe/sepolia-encryptor.ts:102 |
fheArtifactCacheTTL? | ... | ... | Cache TTL in seconds for FHE public material. Default: 86400 (24h). Set to 0 to revalidate on every operation (rare; only useful for tests that want to exercise the fetch path). | fhe/sepolia-encryptor.ts:108 |
SepoliaEncryptor
Defined in: fhe/sepolia-encryptor.ts:116
Returned by createSepoliaEncryptor. Carries the underlying
RelayerNode so consumers who need user-decrypt or worker lifecycle
control can reach it, plus the chain id this encryptor is bound to.
Extends
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
instance | readonly | unknown | The underlying RelayerNode. Use this for userDecrypt / publicDecrypt flows the SDK's structural Encryptor interface doesn't surface. Typed unknown to avoid importing the optional @zama-fhe/sdk peer dep into the SDK's public types. | fhe/sepolia-encryptor.ts:123 |
chainId | readonly | number | Chain id this encryptor is bound to (11155111 for Sepolia). | fhe/sepolia-encryptor.ts:125 |
Methods
encrypt()
encrypt(params): Promise<...>;
Defined in: fhe-vesting/encryption.ts:42
Parameters
| Parameter | Type |
|---|---|
params | { values: ...; contractAddress: ...; userAddress: ...; } |
params.values | ... |
params.contractAddress | ... |
params.userAddress | ... |
Returns
Promise<...>
Inherited from
terminate()
terminate(): void;
Defined in: fhe/sepolia-encryptor.ts:133
Tear down the underlying worker thread pool. Must be called before
process.exit() (or at the end of any Node script) — RelayerNode owns
node:worker_threads that keep the event loop alive. Forgetting to call
terminate() is the #1 reason Sepolia scripts hang after main()
resolves.
Returns
void
EncryptedInput
Defined in: fhe/types.ts:18
A single externalEuint64 ciphertext: the on-chain handle plus the KMS
input proof that authorises it. Produced by encryptUint64 and consumed
by every @tokenops/sdk write method that takes an encrypted amount.
The handle and proof are bound to the (contractAddress, userAddress)
pair passed at encryption time and cannot be replayed against a different
contract or sender. Field names match the on-chain calldata layout
(bytes32 handle, bytes inputProof) so the value spreads directly into
contract calls.
The current SDK only produces uint64 ciphertexts. If a future version
adds encryption helpers for other widths (e.g. encryptUint128), this
type may be specialised; existing uint64 usage will keep type-checking.
Properties
| Property | Type | Defined in |
|---|---|---|
handle | `0x${(...)}` | fhe/types.ts:19 |
inputProof | `0x${(...)}` | fhe/types.ts:20 |
EncryptedInputs
Defined in: fhe/types.ts:30
N externalEuint64 ciphertexts sharing a single KMS input proof. One
proof per batch is cheaper than N independent proofs and is the shape the
encryptor returns from a batched encrypt({ values: [...] }) call.
handles[i] corresponds to the i-th plaintext value passed in.
Properties
| Property | Type | Defined in |
|---|---|---|
handles | ...[] | fhe/types.ts:31 |
inputProof | `0x${(...)}` | fhe/types.ts:32 |
EncryptedViewResult
Defined in: fhe/types.ts:44
Return shape for SDK methods that perform an on-chain encrypted-view tx —
the contract emits FHE.allow(handle, msg.sender) and the SDK extracts
handle from the receipt's ACL Allowed event.
Pass handle to the Zama relayer's userDecrypt to obtain the plaintext.
hash is the tx that committed the persistent ACL grant — surface it if
your UI needs to show the receipt.
Properties
| Property | Type | Defined in |
|---|---|---|
handle | `0x${(...)}` | fhe/types.ts:45 |
hash | `0x${(...)}` | fhe/types.ts:46 |
Type Aliases
ScaleRatioWidth
type ScaleRatioWidth = ... | ...;
Defined in: fhe/scale-ratio.ts:66
Bit-width to validate the scaled numerator/denominator against.
"uint64"matches the encrypted-numerator width every confidential split path actually uses (the SDK routes throughencryptUint64). HitsplitVesting-style call sites with this so the validator's bound matches the encryption path's bound — sameInvalidArgumentErrorinstead of a less specificEncryptionFailedErrordownstream."uint128"is the legacy default kept for non-split contract surfaces that the helper might also serve in the future.
EncryptedInput64
type EncryptedInput64 = EncryptedInput;
Defined in: fhe/types.ts:56
Deprecated
Use EncryptedInput. Earlier versions of
@tokenops/sdk/fhe exported this name with field proof, which did not
match the rest of the SDK or the on-chain calldata layout (the contracts
accept bytes inputProof). This alias points at the corrected shape and
will be removed in the next major.
EncryptedHandle
type EncryptedHandle = Hex;
Defined in: fhe/types.ts:62
Deprecated
Use Hex from viem directly. This alias added no narrowing
beyond Hex and will be removed in the next major.
ExternalInputProof
type ExternalInputProof = Hex;
Defined in: fhe/types.ts:68
Deprecated
Use Hex from viem directly. This alias added no narrowing
beyond Hex and will be removed in the next major.
Variables
FHEVM_ACL_ADDRESS_BY_CHAIN
const FHEVM_ACL_ADDRESS_BY_CHAIN: {
31337: ...;
11155111: ...;
1: ...;
};
Defined in: fhe/acl.ts:25
FHEVM ACL contract addresses indexed by chain id. Encrypted-view helpers in
product modules (fhe-vesting, fhe-airdrop, fhe-disperse) filter
receipt logs by this address to identify ACL grants emitted during the tx —
picking the wrong address means the strict-singleton check spuriously fails
or, worse, returns the wrong handle.
Keep this map as the single source of truth across products. Update all three entries together when Zama publishes new host contracts.
- Hardhat / Anvil (forge-fhevm) — see
@zama-fhe/sdkHardhatConfig. - Sepolia —
SepoliaConfig.aclContractAddress. - Mainnet —
MainnetConfig.aclContractAddress.
Prefer the accessors getFhevmAclAddress / requireFhevmAclAddress over reaching into this object directly — they centralise chain-id resolution and the typed-error policy. Indexing the map directly is still supported for advanced consumers who need raw registry access.
Type Declaration
31337
readonly 31337: ... = "0x50157CFfD6bBFA2DECe204a89ec419c23ef5755D";
11155111
readonly 11155111: ... = "0xf0Ffdc93b7E186bC2f8CB3dAA75D86d1930A433D";
1
readonly 1: ... = "0xcA2E8f1F656CD25C01F05d0b243Ab1ecd4a8ffb6";
ACL_ALLOWED_EVENT
const ACL_ALLOWED_EVENT: {
};
Defined in: fhe/acl.ts:38
Allowed(address indexed caller, address indexed account, bytes32 handle)
— emitted by the FHEVM ACL contract whenever a handle is granted to an
address. Encrypted-view helpers parse this from the tx receipt to extract
the handle the contract granted to the caller; using simulateContract for
the same purpose returns a divergent handle that has no ACL grant.
erc7984OperatorAbi
const erc7984OperatorAbi: readonly [..., ..., ...];
Defined in: fhe/erc7984-abi.ts:9
createLocalFhevmEncryptor
const createLocalFhevmEncryptor: (options) => ... = createMockEncryptor;
Defined in: fhe/mock-encryptor.ts:453
Alias for createMockEncryptor. Some docs and consumer agents reach for the more-descriptive name; both resolve to the same implementation.
Construct an SDK-shaped Encryptor backed by MockFhevmInstance
against a local FHEVM-ready Anvil node (pnpm fhevm:up). One call replaces
the 7-address MockFhevmInstance.create boilerplate every local-chain
consumer used to copy from node_modules/@fhevm/mock-utils.
Parameters
| Parameter | Type |
|---|---|
options | ... |
Returns
...
Example
import { createMockEncryptor } from "@tokenops/sdk/fhe";
const encryptor = await createMockEncryptor({ rpcUrl: "http://127.0.0.1:8545" });
const mgr = createConfidentialVestingManagerClient({ publicClient, walletClient, address, encryptor });
await mgr.createVesting({ params, amount: 1_000_000n });
Remarks
MockFhevmInstance is process-scoped: handles produced by one instance
are only decryptable by that same instance. For end-to-end encrypt →
submit → decrypt loops, keep one encryptor alive for the whole run and
serialize state (vestingId, manager, etc.) to disk between steps. See
/concepts/encryption for the recommended pattern.
MOCK_ERC7984_MINT_ABI
const MOCK_ERC7984_MINT_ABI: readonly [...];
Defined in: fhe/mock-erc7984.ts:40
Minimal mint(address,uint64) ABI fragment. Embedded inline (rather than
imported from a shared mock-token JSON artifact) because the selector is
stable across every ERC-7984-conformant mock — production ERC-7984s with
a mint(address,uint64) shape are accepted by the same fragment. No
artifact dependency.
The contract signature is:
function mint(address to, uint64 amount) external;
ERC7984_SET_OPERATOR_ABI
const ERC7984_SET_OPERATOR_ABI: readonly [...];
Defined in: fhe/operators.ts:48
Minimal setOperator ABI fragment. Embedded inline (rather than imported
from a shared mock-token ABI) because every ERC-7984-conformant token —
production or mock — exposes this exact 4-byte selector. No artifact
dependency.
The contract signature is:
function setOperator(address operator, uint48 until) external;
uint48 upper bound (2**48 - 1 ≈ 8.9e+14) is comfortably past year 9999
in unix seconds, so a "far-future" deadline is structurally safe.
ERC7984_OPERATOR_MAX_DEADLINE
const ERC7984_OPERATOR_MAX_DEADLINE: bigint;
Defined in: fhe/operators.ts:69
Far-future uint48 deadline. The on-chain until parameter is a uint48
unix timestamp; this constant is the maximum value the type can hold
(2**48 - 1). Use as the default deadline when a consumer doesn't care
about expiry — typical for local-chain dev loops and end-to-end fixture
setup. For production flows, scope the deadline to the expected operation
window (e.g. Date.now()/1000 + 3600).
FHE_SPLIT_DENOMINATOR
const FHE_SPLIT_DENOMINATOR: 90090000n = 90_090_000n;
Defined in: fhe/scale-ratio.ts:44
Fixed plaintext denominator used by every confidential split call.
= LCM(1..16, 10_000) = 2⁴ × 3² × 5⁴ × 7 × 11 × 13 = 90,090,000.
The denominator lives in plaintext (calldata or storage). Sizing it
per-call to fit each specific split would leak the split's shape — a
1/2 split would use a different plaintext denominator than a 1/7
split, and observers could distinguish them without decrypting anything.
Pinning every split to a single universal constant removes that side
channel.
90_090_000 specifically is the smallest integer divisible by every
common human split shape we support, in two flavours:
n/mwithm ∈ 1..16(halves, thirds, …, sixteenths and their combinations) — produces an exact integer numerator becausemdivides90_090_000.o/10_000(basis points,o ∈ 0..10_000) — produces an exact integer numerator because90_090_000 = 10_000 × 9_009, sobpsmaps tobps × 9_009.
No rounding artifacts in either case — the denominator itself is the only signal an observer sees, and it never changes, so the leak surface is zero. Use the share builder to construct ratios from either shape ergonomically.
Overflow is not a concern. The confidential-vesting contract upcasts
the encrypted numerator to euint128 before multiplying by the holder
balance, so the intermediate amount × numerator math happens in
euint128 space (max ~3.4 × 10³⁸). For a 6-decimal ERC-7984 balance
(max ~1.84 × 10¹⁹) and our denominator (~9 × 10⁷) the product tops out
at ~1.7 × 10²⁷ — eleven orders of magnitude under the euint128
ceiling. The plaintext denominator itself fits trivially in the
contract's uint128 denominator parameter.
Do NOT shrink this. All split-style SDK methods must use the same
value — the leak surface is only zero when every product agrees on
one constant. Today that's fhe-vesting splitVesting; future
split-style surfaces (weighted disperses, weighted airdrops if added)
must pin to this same constant.
share
const share: {
fraction: ...;
basisPoints: ...;
};
Defined in: fhe/scale-ratio.ts:210
Guided builders for the two split shapes the SDK supports as
exact-integer numerators over FHE_SPLIT_DENOMINATOR
(90_090_000 = LCM(1..16, 10_000)).
Use these when you know your split as one of:
- a simple fraction
n/mwithm ∈ 1..16(halves, thirds, …, sixteenths), or - a basis-point amount
bps/10_000withbps ∈ 0..10_000(1 bp = 0.01%, 100 bp = 1%, 10_000 bp = 100%).
Both shapes land on 90_090_000 with no rounding artifacts. The
returned ScaledRatio is ready to pass to split-style SDK calls with
preScaled: true — the auto-scaling path is skipped because the math
has already been done exactly.
Type Declaration
fraction()
readonly fraction(numerator, denominator): ...;
Build a ScaledRatio from a simple fraction n/m.
mmust be in1..16— every integer in this range divides FHE_SPLIT_DENOMINATOR cleanly, so the result is exact.nmust be in0..m—0is a zero-share (no-op split) andmitself is the whole position.
Both arguments accept number (must be an integer) or bigint —
use whichever is convenient at the call site.
Parameters
| Parameter | Type |
|---|---|
numerator | ... |
denominator | ... |
Returns
...
Throws
InvalidArgumentError if m is outside 1..16 or n is
outside 0..m, or either input is a non-integer number.
basisPoints()
readonly basisPoints(bps): ...;
Build a ScaledRatio from a basis-point amount.
bps must be in 0..10_000 — 0 is a zero-share and 10_000 is
the whole position (= 100%). 10_000 divides
FHE_SPLIT_DENOMINATOR cleanly, so the result is exact:
bps × 9_009 over 90_090_000.
Accepts number (must be an integer) or bigint.
Parameters
| Parameter | Type |
|---|---|
bps | ... |
Returns
...
Throws
InvalidArgumentError if bps is outside 0..10_000, or is
a non-integer number.
Examples
share.fraction(1, 3) // → { numerator: 30_030_000n, denominator: 90_090_000n }
share.basisPoints(250) // → { numerator: 2_252_250n, denominator: 90_090_000n } // 2.5%
const ratio = share.basisPoints(50); // 0.5%
await manager.splitVesting({
vestingId,
numerator: ratio.numerator,
denominator: ratio.denominator,
preScaled: true, // skip auto-scaling; share already did it
newRecipient,
});
SEPOLIA_CHAIN_ID
const SEPOLIA_CHAIN_ID: 11155111;
Defined in: fhe/sepolia-encryptor.ts:39
Sepolia testnet chain id (11155111). Re-exported as a typed literal so
consumers indexing DEPLOYED_ADDRESSES against this constant get the
narrow return type, not Address | undefined.
MAINNET_CHAIN_ID
const MAINNET_CHAIN_ID: 1;
Defined in: fhe/sepolia-encryptor.ts:41
Mainnet chain id (1). Same use as SEPOLIA_CHAIN_ID.
Functions
getFhevmAclAddress()
function getFhevmAclAddress(chainId): ... | ...;
Defined in: fhe/acl.ts:51
Resolve the FHEVM ACL contract address for chainId, returning undefined
when the chain isn't recognised. Mirrors the get*Address shape in
core/addresses.ts.
Use this when the caller wants to handle "no ACL on this chain" without a throw — e.g. constructing a product client lazily and deferring the error to first encrypted-view use.
Parameters
| Parameter | Type |
|---|---|
chainId | number |
Returns
... | ...
requireFhevmAclAddress()
function requireFhevmAclAddress(chainId, clientLabel): `0x${(...)}`;
Defined in: fhe/acl.ts:69
Resolve the FHEVM ACL contract address for chainId, throwing
DeploymentAddressUnavailableError when it can't be determined.
Mirrors the require*Address shape in core/addresses.ts.
Accepts chainId: undefined so callers can pass publicClient.chain?.id
directly without a pre-check; the helper handles the chain-id-missing
branch itself.
clientLabel is embedded in the thrown error so consumers can tell which
client misconfigured ACL (e.g. "ConfidentialVestingManagerClient").
The error's context.overrideName is set to "aclAddress" so the
message points users at the right config knob.
Parameters
| Parameter | Type |
|---|---|
chainId | ... | ... |
clientLabel | string |
Returns
`0x${(...)}`
createMockEncryptor()
function createMockEncryptor(options?): Promise<...>;
Defined in: fhe/mock-encryptor.ts:327
Construct an SDK-shaped Encryptor backed by MockFhevmInstance
against a local FHEVM-ready Anvil node (pnpm fhevm:up). One call replaces
the 7-address MockFhevmInstance.create boilerplate every local-chain
consumer used to copy from node_modules/@fhevm/mock-utils.
Parameters
| Parameter | Type |
|---|---|
options | CreateMockEncryptorOptions |
Returns
Promise<...>
Example
import { createMockEncryptor } from "@tokenops/sdk/fhe";
const encryptor = await createMockEncryptor({ rpcUrl: "http://127.0.0.1:8545" });
const mgr = createConfidentialVestingManagerClient({ publicClient, walletClient, address, encryptor });
await mgr.createVesting({ params, amount: 1_000_000n });
Remarks
MockFhevmInstance is process-scoped: handles produced by one instance
are only decryptable by that same instance. For end-to-end encrypt →
submit → decrypt loops, keep one encryptor alive for the whole run and
serialize state (vestingId, manager, etc.) to disk between steps. See
/concepts/encryption for the recommended pattern.
mintMockERC7984()
function mintMockERC7984(args): Promise<...>;
Defined in: fhe/mock-erc7984.ts:122
Mint amount MockERC7984 ciphertext units to to. Required pre-step for
any outside-in /fhe-vesting / /fhe-airdrop / /fhe-disperse walkthrough
where the operator's wallet needs a starting balance before the next
setOperator + createX call.
Parameters
| Parameter | Type |
|---|---|
args | MintMockERC7984Args |
Returns
Promise<...>
Example
import { mintMockERC7984, DEPLOYED_ADDRESSES } from "@tokenops/sdk";
const { hash, blockNumber } = await mintMockERC7984({
publicClient,
walletClient,
token: DEPLOYED_ADDRESSES.tokens.testConfidential[11155111]!,
to: walletClient.account!.address,
amount: 1_000_000n,
});
Throws
TokenOpsContractError if the writeContract or receipt-wait step throws. The original viem error is attached as the cause.
createMockErc7984Client()
function createMockErc7984Client(args): MockErc7984Client;
Defined in: fhe/mock-erc7984.ts:240
Construct a bound MockERC7984Token client. Lighter than
mintMockERC7984 when a consumer makes multiple mints against the
same token — the bound address + clients are stashed once.
Parameters
| Parameter | Type |
|---|---|
args | CreateMockErc7984ClientArgs |
Returns
Example
import { createMockErc7984Client, DEPLOYED_ADDRESSES } from "@tokenops/sdk/fhe";
const token = createMockErc7984Client({
publicClient,
walletClient,
address: DEPLOYED_ADDRESSES.tokens.testConfidential[11155111]!,
});
await token.mint({ to: alice, amount: 1_000_000n });
await token.mint({ to: bob, amount: 2_000_000n });
setOperator()
function setOperator(args): Promise<...>;
Defined in: fhe/operators.ts:154
Authorize spender to pull ERC-7984 tokens from account until
deadline. Required pre-step before any /fhe-vesting, /fhe-airdrop,
or /fhe-disperse flow that takes funds from the operator's balance.
Resolves to the transaction hash. Waits for the transaction to be mined
by default (waitForReceipt: true) — the receipt is the strongest
"operator is now authorized" signal a consumer can build the next call on
top of. Pass waitForReceipt: false if your call site manages receipt
polling itself.
Parameters
| Parameter | Type |
|---|---|
args | SetOperatorArgs |
Returns
Promise<...>
Example
import { setOperator, ERC7984_OPERATOR_MAX_DEADLINE } from "@tokenops/sdk/fhe";
await setOperator({
publicClient,
walletClient,
token: DEPLOYED_ADDRESSES.tokens.testConfidential[31337]!,
spender: manager,
// deadline defaults to ERC7984_OPERATOR_MAX_DEADLINE (forever).
});
// Now safe to call manager.createVesting / factory.fundConfidentialAirdrop / etc.
Throws
TokenOpsContractError if the writeContract or receipt-wait step throws. The original viem error is attached as the cause.
revokeOperator()
function revokeOperator(args): Promise<...>;
Defined in: fhe/operators.ts:308
Revoke a previously granted ERC-7984 operator authorization. Calls
token.setOperator(spender, 0) — the ERC-7984 convention where until=0
means "no future authorization" (the on-chain timestamp check until >= block.timestamp fails immediately).
When to use this. Any setOperator flow leaves the spender authorized
for the deadline window. The default deadline is
ERC7984_OPERATOR_MAX_DEADLINE (uint48 max ≈ year 8.9e+14) — useful
for local-chain dev loops, hostile for production deployments where a
stale manager clone (replaced by a new one) would otherwise keep operator
rights forever. The original setOperator shipped
without a revoke sibling, forcing consumers to hand-roll
walletClient.writeContract({ ..., args: [spender, 0] }).
Parameters
| Parameter | Type |
|---|---|
args | RevokeOperatorArgs |
Returns
Promise<...>
Example
import { revokeOperator } from "@tokenops/sdk/fhe";
await revokeOperator({
publicClient,
walletClient,
token: DEPLOYED_ADDRESSES.tokens.testConfidential[31337]!,
spender: staleManager, // old manager clone after deploying a new one
});
// `staleManager` can no longer call `confidentialTransferFrom` against
// the caller's balance.
Throws
TokenOpsContractError if the writeContract or receipt-wait step throws. The original viem error is attached as the cause.
scaleRatio()
function scaleRatio(__namedParameters): ScaledRatio;
Defined in: fhe/scale-ratio.ts:122
Scale a plaintext ratio so the output denominator equals the
privacy-preserving split constant (FHE_SPLIT_DENOMINATOR,
default 90_090_000) while keeping both values within uint128.
For arbitrary numerator/denominator inputs the output is the closest
exact-integer numerator under that constant — i.e. numerator × (90_090_000 / denominator) when denominator divides 90_090_000
(every 1..16 fraction and every basis-point amount), or
ceil(90_090_000 × numerator / denominator) for general inputs (with
the denominator still pinned to 90_090_000).
Pre-scaled inputs whose denominator already matches minDenominator
are returned unchanged; pre-scaled inputs whose denominator exceeds
minDenominator are also returned unchanged (the caller is asking for
higher precision than the standard constant, e.g. for a non-split
surface).
Most consumers should use share instead — its builders express
the two natural shapes (n/m, basis points) directly and produce
ScaledRatio outputs that are exact-integer by construction.
Parameters
| Parameter | Type |
|---|---|
__namedParameters | ScaleRatioArgs |
Returns
Examples
scaleRatio({ numerator: 1n, denominator: 2n });
// → { numerator: 45_045_000n, denominator: 90_090_000n } // 50% of 90_090_000
scaleRatio({ numerator: 2n, denominator: 3n });
// → { numerator: 60_060_000n, denominator: 90_090_000n } // exact: 2/3 × 90_090_000
createSepoliaEncryptorWeb()
function createSepoliaEncryptorWeb(opts): Promise<...>;
Defined in: fhe/sepolia-encryptor-web.ts:168
Construct an SDK-shaped Encryptor backed by Zama's RelayerWeb
against the public Sepolia (or mainnet) relayer. The browser parity peer
of createSepoliaEncryptor — same Encryptor contract, no
node:worker_threads / node:module in the import graph, so bundlers
(Next, Vite, etc.) follow only browser-safe paths.
Parameters
| Parameter | Type |
|---|---|
opts | CreateSepoliaEncryptorWebOpts |
Returns
Promise<...>
Example
import { createSepoliaEncryptorWeb } from "@tokenops/sdk/fhe";
import { createConfidentialVestingManagerClient } from "@tokenops/sdk/fhe-vesting";
const encryptor = await createSepoliaEncryptorWeb({ publicClient, walletClient });
const mgr = createConfidentialVestingManagerClient({
publicClient, walletClient, address: manager, encryptor,
});
await mgr.createVesting({ params, amount: 1_000_000n });
Remarks
This is the Sepolia / mainnet path. For local Anvil
(pnpm fhevm:up), use createMockEncryptor instead. Mock and real
relayer ciphertexts are not interchangeable.
createSepoliaEncryptor()
function createSepoliaEncryptor(options?): Promise<...>;
Defined in: fhe/sepolia-encryptor.ts:211
Construct an SDK-shaped Encryptor backed by Zama's RelayerNode
against the public Sepolia (or mainnet) relayer. One call replaces the
hand-rolled new RelayerNode({ transports: { 11155111: SepoliaConfig }, getChainId: async () => 11155111 })
boilerplate every Sepolia consumer used to copy from
node_modules/@zama-fhe/sdk/dist/esm/node/index.d.ts.
Parameters
| Parameter | Type |
|---|---|
options | CreateSepoliaEncryptorOptions |
Returns
Promise<...>
Example
import { createSepoliaEncryptor } from "@tokenops/sdk/fhe";
import { createConfidentialVestingManagerClient } from "@tokenops/sdk/fhe-vesting";
const encryptor = await createSepoliaEncryptor();
try {
const mgr = createConfidentialVestingManagerClient({
publicClient, walletClient, address: manager, encryptor,
});
await mgr.createVesting({ params, amount: 1_000_000n });
} finally {
encryptor.terminate(); // RelayerNode owns worker_threads — always tear down.
}
Remarks
This is the Sepolia / mainnet path. For local Anvil
(pnpm fhevm:up), use createMockEncryptor instead. The mock and
the real relayer do not share a bytestream — handles are not portable
across them.