Developer Guide¶
Project Structure¶
├── backend/
│ ├── hashscope/
│ │ ├── proxy/ # TCP proxy, sessions, relay logic
│ │ ├── stratum/ # parsers/encoders, message models
│ │ ├── capture/ # event model, storage (in-memory ring buffers)
│ │ ├── nostr/ # Nostr client, schemas, constants
│ │ │ ├── client.py # WebSocket connect, publish, subscribe
│ │ │ ├── schemas.py # ShareEvent/TelemetryEvent models
│ │ │ └── constants.py # event kinds, tag conventions
│ │ ├── api/ # FastAPI app: REST + WebSocket to UI
│ │ └── config/ # Pydantic settings
│ └── tests/ # pytest
├── agents/
│ └── hashscope_agent/
│ ├── main.py # agent entrypoint
│ ├── pool_client.py # Stratum client
│ └── nostr_client.py # Nostr subscription + telemetry
├── frontend/
│ ├── src/
│ │ ├── components/ # React + TypeScript (shadcn/ui)
│ │ ├── pages/ # Route pages
│ │ └── lib/ # API client, utilities
│ └── package.json
└── docker-compose.yml
Technology Stack¶
Backend¶
- Python 3.11+
- FastAPI - Web framework
- asyncio - Async I/O for TCP
- Pydantic - Data validation
- uvicorn - ASGI server
- pytest - Testing
Frontend¶
- React 18 - UI framework
- TypeScript - Type safety
- Vite - Build tool
- shadcn/ui - Component library
- Tailwind CSS - Styling
- React Router - Routing
- Mermaid - Diagrams
Infrastructure¶
- Docker - Containerization
- docker-compose - Orchestration
- nginx - Frontend serving
Development Setup¶
Backend¶
cd backend
pip install -r requirements.txt
# Set required config
export POOL_HOST=stratum+tcp://your-test-pool.com
export POOL_PORT=3333
# Run tests
pytest -q
# Run in development
uvicorn hashscope.api.app:create_app --factory --reload --host 0.0.0.0 --port 8000
Frontend¶
Frontend dev server runs on http://localhost:5173 and proxies API requests to backend.
Agent¶
cd agents
pip install -r requirements.txt
# Set config
export AGENT_POOL_HOST=stratum+tcp://pool.example.com
export AGENT_NOSTR_RELAY_URL=wss://relay.damus.io
export AGENT_RUN_ID=test-run-123
export AGENT_WORKER_NAME=test_agent
# Run agent
python -m hashscope_agent.main
Coding Standards¶
Python¶
- Type hints required for public functions
- Use
rufforblackfor formatting - No blocking calls in async code
- Structured logging (JSON logs preferred)
- Best-effort parsing - never crash on malformed input
TypeScript¶
- Strict mode enabled
- Functional components with hooks
- Prefer composition over complex components
- Type all props and state
Key Principles¶
- Never modify message contents - byte-for-byte relay
- Best-effort parsing - parse errors should not crash the proxy
- Security first - treat all input as untrusted
- Type safety - use type hints and TypeScript strictly
- Nostr events must be signed - all events require valid signatures
- Publishing never blocks relaying - background tasks only
Message Model¶
CapturedMessage¶
{
"id": str, # Unique message ID
"ts_recv": datetime, # When received by proxy
"ts_fwd": datetime, # When forwarded
"direction": enum, # miner_to_pool | pool_to_miner | hashscope_to_pool
"session_id": str, # Session identifier
"peer": str, # IP:port of peer
"raw": str, # Raw bytes (escaped string or base64)
"decoded": dict, # Parsed JSON-RPC
"parse_error": str, # Error message if parse failed
"size_bytes": int # Message size
}
Testing¶
# Backend tests
cd backend
pytest -q
# Run specific test
pytest tests/test_stratum_parser.py -v
# Frontend lint
cd frontend
npm run lint
Docker Workflow¶
CRITICAL: After making ANY code changes, rebuild affected services:
# Modified backend code or requirements.txt
docker compose build backend
# Modified frontend code or package.json
docker compose build frontend
# Modified agent code
docker compose build agents
# Update running containers
docker compose up -d
# Complete refresh
docker compose down
docker compose build
docker compose up -d
Performance Characteristics¶
Scalability¶
- Concurrent miners: Limited by system resources
- Messages/second: Thousands (async I/O)
- Memory usage: Bounded by ring buffer size
- CPU usage: Low (mostly I/O bound)
Latency¶
- Relay overhead: <1ms (in-memory copy)
- Parse overhead: ~0.1ms per message
- WebSocket broadcast: <10ms to all clients
Extension Points¶
The architecture supports future enhancements:
- Message Routing - Add routing rules in ProxySession
- Persistent Storage - Swap CaptureStorage implementation
- Authentication - Add middleware to FastAPI
- Message Modification - Add transform step before forwarding (future iterations)
- Additional Relays - Secondary Nostr relays for redundancy