Skip to main content

fhe-disperse

Classes

NotRegisteredError

Defined in: fhe-disperse/errors.ts:20

The user has not yet called register(token). Wallet-mode disperse paths require the per-user OZ-clone wallet pair to exist before they can transfer.

Extends

Constructors

Constructor
new NotRegisteredError(args): NotRegisteredError;

Defined in: fhe-disperse/errors.ts:28

Parameters
ParameterType
args{ method: ...; contractAddress: ...; user: ...; cause?: ...; }
args.method...
args.contractAddress...
args.user...
args.cause?...
Returns

NotRegisteredError

Overrides

TokenOpsSdkError.constructor

Properties

PropertyModifierTypeDefault valueOverridesInherited fromDefined in
codereadonlyTokenOpsSdkErrorCodeundefined-TokenOpsSdkError.codecore/errors.ts:89
[TOKENOPS_SDK_ERROR_BRAND]readonlytruetrue-TokenOpsSdkError.[TOKENOPS_SDK_ERROR_BRAND]core/errors.ts:91
namereadonly"NotRegisteredError""NotRegisteredError"TokenOpsSdkError.name-fhe-disperse/errors.ts:21
contextreadonly{ method: ...; contractAddress: ...; user: ...; }undefinedTokenOpsSdkError.context-fhe-disperse/errors.ts:22
context.methodpublic...undefined--fhe-disperse/errors.ts:23
context.contractAddresspublic...undefined--fhe-disperse/errors.ts:24
context.userpublic...undefined--fhe-disperse/errors.ts:25

AlreadyRegisteredError

Defined in: fhe-disperse/errors.ts:49

The user has already registered — register(token) is single-use per user. Use approveUserWalletsForToken(token) to grant the existing wallet pair approval over a new token.

Extends

Constructors

Constructor
new AlreadyRegisteredError(args): AlreadyRegisteredError;

Defined in: fhe-disperse/errors.ts:57

Parameters
ParameterType
args{ method: ...; contractAddress: ...; user: ...; cause?: ...; }
args.method...
args.contractAddress...
args.user...
args.cause?...
Returns

AlreadyRegisteredError

Overrides

TokenOpsSdkError.constructor

Properties

PropertyModifierTypeDefault valueOverridesInherited fromDefined in
codereadonlyTokenOpsSdkErrorCodeundefined-TokenOpsSdkError.codecore/errors.ts:89
[TOKENOPS_SDK_ERROR_BRAND]readonlytruetrue-TokenOpsSdkError.[TOKENOPS_SDK_ERROR_BRAND]core/errors.ts:91
namereadonly"AlreadyRegisteredError""AlreadyRegisteredError"TokenOpsSdkError.name-fhe-disperse/errors.ts:50
contextreadonly{ method: ...; contractAddress: ...; user: ...; }undefinedTokenOpsSdkError.context-fhe-disperse/errors.ts:51
context.methodpublic...undefined--fhe-disperse/errors.ts:52
context.contractAddresspublic...undefined--fhe-disperse/errors.ts:53
context.userpublic...undefined--fhe-disperse/errors.ts:54

ConfidentialDisperseClient

Defined in: fhe-disperse/singleton.ts:214

Typed SDK wrapper for the deployed DisperseConfidential singleton.

One DisperseConfidential exists per chain (no factory). This client is wired to a specific chain's singleton address, either by explicit address override or via DEPLOYED_ADDRESSES.fheDisperse.disperseConfidentialSingleton[chainId].

Example

// On Sepolia or mainnet the singleton address auto-resolves from
// `DEPLOYED_ADDRESSES.fheDisperse.disperseConfidentialSingleton[chainId]`;
// pass `address` explicitly only for custom networks.
const client = new ConfidentialDisperseClient({
publicClient,
walletClient,
encryptor,
});
await client.register({ token });
await client.disperse({ token, mode: "direct", recipients, amounts });

Constructors

Constructor
new ConfidentialDisperseClient(config): ConfidentialDisperseClient;

Defined in: fhe-disperse/singleton.ts:223

Parameters
ParameterType
configConfidentialDisperseClientConfig
Returns

ConfidentialDisperseClient

Properties

PropertyModifierTypeDefined in
publicClientreadonly{ }fhe-disperse/singleton.ts:215
walletClient?readonly... | ...fhe-disperse/singleton.ts:216
addressreadonly`0x${(...)}`fhe-disperse/singleton.ts:217
encryptor?readonly... | ...fhe-disperse/singleton.ts:218

Accessors

aclAddress
Get Signature
get aclAddress(): `0x${(...)}`;

Defined in: fhe-disperse/singleton.ts:270

The FHEVM ACL contract address used by encrypted-view methods to parse ACL.Allowed events. Resolved lazily on first access; throws DeploymentAddressUnavailableError if no override was passed and the SDK does not have an ACL deployed for the connected chain.

Returns

`0x${(...)}`

Methods

isRegistered()
isRegistered(user): Promise<...>;

Defined in: fhe-disperse/singleton.ts:285

Check whether a user has registered their wallet pair via register(token).

Parameters
ParameterType
user`0x${(...)}`
Returns

Promise<...>

getWallets()
getWallets(user): Promise<...>;

Defined in: fhe-disperse/singleton.ts:297

Return the on-chain wallet pair for a registered user, or null if not registered.

Both wallet addresses are fetched in parallel via getUserWallet(user, 0|1). For unregistered users, call predictWallets to get the deterministic addresses they would get after registration.

Parameters
ParameterType
user`0x${(...)}`
Returns

Promise<...>

predictWallets()
predictWallets(user): Promise<...>;

Defined in: fhe-disperse/singleton.ts:319

Deterministically predict the wallet addresses a user would get after calling register(), even before registration.

Reads WALLET_IMPLEMENTATION() once from chain, then applies the same keccak256(abi.encodePacked(user, uint256(0|1))) salt scheme used in the contract's _registerWallets function.

Note: Clones.predictDeterministicAddress(impl, salt) without an explicit deployer uses address(this) (the singleton) as the deployer — mirrored here.

Parameters
ParameterType
user`0x${(...)}`
Returns

Promise<...>

getFees()
getFees(user): Promise<...>;

Defined in: fhe-disperse/singleton.ts:336

Return consolidated fee information for a user in a single helper.

Combines getFeeAmounts(user) (per-user resolved fees) and feeConfig() (global toggles) in two parallel RPC calls. UI code calls this to render the fee panel before the user submits.

Parameters
ParameterType
user`0x${(...)}`
Returns

Promise<...>

getCustomFee()
getCustomFee(user): Promise<...>;

Defined in: fhe-disperse/singleton.ts:366

Read the raw per-user fee override stored on-chain, BEFORE the global toggles are applied. Returns { enabled: false, gasFeeWei: 0n, tokenFeeBps: 0 } when no override exists for user.

Use this — not getFees — when you need to distinguish "no override set" from "override set but globally disabled". The resolved shape is in getFees.

Parameters
ParameterType
user`0x${(...)}`
Returns

Promise<...>

getFeeConfig()
getFeeConfig(): Promise<...>;

Defined in: fhe-disperse/singleton.ts:384

Return the on-chain global fee configuration.

Round-trips against setFeeConfig — pass the result back unchanged to update one toggle without re-stating the others. Note that ABI outputs are positional, not named — viem decodes the tuple as an array.

Returns

Promise<...>

getBatchLimits()
getBatchLimits(): Promise<...>;

Defined in: fhe-disperse/singleton.ts:394

Return batch size limits for all three disperse modes. 0n means no limit is configured.

Returns

Promise<...>

calculateFee()
calculateFee(args): Promise<...>;

Defined in: fhe-disperse/singleton.ts:419

Calculate the fee for a specific disperse call without writing to chain.

Reads live fee data via getFeeAmounts(user) and computes:

  • "wallet" / "direct": ethValue = recipients * gasFeeWei, no token fee.
  • "wallet-token-fee": ethValue = 0n, tokenFeeAmount = totalTokens * tokenFeeBps / 10000n.

For "wallet-token-fee" mode, the on-chain fee base is the post-cap subtotal sum (subtotal0 + subtotal1), not sum(amounts[]). The two differ only when the caller has independently constructed subtotals that don't match sum(amounts) — pass totalTokens === subtotal0 + subtotal1 for the result to match the on-chain computation. Both this SDK and the contract round the BPS multiplication down (floor division).

Parameters
ParameterType
argsCalculateFeeArgs
Returns

Promise<...>

Throws

if mode is "wallet-token-fee" and totalTokens is not provided.

hasApprovedSubwallets()
hasApprovedSubwallets(args): Promise<...>;

Defined in: fhe-disperse/singleton.ts:445

Check whether a user's registered subwallets have approved the singleton as an ERC-7984 operator for the given token.

Calls isOperator(wallet, singleton) on the token contract for each wallet. Both wallets must return true for wallet-mode disperses to work.

Note: this requires the user to already be registered. For unregistered users, call predictWallets first and check predicted addresses.

Parameters
ParameterType
args{ user: ...; token: ...; }
args.user...
args.token...
Returns

Promise<...>

preflightDisperse()
preflightDisperse(args): Promise<...>;

Defined in: fhe-disperse/singleton.ts:487

Comprehensive pre-flight report. One call gives a UI everything it needs to render a "ready to disperse" checklist.

Internally composes:

  • isRegistered + getWallets / predictWallets
  • hasApprovedSubwallets (wallet modes) or isOperator(sender, singleton) (direct mode)
  • calculateFee / getBatchLimits
  • Structural recipient + amount validation
Parameters
ParameterType
argsPreflightDisperseArgs
Returns

Promise<...>

register()
register(args): Promise<...>;

Defined in: fhe-disperse/singleton.ts:693

Register the caller's dedicated wallet pair for wallet-mode disperses.

Deploys two deterministic ERC-1167 wallet clones and approves them for token. Can only be called once per user — subsequent calls revert with UserAlreadyRegistered.

Parameters
ParameterType
args{ token: ...; account?: ...; }
args.token...
args.account?...
Returns

Promise<...>

{ hash, wallets }wallets is parsed from the UserRegistered event.

Throws

if no UserRegistered event matching the singleton is found.

approveTokenOnWallets()
approveTokenOnWallets(args): Promise<...>;

Defined in: fhe-disperse/singleton.ts:738

Approve the caller's existing registered wallets as ERC-7984 operators for token.

Required for wallet-mode disperses when using a token different from the one passed at registration time.

Parameters
ParameterType
args{ token: ...; account?: ...; }
args.token...
args.account?...
Returns

Promise<...>

revokeTokenOnWallets()
revokeTokenOnWallets(args): Promise<...>;

Defined in: fhe-disperse/singleton.ts:749

Revoke the operator approval on token for the caller's wallets.

The user can re-approve later via approveTokenOnWallets.

Parameters
ParameterType
args{ token: ...; account?: ...; }
args.token...
args.account?...
Returns

Promise<...>

recoverFromWallets()
recoverFromWallets(args): Promise<...>;

Defined in: fhe-disperse/singleton.ts:763

Recover all residual confidential tokens from the caller's wallets to to.

Use after a wallet-mode disperse where the subtotals were inflated and tokens remain locked in the wallets. Returns the bare tx hash (not a wrapped result object) — unlike disperse(), this method does not surface any additional receipt-derived data.

Parameters
ParameterType
args{ token: ...; to: ...; account?: ...; }
args.token...
args.to...
args.account?...
Returns

Promise<...>

recoverERC20FromWallets()
recoverERC20FromWallets(args): Promise<...>;

Defined in: fhe-disperse/singleton.ts:778

Recover ERC-20 tokens accidentally sent to the caller's wallets. Returns the bare tx hash.

Parameters
ParameterType
args{ token: ...; to: ...; account?: ...; }
args.token...
args.to...
args.account?...
Returns

Promise<...>

disperse()
disperse(args): Promise<...>;

Defined in: fhe-disperse/singleton.ts:806

Disperse confidential tokens to multiple recipients.

SDK responsibilities:

  1. Validates input deterministically (lengths, zero addresses, per-amount uint64 bounds, wallet-mode subtotal overflow, batch-limit for the selected mode) — using the same validateDisperseInputs helper preflightDisperse uses, so an oversized or malformed batch is rejected before any FHE encryption time is spent.
  2. For wallet modes: computes group subtotals using the contract's exact split rule.
  3. Encrypts amounts + subtotals in a single batch call (one input proof).
  4. Computes msg.value for gas-fee modes; 0 for token-fee mode.
  5. Dispatches to the correct contract function based on mode.
Parameters
ParameterType
argsDisperseArgs
Returns

Promise<...>

Throws

on input validation failure (first deterministic error).

Throws

if no encryptor is available at call time.

getEncryptedFeeReserve()
getEncryptedFeeReserve(args): Promise<...>;

Defined in: fhe-disperse/singleton.ts:884

This is a write transaction, not a free view. It costs gas.

Grant the caller persistent FHE ACL on the encrypted token fee reserve and return the handle. The handle is extracted from the receipt's ACL Allowed event — using simulateContract here would return a divergent handle that breaks user-decrypt downstream (Pitfall #1).

If no fees have accrued for token, the contract does not emit an ACL event and this method throws DisperseEncryptedReserveNotGrantedError. Check FHE.isInitialized off-chain: a zero-hash handle means the reserve is uninitialised.

Requires FEE_COLLECTOR_ROLE or DEFAULT_ADMIN_ROLE.

Parameters
ParameterType
argsGetEncryptedFeeReserveArgs
Returns

Promise<...>

Throws

when no ACL event is found (i.e., reserve is uninitialised — no fees have accrued).

discloseHandleToParty()
discloseHandleToParty(args): Promise<...>;

Defined in: fhe-disperse/singleton.ts:965

Grant party persistent FHE ACL on a single handle.

Caller must already hold ACL on handle. FHEVM ACL is append-only — the grant cannot be revoked.

Parameters
ParameterType
argsDiscloseHandleArgs
Returns

Promise<...>

{ hash, discloser, party, disclosedHandles }. The non-hash fields are parsed from the HandlesDisclosedToParty event when present; if the event is absent (anomalous), they fall back to the call's inputs.

batchDiscloseHandlesToParty()
batchDiscloseHandlesToParty(args): Promise<...>;

Defined in: fhe-disperse/singleton.ts:981

Batch variant — atomically grant party persistent ACL on all handles. Reverts on the first handle that fails caller-ACL or contract-ACL checks.

Parameters
ParameterType
argsBatchDiscloseHandlesArgs
Returns

Promise<...>

pause()
pause(account?): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1035

Pause all disperse operations. Requires PAUSER_ROLE.

Parameters
ParameterType
account?... | ... | ...
Returns

Promise<...>

Transaction hash.

unpause()
unpause(account?): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1045

Unpause the singleton. Requires PAUSER_ROLE.

Parameters
ParameterType
account?... | ... | ...
Returns

Promise<...>

Transaction hash.

setFeeConfig()
setFeeConfig(config, account?): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1056

Update the global fee configuration: enable/disable gas and token fees, set defaults. Requires FEE_MANAGER_ROLE.

Parameters
ParameterType
configFeeConfig
account?... | ... | ...
Returns

Promise<...>

Transaction hash.

setCustomFee()
setCustomFee(
user,
gasFee,
tokenFee,
account?): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1078

Set a per-user fee override (gas fee in wei, token fee in BPS). Requires FEE_MANAGER_ROLE.

Parameters
ParameterType
user`0x${(...)}`
gasFeebigint
tokenFeenumber
account?... | ... | ...
Returns

Promise<...>

Transaction hash.

disableCustomFee()
disableCustomFee(user, account?): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1093

Remove a per-user fee override, falling back to the global defaults. Requires FEE_MANAGER_ROLE. Throws CustomFeeNotSet if no override exists.

Parameters
ParameterType
user`0x${(...)}`
account?... | ... | ...
Returns

Promise<...>

Transaction hash.

setMaxBatchSizeHolding()
setMaxBatchSizeHolding(size, account?): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1103

Set the maximum batch size for "wallet" mode disperses. 0n = no limit. Requires DEFAULT_ADMIN_ROLE.

Parameters
ParameterType
sizebigint
account?... | ... | ...
Returns

Promise<...>

Transaction hash.

setMaxBatchSizeDirect()
setMaxBatchSizeDirect(size, account?): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1118

Set the maximum batch size for "direct" mode disperses. 0n = no limit. Requires DEFAULT_ADMIN_ROLE.

Parameters
ParameterType
sizebigint
account?... | ... | ...
Returns

Promise<...>

Transaction hash.

setMaxBatchSizeTokenFee()
setMaxBatchSizeTokenFee(size, account?): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1133

Set the maximum batch size for "wallet-token-fee" mode disperses. 0n = no limit. Requires DEFAULT_ADMIN_ROLE.

Parameters
ParameterType
sizebigint
account?... | ... | ...
Returns

Promise<...>

Transaction hash.

withdrawGasFee()
withdrawGasFee(
to,
amount,
account?): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1153

Withdraw amount wei of accumulated ETH gas fees to to. The amount is not capped on-chain — callers MUST pass an explicit amount. There is no "drain full balance" sentinel: passing 0n succeeds with no ETH movement. Read the singleton's ETH balance with publicClient.getBalance(singleton) to drain.

Requires FEE_COLLECTOR_ROLE.

Parameters
ParameterType
to`0x${(...)}`
amountbigint
account?... | ... | ...
Returns

Promise<...>

Transaction hash.

withdrawTokenFee()
withdrawTokenFee(args): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1178

Withdraw accumulated encrypted token fees.

The amount is encrypted by the caller — pass plaintext amount and an encryptor, or pass encryptedInput directly. The contract caps the withdrawal at the available reserve via FHE.min.

Returns the tx hash plus the transferred handle parsed from the TokenFeeWithdrawn event. Decrypt the handle via Zama's userDecrypt to view the actual amount moved (which can be less than requested when the reserve was smaller than the request). The caller is granted persistent ACL on this handle by the contract.

encryptedInput is bound to (this singleton, this caller). Zama's KMSVerifier rejects proofs whose contractAddress or userAddress don't match the executing tx. If you pre-encrypt on a different chain's singleton, or for a different caller, the on-chain submission will revert with a generic verification failure. The plaintext amount path is safer when the caller / chain isn't fixed yet.

Parameters
ParameterTypeDescription
args{ token: ...; to: ...; amount?: ...; encryptor?: ...; encryptedInput?: ...; account?: ...; }-
args.token...-
args.to...-
args.amount?...Plaintext amount. Mutually exclusive with encryptedInput — supply exactly one.
args.encryptor?...-
args.encryptedInput?...Pre-encrypted input. Mutually exclusive with amount.
args.account?...-
Returns

Promise<...>

rescueConfidentialTokens()
rescueConfidentialTokens(
token,
to,
account?): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1236

Rescue accidentally-sent ERC-7984 confidential tokens from the singleton. Requires WITHDRAWER_ROLE.

Parameters
ParameterType
token`0x${(...)}`
to`0x${(...)}`
account?... | ... | ...
Returns

Promise<...>

Transaction hash.

rescueERC20()
rescueERC20(
token,
to,
account?): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1251

Rescue accidentally-sent ERC-20 tokens from the singleton. Requires WITHDRAWER_ROLE.

Parameters
ParameterType
token`0x${(...)}`
to`0x${(...)}`
account?... | ... | ...
Returns

Promise<...>

Transaction hash.

hasRole()
hasRole(role, address): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1266

Check whether address holds role on the singleton.

Parameters
ParameterType
role`0x${(...)}`
address`0x${(...)}`
Returns

Promise<...>

Example
const isAdmin = await client.hasRole("0x0000...0000", account.address);
grantRole()
grantRole(
role,
accountTarget,
account?): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1275

Grant role to accountTarget. Requires DEFAULT_ADMIN_ROLE.

Parameters
ParameterType
role`0x${(...)}`
accountTarget`0x${(...)}`
account?... | ... | ...
Returns

Promise<...>

Transaction hash.

revokeRole()
revokeRole(
role,
accountTarget,
account?): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1284

Revoke role from accountTarget. Requires DEFAULT_ADMIN_ROLE.

Parameters
ParameterType
role`0x${(...)}`
accountTarget`0x${(...)}`
account?... | ... | ...
Returns

Promise<...>

Transaction hash.

renounceRole()
renounceRole(
role,
callerConfirmation,
account?): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1300

Voluntarily relinquish role from the caller. The contract enforces callerConfirmation === msg.sender (OZ AccessControl) as a guard against accidental renunciation via a wrapper contract — pass the connected wallet's address here.

Use to permanently drop privileges from a fee-collector / withdrawer / pauser without needing an admin's revokeRole. Cannot be undone.

Parameters
ParameterType
role`0x${(...)}`
callerConfirmation`0x${(...)}`
account?... | ... | ...
Returns

Promise<...>

Transaction hash.

paused()
paused(): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1314

Whether the singleton is currently paused.

Returns

Promise<...>

deploymentBlockNumber()
deploymentBlockNumber(): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1319

Block number at which the singleton was deployed.

Returns

Promise<...>

walletImplementation()
walletImplementation(): Promise<...>;

Defined in: fhe-disperse/singleton.ts:1324

The ERC-1167 WALLET_IMPLEMENTATION address used by Clones.cloneDeterministic.

Returns

Promise<...>


DisperseSubwalletNotFoundError

Defined in: fhe-disperse/types.ts:361

Thrown by register() when no UserRegistered event matching the singleton address is found in the transaction receipt.

Extends

Constructors

Constructor
new DisperseSubwalletNotFoundError(txHash, singletonAddress): DisperseSubwalletNotFoundError;

Defined in: fhe-disperse/types.ts:365

Parameters
ParameterType
txHash`0x${(...)}`
singletonAddress`0x${(...)}`
Returns

DisperseSubwalletNotFoundError

Overrides

TokenOpsSdkError.constructor

Properties

PropertyModifierTypeDefault valueOverridesInherited fromDefined in
codereadonlyTokenOpsSdkErrorCodeundefined-TokenOpsSdkError.codecore/errors.ts:89
[TOKENOPS_SDK_ERROR_BRAND]readonlytruetrue-TokenOpsSdkError.[TOKENOPS_SDK_ERROR_BRAND]core/errors.ts:91
namepublicstring"DisperseSubwalletNotFoundError"TokenOpsSdkError.name-fhe-disperse/types.ts:362
contextreadonly{ txHash: ...; singletonAddress: ...; }undefinedTokenOpsSdkError.context-fhe-disperse/types.ts:363
context.txHashpublic...undefined--fhe-disperse/types.ts:363
context.singletonAddresspublic...undefined--fhe-disperse/types.ts:363

DisperseEncryptedReserveNotGrantedError

Defined in: fhe-disperse/types.ts:380

Thrown by getEncryptedFeeReserve() when no ACL Allowed event granting the caller access to the fee reserve handle is found in the receipt.

Extends

Constructors

Constructor
new DisperseEncryptedReserveNotGrantedError(txHash, callerAddress): DisperseEncryptedReserveNotGrantedError;

Defined in: fhe-disperse/types.ts:384

Parameters
ParameterType
txHash`0x${(...)}`
callerAddress`0x${(...)}`
Returns

DisperseEncryptedReserveNotGrantedError

Overrides

TokenOpsSdkError.constructor

Properties

PropertyModifierTypeDefault valueOverridesInherited fromDefined in
codereadonlyTokenOpsSdkErrorCodeundefined-TokenOpsSdkError.codecore/errors.ts:89
[TOKENOPS_SDK_ERROR_BRAND]readonlytruetrue-TokenOpsSdkError.[TOKENOPS_SDK_ERROR_BRAND]core/errors.ts:91
namepublicstring"DisperseEncryptedReserveNotGrantedError"TokenOpsSdkError.name-fhe-disperse/types.ts:381
contextreadonly{ txHash: ...; callerAddress: ...; }undefinedTokenOpsSdkError.context-fhe-disperse/types.ts:382
context.txHashpublic...undefined--fhe-disperse/types.ts:382
context.callerAddresspublic...undefined--fhe-disperse/types.ts:382

Interfaces

Encryptor

Defined in: fhe-disperse/encryption.ts:36

Subset of @zama-fhe/sdk RelayerSDK we depend on. Declared structurally so consumers can pass any v3 RelayerSDK without us importing the optional peer dep.

Methods

encrypt()
encrypt(params): Promise<...>;

Defined in: fhe-disperse/encryption.ts:37

Parameters
ParameterType
params{ values: ...; contractAddress: ...; userAddress: ...; }
params.values...
params.contractAddress...
params.userAddress...
Returns

Promise<...>


EncryptUint64Args

Defined in: fhe-disperse/encryption.ts:67

Properties

PropertyTypeDefined in
encryptorEncryptorfhe-disperse/encryption.ts:68
contractAddress`0x${(...)}`fhe-disperse/encryption.ts:69
userAddress`0x${(...)}`fhe-disperse/encryption.ts:70
valuebigintfhe-disperse/encryption.ts:71

EncryptUint64BatchArgs

Defined in: fhe-disperse/encryption.ts:74

Properties

PropertyTypeDefined in
encryptorEncryptorfhe-disperse/encryption.ts:75
contractAddress`0x${(...)}`fhe-disperse/encryption.ts:76
userAddress`0x${(...)}`fhe-disperse/encryption.ts:77
values...[]fhe-disperse/encryption.ts:78

ConfidentialDisperseClientConfig

Defined in: fhe-disperse/singleton.ts:142

Properties

PropertyTypeDescriptionDefined in
publicClient{ }viem public client for read calls.fhe-disperse/singleton.ts:144
walletClient?... | ...viem wallet client for write calls. Optional for read-only usage.fhe-disperse/singleton.ts:146
address?... | ...Override the singleton address. Falls back to DEPLOYED_ADDRESSES.fheDisperse.disperseConfidentialSingleton[chainId]. Required when that entry is null (i.e., singleton not yet deployed on this chain).fhe-disperse/singleton.ts:152
chainId?... | ...Chain id used to look up the default singleton address and the FHEVM ACL address. Defaults to publicClient.chain?.id.fhe-disperse/singleton.ts:157
encryptor?... | ...Default encryptor for disperse and getEncryptedFeeReserve. Accepts an eager instance or a lazy factory (for React / Vue hosts). Wallet-switch hazard. A RelayerWeb instance binds to the signing keypair active when it was constructed. If you cache a single SDK client across wallet switches in a React/Vue app, the lazy factory MUST return a freshly constructed RelayerWeb for the new active account — returning a memoised instance built for the previous user will produce input-proofs the KMSVerifier rejects on-chain.fhe-disperse/singleton.ts:169
aclAddress?... | ...FHEVM ACL contract address override. When omitted, resolved from the effective chain id (chainId arg or publicClient.chain?.id) via the SDK's chain registry; the constructor throws DeploymentAddressUnavailableError if neither is available. Required because getEncryptedFeeReserve filters the receipt for ACL grants to extract the returned handle.fhe-disperse/singleton.ts:178
telemetry?... | ...Optional telemetry sink. When provided, the SDK emits a fhe-disperse.client.init event on construction and brackets public write methods with named spans (fhe-disperse.singleton.register, …disperse, …). Defaults to a no-op — zero overhead, zero leakage of consumer-side identifiers. The shape is structurally compatible with NoopTelemetry / ConsoleTelemetry / TokenOpsTelemetry exported from @tokenops/sdk/telemetry.fhe-disperse/singleton.ts:188

UserFees

Defined in: fhe-disperse/types.ts:30

Resolved fee configuration for a given user. Combines getFeeAmounts(user) and feeConfig() global toggles.

Properties

PropertyTypeDescriptionDefined in
isCustombooleantrue when the user has a per-user custom fee override.fhe-disperse/types.ts:32
gasFeeWeibigintResolved gas fee per recipient in wei (0 if gas fee is disabled).fhe-disperse/types.ts:34
tokenFeeBpsnumberResolved token fee in basis points (0 if token fee is disabled).fhe-disperse/types.ts:36
gasFeeEnabledbooleanWhether gas fees are globally enabled.fhe-disperse/types.ts:38
tokenFeeEnabledbooleanWhether token fees are globally enabled.fhe-disperse/types.ts:40

FeeConfig

Defined in: fhe-disperse/types.ts:49

Global fee configuration (on-chain feeConfig struct).

Field names match the contract ABI exactly so the type round-trips through getFeeConfig() (read) and setFeeConfig(config) (write).

Properties

PropertyTypeDescriptionDefined in
gasFeeEnabledboolean-fhe-disperse/types.ts:50
tokenFeeEnabledboolean-fhe-disperse/types.ts:51
defaultGasFeebigintDefault gas fee per recipient, in wei.fhe-disperse/types.ts:53
defaultTokenFeenumberDefault token fee in basis points.fhe-disperse/types.ts:55

BatchLimits

Defined in: fhe-disperse/types.ts:61

Batch size limits. 0n means no limit.

Properties

PropertyTypeDescriptionDefined in
holdingbigintMax recipients for wallet-mode disperses. 0n = no limit.fhe-disperse/types.ts:63
directbigintMax recipients for direct-mode disperses. 0n = no limit.fhe-disperse/types.ts:65
tokenFeebigintMax recipients for token-fee wallet-mode disperses. 0n = no limit.fhe-disperse/types.ts:67

CalculatedFee

Defined in: fhe-disperse/types.ts:75

Calculated fee for a specific disperse call.

  • For "wallet" and "direct" modes: ethValue covers the gas fee; tokenFeeAmount is undefined.
  • For "wallet-token-fee": ethValue is 0n; tokenFeeAmount is the BPS fee on the subtotals.

Properties

PropertyTypeDefined in
ethValuebigintfhe-disperse/types.ts:76
tokenFeeAmount?... | ...fhe-disperse/types.ts:77

CustomFee

Defined in: fhe-disperse/types.ts:87

Raw per-user fee override as stored on-chain. Distinct from UserFees (which combines this with global toggles into the resolved fee).

Use to surface "this user has an override of 0 BPS that's currently being masked by tokenFeeEnabled = false" in admin UIs.

Properties

PropertyTypeDescriptionDefined in
enabledbooleantrue when the user has an override set. false means no override.fhe-disperse/types.ts:89
gasFeeWeibigintOverride gas fee per recipient, in wei. Only meaningful when enabled.fhe-disperse/types.ts:91
tokenFeeBpsnumberOverride token fee in basis points. Only meaningful when enabled.fhe-disperse/types.ts:93

RecipientCheck

Defined in: fhe-disperse/types.ts:103

Per-recipient validation result inside a PreflightReport.

Properties

PropertyTypeDescriptionDefined in
address`0x${(...)}`-fhe-disperse/types.ts:104
okbooleantrue when no structural problem was detected for this recipient.fhe-disperse/types.ts:106
reason?... | ...Human-readable description if ok === false.fhe-disperse/types.ts:108

PreflightReport

Defined in: fhe-disperse/types.ts:118

Comprehensive pre-flight report returned by ConfidentialDisperseClient.preflightDisperse.

One call gives a UI everything it needs to render a "ready to disperse" checklist. Compose it; do not implement each check inline.

Properties

PropertyTypeDescriptionDefined in
isUserRegisteredbooleanWhether the user has already registered via register(token).fhe-disperse/types.ts:120
wallets... | ...On-chain wallet pair for the user. null if not registered. For wallet modes, these wallets must exist before dispersing.fhe-disperse/types.ts:125
predictedWallets[..., ...]Deterministically predicted wallet addresses — present regardless of registration state.fhe-disperse/types.ts:130
hasApprovedSubwallets{ wallet0: ...; wallet1: ...; both: ...; }Per-wallet approval state for the given token. Only relevant for wallet modes.fhe-disperse/types.ts:132
hasApprovedSubwallets.wallet0...-fhe-disperse/types.ts:132
hasApprovedSubwallets.wallet1...-fhe-disperse/types.ts:132
hasApprovedSubwallets.both...-fhe-disperse/types.ts:132
hasApprovedSingleton... | ... | ...For "direct" mode: whether the sender itself has approved the singleton as operator. null for wallet modes (approval is on the subwallets, not the sender).fhe-disperse/types.ts:137
feeEthbigintETH to attach as msg.value.fhe-disperse/types.ts:139
feeTokenAmount?... | ...Token BPS fee amount. Defined only for "wallet-token-fee" mode.fhe-disperse/types.ts:141
batchLimitbigintCurrent batch limit for the selected mode. 0n = no limit.fhe-disperse/types.ts:143
batchOkbooleantrue when recipients.length <= batchLimit (or limit is 0).fhe-disperse/types.ts:145
recipientChecks...[]Per-recipient structural checks (zero-address, etc.).fhe-disperse/types.ts:147
amountsOkbooleantrue when amounts.length === recipients.length and lengths are non-zero.fhe-disperse/types.ts:149
subtotals?... | ...Pre-computed group subtotals for wallet modes. Matches the split the SDK will use inside disperse(). undefined for "direct" mode.fhe-disperse/types.ts:154
readybooleantrue when no blockers are present — green light to call disperse.fhe-disperse/types.ts:156
blockers...[]Human-readable reasons that prevent dispersing. Empty when ready === true. Deprecated Use blockerErrors instead — typed TokenOpsSdkErrors give you error.code to branch on. This field stays for backward compatibility; it will be removed in the next major.fhe-disperse/types.ts:164
blockerErrors...[]Typed errors that would otherwise be thrown at write time. Same shape as the generic PreflightResult.blockers contract used by preflightClaim on the vesting and airdrop clients. Empty when ready === true. Branch on error.code to render UI.fhe-disperse/types.ts:171

SubwalletApprovalState

Defined in: fhe-disperse/types.ts:181

Approval state of a user's subwallet pair for a specific token.

Properties

PropertyTypeDefined in
wallet0booleanfhe-disperse/types.ts:182
wallet1booleanfhe-disperse/types.ts:183
bothbooleanfhe-disperse/types.ts:184

RegisterResult

Defined in: fhe-disperse/types.ts:192

Result of register().

Properties

PropertyTypeDescriptionDefined in
hash`0x${(...)}`Transaction hash.fhe-disperse/types.ts:194
wallets[..., ...]The two subwallet addresses parsed from the UserRegistered event.fhe-disperse/types.ts:196

DisperseDistribution

Defined in: fhe-disperse/types.ts:204

Per-wallet (wallet modes) or single (direct mode) distribution row, parsed from a WalletDistribution / DirectDistribution event in the disperse receipt.

Properties

PropertyTypeDescriptionDefined in
wallet?... | ...Sub-wallet that funded this distribution, for wallet-mode disperses. undefined for direct mode (sender transfers directly).fhe-disperse/types.ts:209
recipients...[]Recipients in this distribution row, in contract emission order.fhe-disperse/types.ts:211
requested...[]Encrypted euint64 handles for the per-recipient requested amount — the value the caller passed into disperse.fhe-disperse/types.ts:216
transferred...[]Encrypted euint64 handles for the per-recipient transferred amount — what the ERC-7984 confidentialTransfer/confidentialTransferFrom actually moved. Can be less than requested when the sender's confidential balance was insufficient, or zero on a subtotal overflow.fhe-disperse/types.ts:223

DisperseResult

Defined in: fhe-disperse/types.ts:227

Result of disperse().

Properties

PropertyTypeDescriptionDefined in
hash`0x${(...)}`Transaction hash.fhe-disperse/types.ts:229
distributions...[]Distributions parsed from the receipt. One entry per WalletDistribution (wallet modes — up to two entries) or a single entry per DirectDistribution (direct mode). Empty array if no distribution event was emitted (which would indicate a contract or parse anomaly).fhe-disperse/types.ts:236

WithdrawTokenFeeResult

Defined in: fhe-disperse/types.ts:240

Result of withdrawTokenFee().

Properties

PropertyTypeDescriptionDefined in
hash`0x${(...)}`Transaction hash.fhe-disperse/types.ts:242
transferredHandle?... | ...Encrypted euint64 handle for the actual transferred amount, parsed from the TokenFeeWithdrawn event. May be less than the requested withdrawal when the reserve was lower (the contract caps via FHE.min). Pass to Zama's userDecrypt to view the plaintext. undefined if no TokenFeeWithdrawn event was found in the receipt.fhe-disperse/types.ts:251

DisclosureResult

Defined in: fhe-disperse/types.ts:255

Result of discloseHandleToParty() / batchDiscloseHandlesToParty().

Properties

PropertyTypeDescriptionDefined in
hash`0x${(...)}`Transaction hash.fhe-disperse/types.ts:257
discloser`0x${(...)}`Caller that initiated the disclosure (from the HandlesDisclosedToParty event).fhe-disperse/types.ts:259
party`0x${(...)}`Address that received persistent ACL on the disclosed handles.fhe-disperse/types.ts:261
disclosedHandles...[]Handles whose ACL was granted to party.fhe-disperse/types.ts:263

DisperseArgs

Defined in: fhe-disperse/types.ts:271

Arguments for disperse().

Properties

PropertyTypeDescriptionDefined in
token`0x${(...)}`ERC-7984 token address.fhe-disperse/types.ts:273
modeDisperseModeDisperse mode.fhe-disperse/types.ts:275
recipients...[]Array of recipient addresses. Must be non-empty, no zero addresses.fhe-disperse/types.ts:277
amounts...[]Plaintext per-recipient amounts in raw token units. SDK encrypts these.fhe-disperse/types.ts:279
gasFeeOverride?... | ...Override the ETH value — skips live fee read for gas/direct modes.fhe-disperse/types.ts:281
account?... | ... | ...Override signer account. Falls back to walletClient.account.fhe-disperse/types.ts:283

GetEncryptedFeeReserveArgs

Defined in: fhe-disperse/types.ts:287

Arguments for getEncryptedFeeReserve().

Properties

PropertyTypeDescriptionDefined in
token`0x${(...)}`ERC-7984 token to query the fee reserve for.fhe-disperse/types.ts:289
account?... | ... | ...Override signer account. Falls back to walletClient.account.fhe-disperse/types.ts:291

DiscloseHandleArgs

Defined in: fhe-disperse/types.ts:295

Arguments for discloseHandleToParty().

Properties

PropertyTypeDescriptionDefined in
handle`0x${(...)}`The euint64 handle to re-share.fhe-disperse/types.ts:297
party`0x${(...)}`The address receiving persistent decrypt access.fhe-disperse/types.ts:299
account?... | ... | ...-fhe-disperse/types.ts:300

BatchDiscloseHandlesArgs

Defined in: fhe-disperse/types.ts:304

Arguments for batchDiscloseHandlesToParty().

Properties

PropertyTypeDescriptionDefined in
handles...[]The euint64 handles to re-share.fhe-disperse/types.ts:306
party`0x${(...)}`The address receiving persistent decrypt access.fhe-disperse/types.ts:308
account?... | ... | ...-fhe-disperse/types.ts:309

PreflightDisperseArgs

Defined in: fhe-disperse/types.ts:336

Arguments for preflightDisperse().

Properties

PropertyTypeDefined in
user`0x${(...)}`fhe-disperse/types.ts:337
token`0x${(...)}`fhe-disperse/types.ts:338
recipients...[]fhe-disperse/types.ts:339
amounts...[]fhe-disperse/types.ts:340
modeDisperseModefhe-disperse/types.ts:341

CalculateFeeArgs

Defined in: fhe-disperse/types.ts:345

Arguments for calculateFee().

Properties

PropertyTypeDescriptionDefined in
user`0x${(...)}`-fhe-disperse/types.ts:346
modeDisperseMode-fhe-disperse/types.ts:347
recipientsnumber-fhe-disperse/types.ts:348
totalTokens?... | ...Required for "wallet-token-fee" to compute the token fee.fhe-disperse/types.ts:350

Type Aliases

FheValueInput

type FheValueInput = ... | ... | ...;

Defined in: fhe-disperse/encryption.ts:14

FHE input values, discriminated by ciphertext type. Mirrors the shape of EncryptInput from @zama-fhe/sdk so that a RelayerWeb / RelayerNode / MockFhevmInstance instance is structurally assignable to Encryptor without casting.


EncryptorSource

type EncryptorSource = ... | ...;

Defined in: fhe-disperse/encryption.ts:59

Eager or lazy Encryptor reference. Lazy form for React/Vue/signals hosts where the encryptor lifetime doesn't match the client's.

Wallet-switch contract. A RelayerWeb instance binds to the keypair derived from the active signing account at construction time. The input proofs it produces are committed to (contractAddress, userAddress) pairs — the KMSVerifier rejects on-chain submission when those don't match the executing tx.

For multi-wallet React hosts the lazy form MUST return a freshly constructed RelayerWeb for the current walletClient.account — returning a memoised instance built for a previous account is a silent proof-invalidation bug that surfaces only at submit time.


DisperseMode

type DisperseMode = ... | ... | ...;

Defined in: fhe-disperse/types.ts:20

Disperse mode. Maps to the three DisperseConfidential entry points:

  • "wallet" — per-user wallet pair, gas fee in ETH per recipient.
  • "wallet-token-fee" — per-user wallet pair, token BPS fee on subtotals.
  • "direct" — direct confidentialTransferFrom, gas fee in ETH per recipient.

Variables

disperseConfidentialAbi

const disperseConfidentialAbi: readonly [..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ...];

Defined in: fhe-disperse/abis/singleton.ts:2


disperseWalletAbi

const disperseWalletAbi: readonly [..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ...];

Defined in: fhe-disperse/abis/wallet.ts:2


FEE_COLLECTOR_ROLE

const FEE_COLLECTOR_ROLE: "0x2dca0f5ce7e75a4b43fe2b0d6f5d0b7a2bf92ecf89f8f0aa17b8308b67038821";

Defined in: fhe-disperse/index.ts:74


FEE_MANAGER_ROLE

const FEE_MANAGER_ROLE: "0x6c0757dc3e6b28b2580c03fd9e96c274acf4f99d91fbec9b418fa1d70604ff1c";

Defined in: fhe-disperse/index.ts:76


PAUSER_ROLE

const PAUSER_ROLE: "0x65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a";

Defined in: fhe-disperse/index.ts:78


WITHDRAWER_ROLE

const WITHDRAWER_ROLE: "0x10dac8c06a04bec0b551627dad28bc00d6516b0caacd1c7b345fcdb5211334e4";

Defined in: fhe-disperse/index.ts:80


DEFAULT_ADMIN_ROLE

const DEFAULT_ADMIN_ROLE: "0x0000000000000000000000000000000000000000000000000000000000000000";

Defined in: fhe-disperse/index.ts:82

Functions

resolveEncryptor()

function resolveEncryptor(source): ... | ...;

Defined in: fhe-disperse/encryption.ts:62

Normalize an EncryptorSource to the underlying Encryptor.

Parameters

ParameterType
source... | ...

Returns

... | ...


encryptUint64()

function encryptUint64(__namedParameters): Promise<...>;

Defined in: fhe-disperse/encryption.ts:97

Encrypt a single uint64 value into an externalEuint64 handle + KMS input proof.

Parameters

ParameterType
__namedParametersEncryptUint64Args

Returns

Promise<...>


encryptUint64Batch()

function encryptUint64Batch(__namedParameters): Promise<...>;

Defined in: fhe-disperse/encryption.ts:133

Encrypt N uint64 values into N handles bound by a single input proof.

Used by disperse to encrypt amounts[] and the two subtotals in a single round-trip. Handles are returned in the same order as values.

For disperseConfidentialTokens / disperseConfidentialTokensWithTokenFee: the last two entries in values should be [subtotal0, subtotal1] and the corresponding handles[n-2] / handles[n-1] are the subtotal handles.

Parameters

ParameterType
__namedParametersEncryptUint64BatchArgs

Returns

Promise<...>


createConfidentialDisperseClient()

function createConfidentialDisperseClient(config): ConfidentialDisperseClient;

Defined in: fhe-disperse/singleton.ts:1755

Create a ConfidentialDisperseClient. Mirrors viem's create* convention.

Parameters

ParameterType
configConfidentialDisperseClientConfig

Returns

ConfidentialDisperseClient

Example

const client = createConfidentialDisperseClient({
publicClient,
walletClient,
address: "0x...",
encryptor,
});

computeSubtotals()

function computeSubtotals(amounts): {
group0: ...;
group1: ...;
};

Defined in: fhe-disperse/subtotals.ts:11

Compute the two FHE-encrypted subtotals the singleton expects for wallet-mode disperses.

The contract distributes amounts across two subwallets using the rule: group0 = first (baseSize + remainder) recipients → wallet0 group1 = remaining baseSize recipients → wallet1

This matches _distributeFromWallets in DisperseConfidential.sol.

Parameters

ParameterType
amounts...[]

Returns

{
group0: ...;
group1: ...;
}
group0
group0: ...;
group1
group1: ...;