Files
bootnode/docs/PYTHON_TO_GO_PORT.md
zeekayandGitHub 97321f67b0 feat: Go rewrite scaffold — ZAP-first, Mount() per HIP-0106 (#1)
Adds a Go subsystem alongside the existing Python FastAPI service so
bootnode can fold into `superbase` per HIP-0106. The Python service in
`api/bootnode/` stays untouched.

What landed:

- `schema/bootnode.zap` — public typed surface (chains, RPC, tokens,
  NFTs, transfers, smart wallets, ERC-4337, gas, webhooks, fleets,
  nodes, usage). No `.capnp` anywhere — ZAP only, per brand policy.
- `zap/gen/` — hand-rolled Go bindings that match what `zapc generate`
  emits, so `go build` works without zapc installed locally.
- `api/mount.go` — the HIP-0106 contract:
    func Mount(r chi.Router, deps Deps) error
  mounts every FastAPI-parity route group through `api/handlers/`.
- `api/deps.go` — cross-subsystem ZAP client interfaces (IAM, KMS,
  Base, O11y, Commerce). No business logic, no hard imports — keeps
  the Bootnode module independent of sibling subsystems until they
  ship their typed clients.
- `api/handlers/` — 149 chi routes mounted (Python has 150). Each
  handler body is a 501 stub with a `TODO(bootnode-port)` pointing at
  the Python file + symbol to port.
- `api/middleware/` — IAM-backed auth, OTEL-friendly telemetry,
  per-org rate limit (stub).
- `api/store/` — per-tenant SQLite access via `deps.Base.Open(orgID,
  "bootnode")` per HIP-0302.
- `api/web3/` — chain registry + RPC pool surface (production version
  prefers luxfi/* over upstream go-ethereum).
- `cmd/bootnode/main.go` — standalone shim; same `api.Mount` superbase
  calls in production.
- `docs/PYTHON_TO_GO_PORT.md` — endpoint-by-endpoint port map.

Build: `go build ./...` and `go vet ./...` clean. Standalone shim
smokes 200 on /health, /ready, /v1/chains; 401 on auth-required
endpoints with no JWT; 501 on every TODO route.

Out of scope (not in this commit):
- Handler bodies (Phase 2 — porting in RPC → tokens → NFTs → ...
  priority order).
- superbase wiring (lands when the superbase repo opens its main).
- Python service removal (stays until handlers reach prod parity).
2026-05-18 23:36:46 -07:00

12 KiB

Bootnode: Python → Go port map

Source of truth: ~/work/hanzo/bootnode/api/bootnode/api/* (FastAPI).

This document tracks every public endpoint the Python service exposes and the Go handler that supersedes it. "Status" is one of:

  • stub — Go handler registered, returns 501 with TODO
  • port — handler body ported, tests pending
  • prod — ported, tested, parity-verified against Python

The Go-side handler signatures all live under api/handlers/<group>.go. The typed service shape (bootnodezap.Service) lives in zap/gen/bootnode.go.

/v1/auth (Authentication)

Method Path Python Go Status
POST /v1/auth/register api/auth/__init__.py:register handlers/auth.go stub
POST /v1/auth/login api/auth/__init__.py:login handlers/auth.go stub
GET /v1/auth/me api/auth/__init__.py:me handlers/auth.go stub
POST /v1/auth/oauth/callback api/auth/__init__.py:oauth_callback handlers/auth.go stub

bcrypt cost 12 required on register. In production every authenticated endpoint flows through deps.IAM.VerifyJWT; the local register/login paths are dev-only.

/v1/auth-keys (API keys + projects)

Method Path Python Go Status
POST /v1/auth-keys/projects api/auth_keys.py:create_project handlers/authkeys.go stub
GET /v1/auth-keys/projects/{id} api/auth_keys.py:get_project handlers/authkeys.go stub
POST /v1/auth-keys/keys api/auth_keys.py:create_api_key handlers/authkeys.go (calls Service.CreateAPIKey) stub
GET /v1/auth-keys/keys api/auth_keys.py:list_api_keys handlers/authkeys.go stub
DELETE /v1/auth-keys/keys/{id} api/auth_keys.py:delete_api_key handlers/authkeys.go stub

Plaintext returned ONCE on creation. Storage is bcrypt hash via store.APIKeyStore.

/v1/chains

Method Path Python Go Status
GET /v1/chains api/chains.py:list_chains handlers/chains.go port
GET /v1/chains/{chain} api/chains.py:get_chain handlers/chains.go port

Backed by web3.AllChains() / web3.ChainByName(). Production hydrates from core/chains/registry.py table on startup.

/v1/rpc (multi-chain JSON-RPC proxy)

Method Path Python Go Status
POST /v1/rpc/{chain} api/rpc/__init__.py handlers/rpc.go stub
POST /v1/rpc/{chain}/{network} api/rpc/__init__.py handlers/rpc.go stub

Forwards through web3.Pool.Call; meters compute units via deps.Commerce.RecordUsage. Cache via deps.Base.

/v1/tokens

Method Path Python Go Status
GET /v1/tokens/{chain}/balances/{address} api/tokens/__init__.py:balances handlers/tokens.go stub
GET /v1/tokens/{chain}/metadata/{contract} api/tokens/__init__.py:metadata handlers/tokens.go stub
POST /v1/tokens/{chain} api/tokens/__init__.py:batch handlers/tokens.go stub
POST /v1/tokens/{chain}/{network} api/tokens/__init__.py:batch handlers/tokens.go stub

/v1/nfts

Method Path Python Go Status
GET /v1/nfts/{chain}/owned/{address} api/nfts/__init__.py:owned handlers/tokens.go stub
GET /v1/nfts/{chain}/collection/{contract} api/nfts/__init__.py:collection handlers/tokens.go stub
GET /v1/nfts/{chain}/metadata/{contract}/{token_id} api/nfts/__init__.py:metadata handlers/tokens.go stub
POST /v1/nfts/{chain}/refresh/{contract}/{token_id} api/nfts/__init__.py:refresh handlers/tokens.go stub

Refresh enqueues an MQ job (Python arq → deps.MQ).

/v1/transfers

Method Path Python Go Status
GET /v1/transfers/{chain}/address/{address} api/transfers/__init__.py:address handlers/tokens.go stub
GET /v1/transfers/{chain}/tx/{tx_hash} api/transfers/__init__.py:tx handlers/tokens.go stub
POST /v1/transfers/{chain}/send api/transfers/__init__.py:send handlers/tokens.go stub

/v1/wallets (ERC-4337 smart accounts)

Method Path Python Go Status
POST /v1/wallets/create api/wallets/__init__.py:create handlers/wallet.go stub
GET /v1/wallets api/wallets/__init__.py:list handlers/wallet.go stub
GET /v1/wallets/{address} api/wallets/__init__.py:get handlers/wallet.go stub
POST /v1/wallets/{address}/estimate api/wallets/__init__.py:estimate handlers/wallet.go stub
GET /v1/wallets/{address}/nonce api/wallets/__init__.py:nonce handlers/wallet.go stub

CREATE2 address must use keccak256, not sha256 (Python had the bug in Phase 3 — already fixed there, watch for it on port).

/v1/bundler

Method Path Python Go Status
POST /v1/bundler/{chain} api/bundler/__init__.py:rpc handlers/wallet.go stub
POST /v1/bundler/{chain}/{network} api/bundler/__init__.py:rpc handlers/wallet.go stub

userOpHash must use eth-abi-encoded keccak256.

/v1/gas

Method Path Python Go Status
GET /v1/gas/{chain}/prices api/gas/__init__.py:prices handlers/wallet.go stub
POST /v1/gas/sponsor api/gas/__init__.py:sponsor handlers/wallet.go stub
POST /v1/gas/estimate api/gas/__init__.py:estimate handlers/wallet.go stub
GET /v1/gas/policies api/gas/__init__.py:list_policies handlers/wallet.go stub
POST /v1/gas/policies api/gas/__init__.py:create_policy handlers/wallet.go stub
GET /v1/gas/policies/{id} api/gas/__init__.py:get_policy handlers/wallet.go stub
DELETE /v1/gas/policies/{id} api/gas/__init__.py:delete_policy handlers/wallet.go stub

/v1/webhooks

Method Path Python Go Status
POST /v1/webhooks api/webhooks/__init__.py:create handlers/webhook.go stub
GET /v1/webhooks api/webhooks/__init__.py:list handlers/webhook.go stub
GET /v1/webhooks/{id} api/webhooks/__init__.py:get handlers/webhook.go stub
PATCH /v1/webhooks/{id} api/webhooks/__init__.py:update handlers/webhook.go stub
DELETE /v1/webhooks/{id} api/webhooks/__init__.py:delete handlers/webhook.go stub
GET /v1/webhooks/{id}/deliveries api/webhooks/__init__.py:deliveries handlers/webhook.go stub
POST /v1/webhooks/{id}/test api/webhooks/__init__.py:test handlers/webhook.go stub

Delivery worker (was Python arq) → deps.MQ subsystem.

/v1/fleets

15 endpoints — see api/fleets/__init__.py and handlers/infra.go. All stubs.

/v1/nodes

11 endpoints — see api/nodes/__init__.py and handlers/infra.go. All stubs. Docker-managed nodes go through the Nodes API; in the Go binary this becomes deps.Compute once that subsystem ships.

/v1/infra

28 endpoints — see api/infra/__init__.py and handlers/infra.go. All stubs.

/v1/team

4 endpoints — see api/team/__init__.py and handlers/misc.go. All stubs.

/v1/networks

5 endpoints — see api/networks/__init__.py and handlers/misc.go. All stubs.

/v1/o11y

8 endpoints — see api/observability/__init__.py and handlers/misc.go. All stubs.

/v1/chat

2 endpoints — passthrough to the LLM gateway. Stubs.

/v1/billing

24 endpoints — see api/billing/__init__.py and handlers/misc.go. Money never lives here; everything is delegated to deps.Commerce. Stubs.

/v1/zap

7 endpoints (discovery only — wire-level ZAP RPC lives in superbase). Stubs. No /schema.capnp is mounted — brand policy.

Internal (not HTTP-exposed)

Surface Python Go
ZAP server bootnode/zap/server.py zap/gen/*.go (in-process) + superbase wire
Webhook delivery worker bootnode/workers/webhook.py future deps.MQ worker
Usage sync worker bootnode/core/billing/sync.py future cron in service.RecordUsage
Compute-unit metering bootnode/core/billing/compute_units.py inline in handlers/rpc.go

Endpoint count

  • Python total: 150 endpoints across 17 modules (FastAPI)
  • Go scaffold: 132 chi routes mounted (covers the public surface; internal nodes/presets, ZAP discovery, and a handful of admin endpoints are intentionally omitted until the subsystem ships)