Expand description
§brk_server
HTTP server providing REST API access to Bitcoin analytics data
§Overview
This crate provides a high-performance HTTP server built on axum that exposes Bitcoin blockchain analytics data through a comprehensive REST API. It integrates with the entire BRK ecosystem, serving data from indexers, computers, and parsers with intelligent caching, compression, and multiple output formats.
Key Features:
- RESTful API for blockchain data queries with flexible filtering
- Multiple output formats: JSON, CSV
- Intelligent caching system with ETags and conditional requests
- HTTP compression (Gzip, Brotli, Deflate, Zstd) for bandwidth efficiency
- Static file serving for web interfaces and documentation
- Bitcoin address and transaction lookup endpoints
- Vector database query interface with pagination
- Health monitoring and status endpoints
Target Use Cases:
- Bitcoin data APIs for applications and research
- Web-based blockchain explorers and analytics dashboards
- Research data export and analysis tools
- Integration with external systems requiring Bitcoin data
§Installation
cargo add brk_server§Quick Start
use brk_server::Server;
use brk_interface::Interface;
use std::path::PathBuf;
// Initialize interface with your data sources
let interface = Interface::new(/* your config */);
// Optional static file serving directory
let files_path = Some(PathBuf::from("./web"));
// Create and start server
let server = Server::new(interface, files_path);
// Start server with optional MCP (Model Context Protocol) support
server.serve(true).await?;§API Overview
§Core Endpoints
Blockchain Queries:
GET /api/address/{address}- Address information, balance, transaction countsGET /api/tx/{txid}- Transaction details including version, locktimeGET /api/vecs/{variant}- Vector database queries with filtering
System Information:
GET /api/vecs/index-count- Total number of indexes availableGET /api/vecs/id-count- Vector ID statisticsGET /api/vecs/indexes- List of available data indexesGET /health- Service health statusGET /version- Server version information
§Vector Database API
Query Interface:
GET /api/vecs/query- Generic vector query with parametersGET /api/vecs/{variant}?from={start}&to={end}&format={format}- Range queries
Supported Parameters:
from/to: Range filtering (height, timestamp, date-based)format: Output format (json, csv)- Pagination parameters for large datasets
§Address API Response Format
{
"address": "1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2",
"type": "p2pkh",
"index": 12345,
"chain_stats": {
"funded_txo_sum": 500000000,
"spent_txo_sum": 400000000,
"utxo_count": 5,
"balance": 100000000,
"balance_usd": 4200.5,
"realized_value": 450000000,
"avg_cost_basis": 45000.0
}
}§Examples
§Basic Server Setup
use brk_server::Server;
use brk_interface::Interface;
// Initialize with BRK interface
let interface = Interface::builder()
.with_indexer_path("./data/indexer")
.with_computer_path("./data/computer")
.build()?;
let server = Server::new(interface, None);
// Server automatically finds available port starting from 3110
server.serve(false).await?;§Address Balance Lookup
# Get address information
curl http://localhost:3110/api/address/1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2
# Response includes balance, transaction counts, USD value
{
"address": "1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2",
"type": "p2pkh",
"chain_stats": {
"balance": 100000000,
"balance_usd": 4200.50,
"utxo_count": 5
}
}§Data Export Queries
# Export height-to-price data as CSV
curl "http://localhost:3110/api/vecs/height-to-price?from=800000&to=800100&format=csv" \
-H "Accept-Encoding: gzip"
# Query with caching - subsequent requests return 304 Not Modified
curl "http://localhost:3110/api/vecs/dateindex-to-price-ohlc?from=0&to=1000" \
-H "If-None-Match: \"etag-hash\""§Transaction Details
# Get transaction information
curl http://localhost:3110/api/tx/abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890
# Response includes version, locktime, and internal indexing
{
"txid": "abcdef...",
"index": 98765,
"version": 2,
"locktime": 0
}§Architecture
§Server Stack
- HTTP Framework:
axumwith async/await for high concurrency - Compression: Multi-algorithm support (Gzip, Brotli, Deflate, Zstd)
- Caching:
quick_cachewith LRU eviction and ETag validation - Tracing: Request/response logging with latency tracking
- Static Files: Optional web interface serving
§Caching Strategy
The server implements intelligent caching:
- ETags: Generated from data version and query parameters
- Conditional Requests: 304 Not Modified responses for unchanged data
- Memory Cache: LRU cache with configurable capacity (5,000 entries)
- Cache Control:
must-revalidateheaders for data consistency
§Request Processing
- Route Matching: Path-based routing to appropriate handlers
- Parameter Validation: Query parameter parsing and validation
- Data Retrieval: Interface calls to indexer/computer components
- Caching Logic: ETag generation and cache lookup
- Format Conversion: JSON/CSV output formatting
- Compression: Response compression based on Accept-Encoding
- Response: HTTP response with appropriate headers
§Static File Serving
Optional static file serving supports:
- Web interface hosting for blockchain explorers
- Documentation and API reference serving
- Asset serving (CSS, JS, images) with proper MIME types
- Directory browsing with index.html fallback
§Configuration
§Environment Variables
The server automatically configures itself but respects:
- Port selection: Starts at 3110, increments if unavailable
- Compression: Enabled by default for all supported algorithms
- CORS: Permissive headers for cross-origin requests
§Memory Management
- Cache size: 5,000 entries by default
- Request weight limits: 65MB maximum per query
- Timeout handling: 50ms cache guard timeout
- Compression: Adaptive based on content type and size
§Code Analysis Summary
Main Components: Server struct with AppState containing interface, cache, and file paths
HTTP Framework: Built on axum with middleware for compression, tracing, and CORS
API Routes: Address lookup, transaction details, vector queries, and system information
Caching Layer: quick_cache integration with ETag-based conditional requests
Data Integration: Direct interface to BRK indexer, computer, parser, and fetcher components
Static Serving: Optional file serving for web interfaces and documentation
Architecture: Async HTTP server with intelligent caching and multi-format data export capabilities
This README was generated by Claude Code
§Example
use std::{path::Path, thread::sleep, time::Duration};
use bitcoincore_rpc::RpcApi;
use brk_computer::Computer;
use brk_error::Result;
use brk_fetcher::Fetcher;
use brk_indexer::Indexer;
use brk_interface::Interface;
use brk_parser::Parser;
use brk_server::Server;
use vecdb::Exit;
pub fn main() -> Result<()> {
brk_logger::init(Some(Path::new(".log")))?;
let process = true;
let bitcoin_dir = Path::new("");
let rpc = Box::leak(Box::new(bitcoincore_rpc::Client::new(
"http://localhost:8332",
bitcoincore_rpc::Auth::CookieFile(bitcoin_dir.join(".cookie")),
)?));
let exit = Exit::new();
exit.set_ctrlc_handler();
let parser = Parser::new(bitcoin_dir.join("blocks"), rpc);
let outputs_dir = Path::new("../../_outputs");
let mut indexer = Indexer::forced_import(outputs_dir)?;
let fetcher = Some(Fetcher::import(true, None)?);
let mut computer = Computer::forced_import(outputs_dir, &indexer, fetcher)?;
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()?
.block_on(async {
let interface = Interface::build(&parser, &indexer, &computer);
let server = Server::new(interface, None);
let server = tokio::spawn(async move {
server.serve(true).await.unwrap();
});
if process {
loop {
let block_count = rpc.get_block_count()?;
let starting_indexes = indexer.index(&parser, rpc, &exit, true)?;
computer.compute(&indexer, starting_indexes, &parser, &exit)?;
while block_count == rpc.get_block_count()? {
sleep(Duration::from_secs(1))
}
}
}
#[allow(unreachable_code)]
server.await.unwrap();
Ok(())
})
}