mirror of
https://github.com/hanzoai/bootnode.git
synced 2026-10-25 02:31:30 +00:00
`bootnode/db/__init__.py` imported and re-exported three names that models.py
does not define, so `import bootnode.db` raised ImportError on main. Every
consumer died with it: the e2e job's init_db(), the nodes API, the MPC API, the
keys API, the seed. Prod is unaffected only because it runs image 1.0.1, built
before this landed.
It was invisible because test-api ran
pytest -v --tb=short || echo "No tests yet"
The `|| echo` makes the step exit 0 unconditionally, so CI reported GREEN while
every test module failed to import. That mask is removed; CI can fail honestly.
The consequence was not subtle: docker-release triggers on
`workflow_run: ["CI"] completed`, CI was red, so the image build was SKIPPED
every time — which is why the deployed web image sat at 0.0.1-web from June
while main moved on.
Cluster → renamed OrgCluster at some point; call sites updated.
The `"kind": "Cluster"` CRD strings are correct and untouched.
Node → never existed in ANY revision (checked back to 2026-01-26).
Defined here from the contract the code already declares.
MPCWalletModel → likewise. Distinct from SmartWallet, which is ERC-4337
account abstraction, not threshold signing.
Design, in the terms asked for:
DECOMPLECTED — Node stores DESIRED state only. Sync progress, peer count, block
height, cpu/memory, uptime and the backing pod are facts about the cluster, and
fleet_manager already reads them from the Cluster CR. A copy in this table would
be a second source of truth, stale the instant it is written. That split is why
the model is small; it is the spec half of the spec/status pair the CRD layer
already uses, not a new idea.
TYPED — status/node_type/sync_mode are closed Enums at both the Python and the
column level, not free strings. This class of bug was live: the seed wrote
"running" while NodeStatus offers pending/init/starting/bootstrapping/healthy/
unhealthy/terminated — provably DISJOINT sets, so the dashboard's
`filter(n => n.status === "running")` could never match a backend value and
"active nodes" was structurally always 0. One vocabulary now, defined once in
fleet_models and imported everywhere; seed and both frontend call sites moved
onto it.
SMALL INTERFACE — two properties (`is_serving`, `slug`) and a repr. Everything
else is a column read. No cleverness to undo later.
Flagged, not silently reproduced: MPCWalletModel.encrypted_shares holds key
material in the database. It is encrypted, but the standing rule is that secrets
live in KMS. That column is a migration target, documented in the model.
Verified: `import bootnode.db` succeeds, all three enums resolve, every seed
status value is a member of NodeStatus, web tsc 0 errors, web build exits 0.
Hanzo Nodes API
Multi-chain blockchain infrastructure platform providing RPC, APIs, WebSockets, Webhooks, and ERC-4337 bundling.
Features
- Multi-Chain RPC: 100+ EVM chains with load balancing
- Token API: ERC-20 balances, transfers, prices
- NFT API: ERC-721/1155 ownership, metadata, transfers
- Wallet API: Portfolio tracking, activity history
- WebSocket Subscriptions: Real-time blockchain events
- Webhooks: Event notifications with delivery tracking
- ERC-4337 Bundler: Account abstraction with gasless transactions
- Gas API: Real-time gas estimates and EIP-1559 data
Quick Start
# Start dependencies
docker compose up -d postgres redis clickhouse
# Run API locally
uv run uvicorn bootnode.main:app --reload
# Or with Docker
docker compose up -d
API Endpoints
GET /health- Health checkPOST /v1/rpc/{chain}/{network}- JSON-RPC proxyGET /v1/tokens/{chain}/balance/{address}- Token balancesGET /v1/nfts/{chain}/owner/{address}- NFT ownershipPOST /v1/webhooks- Create webhookWS /v1/ws/{chain}/{network}- WebSocket subscriptions
Environment Variables
DATABASE_URL=postgresql+asyncpg://...
REDIS_URL=redis://...
DATASTORE_URL=clickhouse://...
JWT_SECRET=...
Documentation
- API Docs: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
License
BSD-3-Clause