A production-ready TypeScript Express server wrapping ChaintracksService from @bsv/wallet-toolbox, featuring a built-in Bulk Headers CDN for hosting and serving blockchain headers to other servers.
# Clone and start
git clone <repository-url>
cd chaintracks-server
docker compose up -d
# That's it! Services are now running:
# - ChaintracksService API: http://localhost:3011
# - Bulk Headers CDN: http://localhost:3012See DOCKER.md for complete Docker documentation.
# Install dependencies
npm install
# Build
npm run build
# Configure
cp .env.example .env
nano .env
# Start
npm startThis server provides two main services:
- Tracks BSV blockchain headers in real-time
- In-memory NoDb storage - no database required
- REST API endpoints for querying headers
- Automatic sync with BSV blockchain
- Event subscriptions for headers and reorgs
- Hosts bulk header files for download by other servers
- Automatic export at 100k block boundaries
- Self-hosting CDN - becomes a headers source for others
- Persistent storage with Docker volumes
- CORS enabled for cross-origin access
Your server can become a CDN node:
- Downloads headers from remote CDN (if local files don't exist)
- Exports headers to filesystem
- Serves headers to other servers via HTTP
- Creates a distributed network of header sources
- Downloads from
SOURCE_CDN_URLon first startup - Exports to filesystem automatically
- Serves via CDN on port 3012
- Updates every 67 hours (400 blocks)
- Triggers export at 100k boundaries
- First run: Downloads from remote CDN
- Subsequent runs: Uses local filesystem
- Automatically exports new headers
- Other servers can use you as a source
ββββββββββββββββββββββββββββββββββββββββββββ
β Other Servers (your clients) β
β SOURCE_CDN_URL=http://yourserver:3012 β
ββββββββββββββ¬ββββββββββββββββββββββββββββββ
β Download headers
β
ββββββββββββββββββββββββββββββββββββββββββββ
β YOUR Server β
β ββββββββββββββββββββββββββββββββββββββ β
β β ChaintracksService (Port 3011) β β
β β - API endpoints β β
β β - Header queries β β
β β - Real-time sync β β
β ββββββββββββββββββββββββββββββββββββββ β
β ββββββββββββββββββββββββββββββββββββββ β
β β CDN Server (Port 3012) β β
β β - Serves bulk header files β β
β β - mainNetBlockHeaders.json β β
β β - mainNet_0.headers, etc. β β
β ββββββββββββββββββββββββββββββββββββββ β
β β
β Downloads from (if needed): β
β SOURCE_CDN_URL=https://cdn.babbage.com β
ββββββββββββββββββββββββββββββββββββββββββββ
All endpoints return JSON with { status: "success", result: <data> } or { status: "error", ... }
GET /- Server informationGET /getChain- Get blockchain network ('main' or 'test')GET /getInfo- Detailed service informationGET /currentHeight- Current blockchain heightGET /getPresentHeight- Latest available height
GET /findChainTipHeader- Get chain tip headerGET /findChainTipHash- Get chain tip hashGET /findHeaderForHeight?height=N- Get header at height NGET /findHeaderForBlockHash?hash=HASH- Get header by hashGET /getHeaders?height=N&count=M- Get M headers from height N
GET /isValidRootForHeight?root=ROOT&height=N- Validate merkle root
Static file server for bulk headers:
GET /mainNetBlockHeaders.json- Metadata file with file listGET /mainNet_0.headers- First 100k headers (heights 0-99,999)GET /mainNet_1.headers- Next 100k headers (heights 100,000-199,999)GET /mainNet_N.headers- N-th 100k header file
Each .headers file contains 100,000 consecutive 80-byte block headers.
Create .env file (copy from .env.example):
# Chain selection
CHAIN=main # or 'test'
# Server port (ChaintracksService)
PORT=3011
# WhatsOnChain API Key (recommended for production)
WHATSONCHAIN_API_KEY=your_api_key_here
# SOURCE_CDN_URL - Where to download headers FROM (if local files don't exist)
SOURCE_CDN_URL=https://cdn.projectbabbage.com/blockheaders/
# ENABLE_BULK_HEADERS_CDN - Enable CDN hosting
ENABLE_BULK_HEADERS_CDN=true
# CDN_HOST_URL - Public URL where YOUR CDN is accessible
# This is written to JSON rootFolder field
CDN_HOST_URL=https://headers.yourdomain.com
# BULK_HEADERS_PATH - Where to store/serve header files
# Default: ./public/headers
BULK_HEADERS_PATH=
# Auto-export interval (default: 240000000ms = 67 hours)
BULK_HEADERS_AUTO_EXPORT_INTERVAL=240000000For production with a domain:
CHAIN=main
PORT=3011
WHATSONCHAIN_API_KEY=your_api_key
ENABLE_BULK_HEADERS_CDN=true
CDN_HOST_URL=https://headers.yourdomain.com
SOURCE_CDN_URL=https://cdn.projectbabbage.com/blockheaders/Setup nginx reverse proxy:
# CDN Server
server {
listen 443 ssl;
server_name headers.yourdomain.com;
location / {
proxy_pass http://localhost:3012;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
# API Server
server {
listen 443 ssl;
server_name api.yourdomain.com;
location / {
proxy_pass http://localhost:3011;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}Complete Docker setup with persistent volumes and auto-restart:
# Start with docker-compose
docker compose up -d
# View logs
docker compose logs -f
# Stop
docker compose down
# Update
git pull && docker compose up -d --buildSee DOCKER.md for comprehensive Docker documentation.
- Server starts and checks
./public/headersfor existing files - No files found, downloads from
SOURCE_CDN_URL - Syncs blockchain headers to current height
- Exports all headers to
./public/headers - CDN server starts serving files on port 3012
- Server starts and checks
./public/headers - Finds existing files, loads them directly (no download!)
- Continues syncing from last height
- Automatically exports new headers at 100k boundaries
Other servers can now point to YOUR server:
# On other servers
SOURCE_CDN_URL=https://headers.yourdomain.comThis creates a distributed CDN network where servers help each other!
public/headers/
βββ mainNetBlockHeaders.json # Metadata with file list
βββ mainNet_0.headers # Heights 0-99,999 (7.6 MB)
βββ mainNet_1.headers # Heights 100,000-199,999 (7.6 MB)
βββ mainNet_2.headers # Heights 200,000-299,999 (7.6 MB)
βββ ... # More files as blockchain grows
{
"rootFolder": "https://headers.yourdomain.com",
"jsonFilename": "mainNetBlockHeaders.json",
"headersPerFile": 100000,
"files": [
{
"fileName": "mainNet_0.headers",
"firstHeight": 0,
"count": 100000,
"prevHash": "000...000",
"lastHash": "000...250",
"fileHash": "DMX...",
"sourceUrl": "https://headers.yourdomain.com"
}
]
}npm run build# Standard server (port 3011)
npm start
# Test network
npm run start:test
# Development with auto-reload
npm run devβββ src/
β βββ server.ts # Main server with CDN
β βββ client-example.ts # Example client
βββ dist/ # Compiled JavaScript
βββ public/
β βββ headers/ # Exported bulk headers
βββ Dockerfile # Docker build
βββ docker-compose.yml # Docker services
βββ .env.example # Configuration template
βββ .env.docker # Docker-specific template
βββ DOCKER.md # Docker documentation
βββ README.md # This file
Other servers can use your server by setting:
SOURCE_CDN_URL=http://yourserver:3012
# or
SOURCE_CDN_URL=https://headers.yourdomain.comServer A (Public CDN):
ENABLE_BULK_HEADERS_CDN=true
CDN_HOST_URL=https://cdn.example.com
SOURCE_CDN_URL=https://cdn.projectbabbage.com/blockheaders/Server B (Uses Server A):
ENABLE_BULK_HEADERS_CDN=true
CDN_HOST_URL=https://headers-b.example.com
SOURCE_CDN_URL=https://cdn.example.com # Points to Server AServer C (Uses Server B):
ENABLE_BULK_HEADERS_CDN=true
CDN_HOST_URL=https://headers-c.example.com
SOURCE_CDN_URL=https://headers-b.example.com # Points to Server BCreates a self-healing, distributed CDN network! π
- CPU: 1 core
- RAM: 2 GB
- Disk: 5 GB (for headers)
- CPU: 2 cores
- RAM: 4 GB
- Disk: 10 GB (with growth room)
- ~7.6 MB per 100k blocks
- Current blockchain: ~920k blocks = ~70 MB
- Growth: ~7.6 MB per ~67 days (at 10 min blocks)
# API health
curl http://localhost:3011/getInfo
# CDN health
curl http://localhost:3012/mainNetBlockHeaders.jsondocker compose logs -fls -lh public/headers/- Check
ENABLE_BULK_HEADERS_CDN=truein.env - Check logs for export messages
- Verify disk space available
- Restart server to trigger export
- Verify CDN server running on port 3012
- Check firewall rules
- Test locally:
curl http://localhost:3012/mainNetBlockHeaders.json
- Add
WHATSONCHAIN_API_KEYfor better rate limits - Check
SOURCE_CDN_URLis reachable - Verify network connectivity
See DOCKER.md troubleshooting section.
- DOCKER.md - Complete Docker deployment guide
- API.md - Detailed API documentation
- ARCHITECTURE.md - System architecture details
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
MIT License - see LICENSE file for details
Built with @bsv/wallet-toolbox by the BSV team.