The bootnode-web CR set NEXT_PUBLIC_API_URL=https://api.web3.hanzo.ai and NEXT_PUBLIC_WS_URL=wss://ws.web3.hanzo.ai. The image is a static export served by the Go hanzoai/static binary, so nothing reads container env — the live bundle carried the build-time default api.bootno.de and ws.bootno.de instead. The CR promised one thing and the app did another, on every host it serves. Exactly the failure already fixed for the IAM knobs in this file: one image, many white-label hosts, so a build-time NEXT_PUBLIC_* is a single global that cannot express per-host anything. The brand catalog can, because it resolves from the hostname at runtime. web3.hanzo.ai now gets its own API and WS origins. Verified the two backends are the same service before repointing: `/` and `/v1/chains` return byte-identical bodies on api.bootno.de and api.web3.hanzo.ai, and both answer 401 on /v1/auth/me; ws.web3.hanzo.ai serves. bootno.de keeps api.bootno.de via the built-in default. pars and zoo are left alone deliberately: api.pars.network and api.zoo.network exist, but nothing declared them as those brands' backends and cloud.zoo.network does not resolve at all — I am not inventing a binding I cannot verify. (Note for whoever does: lib/docs-config.ts derives `api.${brand.domain}`, which yields the nonexistent api.cloud.pars.network — that derivation is wrong for the cloud.* hosts.)
Bootnode
Web3 Backend in a Box - Run locally or deploy to cloud.
Go rewrite (HIP-0106) in progress. The current production service is the Python FastAPI app under
api/. A Go scaffold that mounts intosuperbaseper HIP-0106 lives alongside it —api/,cmd/bootnode/,schema/,zap/. Seedocs/PYTHON_TO_GO_PORT.mdfor the endpoint-by-endpoint port map and the new Go README section below.
Quick Start
docker compose up -d
Done. Your Web3 backend is running:
- API: http://localhost:8000
- Dashboard: http://localhost:3001
- API Docs: http://localhost:8000/docs
Features
| API | Description |
|---|---|
POST /v1/rpc/{chain} |
Multi-chain JSON-RPC proxy |
WS /v1/ws/{chain} |
Real-time blockchain subscriptions |
GET /v1/tokens/{chain}/balances/{address} |
Token balances & metadata |
GET /v1/nfts/{chain}/owned/{address} |
NFT ownership & metadata |
POST /v1/webhooks |
Event-driven notifications |
POST /v1/wallets/create |
ERC-4337 smart wallets |
POST /v1/bundler/{chain} |
UserOp bundling |
POST /v1/gas/sponsor |
Gas sponsorship |
Supported Chains
L1: Ethereum, BNB Chain, Avalanche, Solana, Bitcoin
L2: Arbitrum, Optimism, Base, Polygon, zkSync, Scroll, Linea, Blast
Development
# API (Python 3.12+)
cd api && uv sync && uvicorn bootnode.main:app --reload --port 8000
# Dashboard (Node 22+)
cd web && pnpm install && pnpm dev
Deploy
Self-hosted
docker compose -f docker-compose.prod.yml up -d
# or
kubectl apply -f infra/k8s/
Hanzo Cloud
hanzo deploy
Visit web3.hanzo.ai for managed hosting.
License
Apache-2.0
Go rewrite (HIP-0106)
The Go subsystem mounts into superbase (the unified Hanzo Cloud
binary). It exposes a single Mount(r chi.Router, deps api.Deps) error
entry point and a public ZAP schema (schema/bootnode.zap) covering
every cross-subsystem type.
bootnode/
schema/bootnode.zap # public typed surface (ZAP)
zap/gen/ # zapc-generated Go (hand-stubs today)
api/ # subsystem code (chi handlers + store)
mount.go # HIP-0106 contract
deps.go # IAM/KMS/Base/O11y/Commerce interfaces
handlers/ # one MountXxx per FastAPI route group
middleware/ # auth, telemetry, rate-limit
store/ # per-tenant SQLite via deps.Base
web3/ # chain registry + RPC pool
cmd/bootnode/main.go # standalone dev shim
docs/PYTHON_TO_GO_PORT.md # endpoint-by-endpoint mapping
Build
go build ./...
go vet ./...
go run ./cmd/bootnode # listens on :8100 (BOOTNODE_ADDR to override)
Generate ZAP bindings
cd zap && make gen # no-op if zapc isn't installed
zapc lives at ~/work/hanzo/zap/zapc-rs/. Brand policy: no
.capnp files, no "Cap'n Proto" references on the public surface
(HIP-0106).