Files
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

342 lines
10 KiB
Plaintext

# Hanzo Bootnode — ZAP Schema
#
# Public typed surface for the Bootnode subsystem (multi-chain Web3 API,
# token/NFT/transfers/wallets/webhooks/AA/bundler/gas/fleets/infra).
# Mounted into superbase per HIP-0106; addressable in-process via the
# generated Go client and over-wire via ZAP RPC.
#
# Code generation:
# zapc generate bootnode.zap --lang go --out ./zap/gen/
#
# Brand policy: ZAP only. Never "Cap'n Proto" / .capnp anywhere on the
# public surface (see ~/.claude/CLAUDE.md + HIP-0106).
@version 1.0.0
# ── Enums ────────────────────────────────────────────────────────────────
enum Chain
ethereum
polygon
arbitrum
optimism
base
bsc
avalanche
gnosis
celo
linea
scroll
zksync
blast
mantle
metis
zora
opbnb
bitcoin
solana
aptos
flow
berachain
sei
sonic
tron
ton
lux
enum Network
mainnet
sepolia
holesky
fuji
devnet
testnet
localnet
enum WebhookEvent
addressActivity
minedTransaction
nftActivity
tokenTransfer
internalTransfer
graphql
enum NodeProvider
docker
kubernetes
process
helm
# ── RPC ──────────────────────────────────────────────────────────────────
struct RPCRequest
chain Chain
network Network
method Text
params Text # JSON-encoded params array
id Int64
struct RPCResponse
jsonrpc Text
id Int64
result Text # JSON-encoded result
error Text # JSON-encoded error or empty
blockNumber UInt64
cached Bool
# ── Tokens ───────────────────────────────────────────────────────────────
struct TokenBalance
contract Text
symbol Text
name Text
decimals Int32
balance Text # bigint as string
balanceUsd Float64
struct TokenMetadata
contract Text
chain Chain
symbol Text
name Text
decimals Int32
logo Text
totalSupply Text
# ── NFTs ─────────────────────────────────────────────────────────────────
struct NFTMetadata
contract Text
tokenId Text
name Text
description Text
image Text
attributes Text # JSON-encoded
tokenUri Text
chain Chain
struct NFTCollection
contract Text
chain Chain
name Text
symbol Text
totalSupply Text
ownerCount Int64
# ── Transfers ───────────────────────────────────────────────────────────
struct Transfer
chain Chain
txHash Text
blockNumber UInt64
fromAddr Text
toAddr Text
value Text
asset Text
category Text # external | internal | erc20 | erc721 | erc1155
timestamp Int64
# ── Smart Wallets (ERC-4337) ────────────────────────────────────────────
struct SmartWallet
address Text
chain Chain
owner Text
factory Text
salt Text
nonce UInt64
deployed Bool
createdAt Int64
struct UserOp
sender Text
nonce Text
initCode Text
callData Text
callGasLimit Text
verificationGasLimit Text
preVerificationGas Text
maxFeePerGas Text
maxPriorityFeePerGas Text
paymasterAndData Text
signature Text
struct UserOpReceipt
userOpHash Text
sender Text
nonce Text
success Bool
txHash Text
blockNumber UInt64
gasUsed Text
# ── Gas Manager ─────────────────────────────────────────────────────────
struct GasPrices
chain Chain
slow Text
standard Text
fast Text
baseFee Text
maxPriorityFeePerGas Text
updatedAt Int64
struct GasPolicy
id Text
orgId Text
name Text
chain Chain
maxGwei Text
dailyLimitUsd Float64
enabled Bool
# ── Webhooks ────────────────────────────────────────────────────────────
struct Webhook
id Text
orgId Text
url Text
chain Chain
event WebhookEvent
filters Text # JSON-encoded
secret Text
active Bool
createdAt Int64
struct WebhookDelivery
id Text
webhookId Text
status Text
responseCode Int32
attempts Int32
payload Text
createdAt Int64
# ── API Keys / Projects ─────────────────────────────────────────────────
struct Project
id Text
orgId Text
name Text
createdAt Int64
struct APIKey
id Text
projectId Text
orgId Text
keyHash Text
name Text
scopes List(Text)
rateLimit Int32
createdAt Int64
struct CreateAPIKeyResult
apiKey APIKey
plaintext Text # returned ONCE on creation, never again
# ── Fleets / Nodes / Infra ──────────────────────────────────────────────
struct Fleet
id Text
orgId Text
chain Chain
network Network
clusterId Text
replicas Int32
status Text
createdAt Int64
struct Node
id Text
orgId Text
name Text
chain Chain
network Network
provider NodeProvider
rpcPort Int32
wsPort Int32
status Text
containerId Text
createdAt Int64
struct Cluster
id Text
orgId Text
name Text
region Text
nodeCount Int32
status Text
# ── Usage / Billing surface (Bootnode reports CU to Commerce) ───────────
struct UsageRecord
orgId Text
projectId Text
chain Chain
method Text
computeUnits Int32
timestamp Int64
struct UsageSummary
orgId Text
total Int64
periodStart Int64
periodEnd Int64
# ── Service Interface ───────────────────────────────────────────────────
interface BootnodeService
# RPC proxy
rpc (req RPCRequest) -> (resp RPCResponse)
# Tokens
tokenBalances (chain Chain, address Text) -> (balances List(TokenBalance))
tokenMetadata (chain Chain, contract Text) -> (metadata TokenMetadata)
# NFTs
nftMetadata (chain Chain, contract Text, tokenId Text) -> (metadata NFTMetadata)
nftCollection (chain Chain, contract Text) -> (collection NFTCollection)
nftsOwned (chain Chain, address Text) -> (items List(NFTMetadata))
# Transfers
listTransfers (chain Chain, address Text) -> (transfers List(Transfer))
# Smart wallets
createSmartWallet (chain Chain, owner Text) -> (wallet SmartWallet)
getSmartWallet (address Text) -> (wallet SmartWallet)
# Bundler (ERC-4337)
sendUserOp (chain Chain, op UserOp) -> (hash Text)
getUserOpReceipt (chain Chain, hash Text) -> (receipt UserOpReceipt)
# Gas
gasPrices (chain Chain) -> (prices GasPrices)
sponsorUserOp (chain Chain, op UserOp, policyId Text) -> (paymasterAndData Text)
# Webhooks
createWebhook (webhook Webhook) -> (created Webhook)
listWebhooks (orgId Text) -> (webhooks List(Webhook))
deleteWebhook (id Text) -> (ok Bool)
# API keys
createAPIKey (orgId Text, projectId Text, name Text, scopes List(Text)) -> (result CreateAPIKeyResult)
listAPIKeys (orgId Text) -> (keys List(APIKey))
revokeAPIKey (orgId Text, id Text) -> (ok Bool)
# Fleets
createFleet (fleet Fleet) -> (created Fleet)
listFleets (orgId Text) -> (fleets List(Fleet))
scaleFleet (id Text, replicas Int32) -> (fleet Fleet)
deleteFleet (id Text) -> (ok Bool)
# Nodes (single-instance blockchain nodes via Docker/K8s)
deployNode (node Node) -> (created Node)
listNodes (orgId Text) -> (nodes List(Node))
startNode (id Text) -> (ok Bool)
stopNode (id Text) -> (ok Bool)
deleteNode (id Text) -> (ok Bool)
# Usage (internal — Bootnode → Commerce)
recordUsage (record UsageRecord) -> (ok Bool)
getUsage (orgId Text, periodStart Int64, periodEnd Int64) -> (summary UsageSummary)