Skip to main content

PoolSessionBuilder

PoolSessionBuilder wires SDK configuration to a runnable PoolSession. There are two paths: a fluent builder with optional .withX() overrides, and a one-call create() shortcut for the simple case.

static create(config: PoolSessionSimpleConfig): Promise<PoolSession>
static fromConfig<Cfg extends PoolSessionBuilderConfig>(config: Cfg): PoolSessionBuilder<Cfg>
create(): Promise<PoolSession> // instance terminator

A builder is single-use: after a successful create() it is consumed, and reusing it throws InvalidBuilderConfig. Validation happens in the instance create(), not in fromConfig.

Two construction paths

Simple: one call

const session = await PoolSessionBuilder.create({
chainId: 11155111,
rpcUrl,
ownerAddress,
protocolKeys,
aspUrl: "https://api-dev.0xbow.io",
relayers,
circuitArtifactsDir: "/path/to/circuits", // Node only
});

Fluent: for custom interactors

import { FetchCircuitArtifacts } from "./FetchCircuitArtifacts";

const session = await PoolSessionBuilder
.fromConfig({
chainId,
rpcUrl,
ownerAddress,
protocolKeys,
aspUrl,
relayers,
walletInteractor: { type: "viem", walletClient },
})
.withCircuitArtifacts(new FetchCircuitArtifacts("/circuits")) // browser
.create();

FetchCircuitArtifacts is a sample-app helper, not an SDK export. Copy v2-monorepo/apps/sample-web/src/FetchCircuitArtifacts.ts or provide your own ICircuitArtifacts implementation.

Config fields

FieldTypeRequiredNotes
chainIdnumberyesSepolia is 11155111
rpcUrlstringyesHTTPS JSON-RPC endpoint
ownerAddressAddressyesthe address that derived protocolKeys
protocolKeysProtocolKeysyes*not needed with .withKeystoreManager(...)
aspUrlstringyes*or ipfsGatewayUrl, or .withAspDataProvider(...)
relayersRelayerInfo[]yes*at least one entry, unless .withRelayerInteractor(...)
deploymentDeploymentAddressesnodefaults to DEPLOYMENTS[chainId]
walletInteractorWalletInteractorConfigno{type: "viem", walletClient} or {type: "EIP1193", provider}; required for execute paths, omit for read-only sessions
persistentStoragePersistentStorageConfigno{type: "local", prefix?} (browser), {type: "file", dirPath, filename?} (Node), {type: "memory"}; without it, note state lives in memory only
circuitArtifactsDirstringnolocal artifacts directory (Node); mutually exclusive with the IPFS path
circuitGatewayUrlsstring[]noIPFS gateways for artifacts; requires circuitManifest
circuitManifestCircuitManifestno*required on the IPFS artifacts path, with pinned CIDs; there is no silent default
ipfsGatewayUrlstringnoswitches the ASP data provider to IPFS
aspPublicKeyPublicKeynofetched from the provider on first use when omitted
httpClientConfigHTTPClientConfignotimeouts and fetch options for the shared HTTP client
loggerILoggernoshared across services

Fluent overrides

Every override returns the builder. Overrides that replace something the config also describes are conflict-guarded: supplying both the config field and the override fails create() with an InvalidBuilderConfig telling you to remove one.

OverrideReplacesConflicts with config field
withKeystoreManager(impl)key managementprotocolKeys
withRelayerInteractor(impl)relayer clientrelayers
withCircuitArtifacts(impl)artifact loadingcircuitArtifactsDir, circuitGatewayUrls
withCircuitCacheStore(store)artifact cachinglocal artifacts path
withAspDataProvider(impl)ASP data sourceaspUrl, ipfsGatewayUrl
withAspClient(impl)ASP clientaspPublicKey
withEntrypointInteractor(impl), withKeystoreInteractor(impl), withVaultInteractor(impl), withAspRegistryInteractor(impl)per-contract interactorsdeployment
withStorageService(impl), withNoteStorageAdapter(impl), withPaymentRequestStorageAdapter(impl)persistencepersistentStorage (and each other, partially)
withWalletInteractor(impl)walletwalletInteractor
withCryptoService, withHashService, withMerkleService, withHttpClient, withRpcInteractor, withGroth16Prover, withProofService, withWitnessPreparationService, withNoteComputationService, withNoteManager, withNoteDiscoveryService, withPaymentRequestServiceindividual servicesnone

Errors

create() throws InvalidBuilderConfig for every configuration failure except one: when deployment is omitted and chainId has no entry in DEPLOYMENTS, it throws UnsupportedChainId. Both classes are runtime exports of the package, so instanceof works for these two. The conditions behind InvalidBuilderConfig:

  • schema validation failure (the message carries the first Zod issue as path: message; log the full issues array when debugging, see Debugging)
  • a config field conflicting with a fluent override (the message names both)
  • reusing a consumed builder
  • missing aspUrl/ipfsGatewayUrl without an ASP override; missing protocolKeys without a keystore-manager override; an empty or missing relayers array without a relayer override
  • the IPFS artifacts path without an explicit circuitManifest, or a manifest with no pinned CIDs
  • a wallet that returns no accounts, or whose account or chain doesn't match ownerAddress / chainId

Versions and compatibility

protocolKeys requires a revocableKeyIndex field ("0x0" for fresh accounts). The SDK, circuits, and deployed verifiers must all belong to the same deployment set (see Sepolia V9 addresses).