For the complete documentation index, see llms.txt. This page is also available as Markdown.

Configuration

How to configure the SDK with createConfig — chains, relayers, provider, signer, and storage.

The SDK uses createConfig to wire together chains, relayers, a provider, an optional signer, and storage into a single configuration object. This guide walks through each piece.

Steps

1. Pick your chains

Import pre-configured chain objects from @zama-fhe/sdk/chains. Each chain includes contract addresses, relayer URLs, and chain IDs.

import { sepolia, mainnet, hoodi } from "@zama-fhe/sdk/chains";
Chain
Chain ID
Description

mainnet

1

Ethereum Mainnet

sepolia

11155111

Sepolia Testnet

hoodi

560048

Hoodi Testnet

ingenTestnet

364301

InGen Testnet

bscTestnet

97

BNB Smart Chain Testnet

hardhat

31337

Local Hardhat node

anvil is also exported as an alias for hardhat (both target chain ID 31337), for Foundry users.

The Sepolia testnet relayer needs no API key — presets like sepolia work as-is, so leave auth unset. Only the Zama-hosted mainnet relayer requires a key; see Authentication.

2. Pick a relayer

Relayers tell the SDK how to run FHE operations on each chain.

Relayer
Environment
Description

web()

Browser

Runs FHE via bundled WASM in the browser

node()

Node.js

Same FHE runtime, server-side

cleartext()

Local dev

No FHE infrastructure — cleartext operations

Chain-specific data (relayerUrl, network, executorAddress, etc.) comes from the chain preset, so a bare call is all most apps need. Each factory also accepts an optional options object forwarded to @fhevm/sdk for per-client tuning (e.g. batchRpcCalls, fheEncryptionKey).

If you need to override a chain field (e.g. proxy relayer requests through your backend), spread the preset in the chains array:

3. Set up chain access

The SDK separates read access (provider) from wallet authority (signer). The provider handles contract reads and receipt polling. The signer handles signing and write transactions. Both are created automatically by createConfig — you pass your Web3 library's native objects.

For full type information, see the ViemProvider / ViemSigner and EthersProvider / EthersSigner reference pages. You can also implement GenericProvider and GenericSigner for a custom integration.

4. Create the config

createConfig takes your chains, relayers, and signer adapter and returns a config object.

When the built-in adapters don't fit your setup — for example, a server-side relayer that implements GenericSigner directly — use the generic createConfig from @zama-fhe/sdk:

See GenericSigner and GenericProvider for the interfaces your adapter must implement.

MV3 Chrome extensions can use chromeSessionStorage as permitStorage so permits survive service worker restarts:

Your manifest.json must include the "storage" permission. See the Web Extensions guide for manifest configuration, multi-context sharing, and browser close behavior.

Browser apps should proxy relayer requests through a backend to keep the API key secret. See the Authentication guide for the full setup.

5. (Optional) Configure TTLs and event listener

You can tune how long the transport key pair and permits remain valid, and subscribe to lifecycle events for debugging:

When done with the SDK, call sdk.terminate() to unsubscribe wallet listeners and release the SDK's resources.

6. (Optional) Choose a storage backend

The transport key pair is cached so users don't get a wallet popup on every decrypt. By default, createConfig picks the right storage for your environment. Override with the storage field if needed:

Storage
When to use

indexedDBStorage

Browser apps — persists across reloads and sessions

memoryStorage

Tests, scripts, throwaway sessions

asyncLocalStorage

Node.js servers — isolates transport key pair per request

For full storage options see the GenericStorage reference.

7. (Optional) Supply a logger

The SDK is silent by default — it emits no console output of its own. Operation failures always surface through the rejected promise or typed error, never as a stray console.error. To observe internal diagnostics, pass a logger to createConfig:

The logger is a minimal four-level interface — error, warn, info, debug — that console and common logging libraries satisfy directly, so no adapter is needed. The SDK never bundles a logging library or imposes a format; level filtering is left to your logger. Levels follow these conventions:

Level
What the SDK emits

error

Unexpected internal failures only — never failures already surfaced via a rejection

warn

Recoverable or degraded conditions (a fallback path, a retry, a swallowed best-effort write)

info

Reserved for coarse lifecycle milestones; not currently emitted

debug

Verbose diagnostics — relayer request timing, orchestration progress

The logger is configured once here and flows SDK-wide — including into relayer request tracing, the credential store, and the decrypt cache. There is deliberately no per-relayer logger option; createConfig({ logger }) is the single source of truth.

8. (Optional) Tune the FHE runtime

The runtime field configures the underlying @fhevm/sdk WASM runtime — threading, WASM asset loading, and module versions. It is process-global: it applies once per process, not per chain or per relayer.

The knob most apps reach for is thread count:

Field
Effect

numberOfThreads

Number of Web Workers used to parallelise FHE encryption/decryption

singleThread

true forces a single thread — no SharedArrayBuffer required

9. (Optional) Share one transport key pair across signers (B2B2C / WaaS)

By default, every signer gets its own transport key pair. Wallet-as-a-Service operators managing many end-user wallets from one operator-controlled key store can opt into sharing a single key pair across signers with transportKeyPairScope:

Permits stay per-signer regardless of scope. See Security Model for the tradeoff this makes, and Permit Model for how revocation splits into a signer-level tier (revokePermits/clear) and an operator-level one (sdk.permits.revokeTransportKeyPair()).

Shared relayer options

When multiple chains use the same relayer, create it once and reference that single instance from each chain:

Chains that reference the same relayer object — the result of a single web() call — share one FHE backend instance, reducing memory usage.

Next steps

Last updated