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
| Field | Type | Required | Notes |
|---|---|---|---|
chainId | number | yes | Sepolia is 11155111 |
rpcUrl | string | yes | HTTPS JSON-RPC endpoint |
ownerAddress | Address | yes | the address that derived protocolKeys |
protocolKeys | ProtocolKeys | yes* | not needed with .withKeystoreManager(...) |
aspUrl | string | yes* | or ipfsGatewayUrl, or .withAspDataProvider(...) |
relayers | RelayerInfo[] | yes* | at least one entry, unless .withRelayerInteractor(...) |
deployment | DeploymentAddresses | no | defaults to DEPLOYMENTS[chainId] |
walletInteractor | WalletInteractorConfig | no | {type: "viem", walletClient} or {type: "EIP1193", provider}; required for execute paths, omit for read-only sessions |
persistentStorage | PersistentStorageConfig | no | {type: "local", prefix?} (browser), {type: "file", dirPath, filename?} (Node), {type: "memory"}; without it, note state lives in memory only |
circuitArtifactsDir | string | no | local artifacts directory (Node); mutually exclusive with the IPFS path |
circuitGatewayUrls | string[] | no | IPFS gateways for artifacts; requires circuitManifest |
circuitManifest | CircuitManifest | no* | required on the IPFS artifacts path, with pinned CIDs; there is no silent default |
ipfsGatewayUrl | string | no | switches the ASP data provider to IPFS |
aspPublicKey | PublicKey | no | fetched from the provider on first use when omitted |
httpClientConfig | HTTPClientConfig | no | timeouts and fetch options for the shared HTTP client |
logger | ILogger | no | shared 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.
| Override | Replaces | Conflicts with config field |
|---|---|---|
withKeystoreManager(impl) | key management | protocolKeys |
withRelayerInteractor(impl) | relayer client | relayers |
withCircuitArtifacts(impl) | artifact loading | circuitArtifactsDir, circuitGatewayUrls |
withCircuitCacheStore(store) | artifact caching | local artifacts path |
withAspDataProvider(impl) | ASP data source | aspUrl, ipfsGatewayUrl |
withAspClient(impl) | ASP client | aspPublicKey |
withEntrypointInteractor(impl), withKeystoreInteractor(impl), withVaultInteractor(impl), withAspRegistryInteractor(impl) | per-contract interactors | deployment |
withStorageService(impl), withNoteStorageAdapter(impl), withPaymentRequestStorageAdapter(impl) | persistence | persistentStorage (and each other, partially) |
withWalletInteractor(impl) | wallet | walletInteractor |
withCryptoService, withHashService, withMerkleService, withHttpClient, withRpcInteractor, withGroth16Prover, withProofService, withWitnessPreparationService, withNoteComputationService, withNoteManager, withNoteDiscoveryService, withPaymentRequestService | individual services | none |
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 fullissuesarray when debugging, see Debugging) - a config field conflicting with a fluent override (the message names both)
- reusing a consumed builder
- missing
aspUrl/ipfsGatewayUrlwithout an ASP override; missingprotocolKeyswithout a keystore-manager override; an empty or missingrelayersarray 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).