Reference
Configuration
setupMixTunnel(opts) accepts the full smolmix-wasm SetupOpts surface plus one TS-layer addition (debug). Pass any subset; every field has a default (listed in SetupMixTunnelOpts).
await setupMixTunnel({
// Pin a specific IPR (otherwise auto-discovered from the topology).
preferredIpr: 'D1rrUqJY9pesL3pTaMaxLnpZGGYQ4ZpZwpQXCqaeBXTW.6PpFkRvF...',
// Cover traffic and Poisson timing are ON by default. Setting these disables
// them for lower latency and bandwidth, at the cost of traffic-analysis
// resistance (it drops timing-correlation resistance at the entry and exit).
disableCoverTraffic: true,
disablePoissonTraffic: true,
// Verbose console tracing from smolmix-wasm. Useful while integrating.
debug: true,
});The complete option surface (IPR pinning, SURB budgets, DNS server overrides, TCP/connect timeouts, gateway selection) is documented in the SetupMixTunnelOpts type reference.
Call setupMixTunnel once. The WASM tunnel is one-shot per page: the first call brings it up, and a second call rejects with tunnel already initialised. Because the feature packages share that one tunnel, calling it from mix-fetch is enough for mix-dns and mix-websocket too. If more than one call site might invoke it, guard with getTunnelState() and skip setup when the state is already ready.
Tunnel state
getTunnelState() returns a tagged state for surfacing connection status in the UI. The five states are:
| State | Meaning |
|---|---|
connecting | Default before setupMixTunnel() completes. |
ready | Tunnel is up. Feature packages can issue requests. |
shutting_down | disconnectMixTunnel() in progress. |
shutdown | Cleanly torn down. The WASM is no longer usable. |
failed | Setup or runtime error. Carries a reason; the other four states have no extra fields. |
reason is a tagged object, not a string. It is either
{ kind: 'task_exited', task: 'bridge' | 'reactor' } or { kind: 'task_panicked' }, so
switch on reason.kind rather than printing it directly.
TunnelState is a discriminated union, so narrow on state before reading reason:
const tunnel = await getTunnelState();
if (tunnel.state === 'failed') {
const { reason } = tunnel;
console.error(
reason.kind === 'task_exited'
? `Tunnel failed: the ${reason.task} task exited`
: 'Tunnel failed: a task panicked',
);
}Each variant is exported under its own name (TunnelConnecting, TunnelReady,
TunnelShuttingDown, TunnelShutdown, TunnelFailed) for writing type guards.
await setupMixTunnel() resolves only once the tunnel is ready, so most apps never need to read the state. Poll getTunnelState() only to drive a separate status indicator. The transitions are coarse (no progress percentage during connecting); the underlying connection events are visible via debug: true in the console.