A crypto Bloomberg terminal — real-time chain metrics dashboard, AI-powered VC sentiment tracking, and on-chain metric publishing with Flare verification.
30 supported chains across L1s, L2s, and EVM-compatible networks.
| Category | Chains |
|---|---|
| L1 Majors | Bitcoin (BTC), Ethereum (ETH), Solana (SOL), Cardano (ADA), Polkadot (DOT), Cosmos Hub (ATOM), NEAR (NEAR), Toncoin (TON), TRON (TRX), Aptos (APT), Hedera (HBAR), Internet Computer (ICP) |
| EVM L1s | BNB Chain (BNB), Avalanche (AVAX), Fantom (FTM) |
| L2s & EVM-Adjacent | Arbitrum One (ARB), Optimism (OP), Polygon PoS (POL), Sui (SUI), zkSync Era (ZK), Starknet (STRK), Mantle (MNT), Injective (INJ) |
| Classic L1s | XRP Ledger (XRP), Dogecoin (DOGE), Litecoin (LTC), Filecoin (FIL) |
| Modular | Celestia (TIA), Sei (SEI), Algorand (ALGO) |
- Python 3.12+ with uv
- Node.js 22+
- (Optional) Docker & Docker Compose
cd backend
cp ../.env.example ../.env # edit with your API keys
# Install dependencies and run
uv sync --extra dev
uv run python -m cli serve --reloadThe API is live at http://localhost:8000. Docs at http://localhost:8000/docs.
cd frontend
npm install
npm run devOpen http://localhost:3000.
cp .env.example .env
docker compose up --buildBackend at :8000, frontend at :3000.
cd backend
uv run pytestcd backend
uv run ruff check src/
uv run ruff format --check src/Live price data from CoinGecko, refreshed every 60 seconds via batch API call.
| Field | Type | Description |
|---|---|---|
usd |
float | Current price in USD |
change_7d_pct |
float | 7-day price change percentage |
change_30d_pct |
float | 30-day price change percentage |
market_cap |
float | Market capitalization in USD |
total_volume |
float | 24-hour trading volume in USD |
ath |
float | All-time high price in USD |
If the live price is missing or zero (rate-limited), the system falls back to the most recent price from the 1-day history endpoint.
Server-side aggregated from price history ticks via _aggregate_ohlc(). Auto-selects candle interval based on the requested time range:
| Time Range | Candle Interval |
|---|---|
| 1-2 days | 1 hour |
| 3-14 days | 4 hours |
| 15-90 days | 1 day (24h) |
| 91-180 days | 3 days (72h) |
| 181-365 days | 1 week (168h) |
Allowed explicit intervals: 1, 4, 24, 72, 168 (hours).
Raw price ticks from CoinGecko with granularity determined by the time range:
| Range | Granularity |
|---|---|
| 1 day | 5-minute intervals |
| 2-90 days | Hourly intervals |
| 91-365 days | Daily intervals |
Includes singleflight deduplication — chains sharing the same CoinGecko ID (e.g., Base and Ethereum both use "ethereum") trigger only one API call. Larger cached tiers (90d, 365d) are sliced to serve shorter ranges without extra API calls.
Composite score computed from four equally-weighted factors (25 points each). Missing data scores 12.5 (neutral midpoint). Includes a confidence field (0.0-1.0) reflecting the fraction of factors with real data.
| Factor | Source | Scoring | Range |
|---|---|---|---|
| Price Stability | CoinGecko 30d change | 0% change = 25pts, >=50% change = 0pts | 0-25 |
| Dev Activity | GitHub commits (30d) | 0 commits = 0pts, >=100 commits = 25pts | 0-25 |
| Holder Decentralization | Etherscan / BlockVision top-10 holder % | 0% concentration = 25pts, 100% = 0pts | 0-25 |
| Funding Neutrality | Binance perpetual funding rate | 0 rate = 25pts, >=0.005 = 0pts | 0-25 |
Labels: excellent (>=85), good (>=70), neutral (>=50), caution (>=30), poor (<30)
Contributing factors are returned as human-readable strings (e.g., "strong dev activity (+)", "high concentration (-)") when a factor scores above or below key thresholds.
Pulled from the GitHub commits API for each chain's tracked repositories (30-day window by default).
| Field | Description |
|---|---|
commits |
Total commit count across all tracked repos |
active_devs |
Number of unique commit authors |
repos |
List of owner/repo strings tracked |
days |
Time window in days |
data_source |
"github" when successful |
Derivatives market data from Binance Futures perpetual contracts.
| Field | Description |
|---|---|
funding_rate |
Current perpetual funding rate (positive = longs pay shorts) |
funding_rate_7d_avg |
7-day average funding rate |
signal |
"bullish" / "bearish" / "neutral" based on rate direction |
funding_source |
"binance" when available |
Token holder distribution from on-chain data. Uses a representative token per chain (typically USDC for EVM chains, native token for non-EVM).
| Field | Description |
|---|---|
top10_pct |
Percentage of token supply held by top 10 addresses |
gini |
Gini coefficient (0 = perfectly equal, 1 = maximally concentrated) |
asset_kind |
"erc20" or "sui_coin" |
asset_symbol |
Token symbol (e.g., "USDC", "SUI") |
asset_identifier |
Contract address (EVM) or coin type (Sui) |
data_source |
"etherscan" / "blockvision" / "unavailable" |
AI-computed sentiment index from classified intel items. Uses sigmoid normalization on raw weighted scores.
| Value | Interpretation |
|---|---|
| 50 | Neutral — no signal |
| > 60 | Bullish — positive VC/funding momentum |
| < 40 | Bearish — negative signals |
| > 80 | Strongly bullish |
| < 20 | Strongly bearish |
Computation: For each classified intel item, per-chain impact is scored as magnitude * confidence * direction_sign. Raw scores are aggregated and normalized via sigmoid: 100 / (1 + exp(-raw / 200)).
Windows: 1d (24h), 7d (7 days), 30d (30 days).
| Provider | Data | Auth | Rate Limit |
|---|---|---|---|
| CoinGecko (free tier) | Prices, market cap, volume, ATH, price history, OHLC source data | None | ~10-30 req/min, 429 on exceeded |
| GitHub | Commits, active developers per repo | Optional PAT | 60/hr unauthenticated, 5000/hr with token |
| Binance Futures | Perpetual funding rate (current + 7d avg) | None | 500 req/5min |
| Etherscan (v2) | EVM token holder concentration (top-10 %) | API key (PRO for holder list) | Standard Etherscan limits |
| BlockVision | Sui coin holder concentration | API key (x-api-key header) |
300 CU/s free tier |
| EVM RPC | Block number for EVM chains | RPC URL | Provider-dependent |
| Sui RPC | Block number for Sui | RPC URL | Provider-dependent |
| OpenAI | Intel item classification (gpt-4o-mini) | API key | Standard OpenAI limits |
| Flare FTSO (skeleton) | Decentralized price feeds (behind feature flag) | None | N/A — CoinGecko is primary |
Base URL: http://localhost:8000
| Method | Path | Description |
|---|---|---|
GET |
/health |
Health check — returns {status, version} |
GET |
/metrics |
Prometheus metrics (request count, latency, cache stats) |
GET |
/docs |
OpenAPI Swagger UI (dev mode only) |
| Method | Path | Params | Description |
|---|---|---|---|
GET |
/chains |
— | List all 30 supported chains (id, name, symbol, is_evm) |
GET |
/chains/all |
— | Full metrics for all chains in one request (30s timeout) |
GET |
/chains/{chain_id} |
— | Full metrics for one chain: price, sentiment, holders, dev, reputation, block_number |
GET |
/chains/{chain_id}/history |
days (1-365, default 30) |
Price history as [{timestamp, price}] time series |
GET |
/chains/{chain_id}/ohlc |
days (1-365), interval (1/4/24/72/168h) |
OHLC candlestick data, auto-interval if omitted |
GET |
/chains/{chain_id}/dev-activity |
days (1-365, default 30) |
Developer activity: commits, active devs, repos |
POST |
/query |
{"query": "...", "chain_id": "..."} |
Keyword search across chains, returns matching metrics |
POST |
/admin/refresh |
Header: X-Admin-Token |
Force-refresh all chain metrics (invalidates price cache) |
| Method | Path | Params | Description |
|---|---|---|---|
GET |
/api/intel/sources |
— | List all configured intel sources with item counts |
GET |
/api/intel/items |
source, chain, since, limit (default 50) |
List intel items, filterable by source/chain/date |
GET |
/api/intel/items/{url_hash} |
— | Full item detail with raw text and parsed classification |
GET |
/api/intel/vc/{slug} |
— | VC source detail: metadata + items + impacted chains summary |
GET |
/api/intel/chains/{chain}/impact |
window (1d/7d/30d, default 7d) |
Chain flow index with top contributing items |
GET |
/api/intel/flow |
— | Flow index table for all chains (1d/7d/30d columns) |
POST |
/api/intel/refresh |
reclassify (bool) |
Trigger fetch/classify cycle. ?reclassify=true reprocesses all |
| Method | Path | Params | Description |
|---|---|---|---|
POST |
/api/onchain/publish |
{chain, metric_type, value, target} |
Publish a metric on-chain. value=0 auto-resolves from current data |
GET |
/api/onchain/status |
chain, metric_type, limit (default 50) |
List publish records with Flare enabled flag |
GET |
/api/onchain/latest/{chain} |
— | Latest publish records for a specific chain |
POST |
/api/onchain/attest/{item_url_hash} |
— | Request FDC attestation for an intel item |
GET |
/api/onchain/attest/{item_url_hash} |
— | Get attestation status for an intel item |
Valid metric types: flow_1d, flow_7d, flow_30d, risk
Valid targets: evm, flare, auto (prefers Flare if enabled, falls back to EVM, then simulated)
Publish modes: real (EVM), flare_direct (Flare), flare_attested (Flare + FDC proof), simulated (SQLite-only)
# Health check
curl http://localhost:8000/health
# List all chains
curl http://localhost:8000/chains
# Get Ethereum metrics (price, sentiment, holders, dev, reputation)
curl http://localhost:8000/chains/ethereum
# Get 90-day OHLC candles with 1-day interval
curl "http://localhost:8000/chains/bitcoin/ohlc?days=90&interval=24"
# Get 7-day price history for Solana
curl "http://localhost:8000/chains/solana/history?days=7"
# Get 60-day dev activity for Sui
curl "http://localhost:8000/chains/sui/dev-activity?days=60"
# Keyword query
curl -X POST http://localhost:8000/query \
-H 'Content-Type: application/json' \
-d '{"query": "polygon"}'
# Flow index table (all chains)
curl http://localhost:8000/api/intel/flow
# Publish Ethereum 7-day flow index on-chain
curl -X POST http://localhost:8000/api/onchain/publish \
-H 'Content-Type: application/json' \
-d '{"chain": "ethereum", "metric_type": "flow_7d", "value": 0, "target": "auto"}'
# Force refresh (admin)
curl -X POST http://localhost:8000/admin/refresh \
-H 'X-Admin-Token: your-token-here'BlockBerg features a Bloomberg-style command bar (/ or Ctrl+K to focus). All commands are case-insensitive.
| Command | Action |
|---|---|
CHAINS |
Go to chain overview (home page) |
SCREENER |
Screener + strategy page |
COMPARE |
Jump to multi-chain comparison charts |
WATCHLIST |
View watched chains |
HELP or ? |
Show command reference |
LAST |
Show command history |
GRAB |
Screenshot current screen to PNG |
| Command | Action |
|---|---|
BTC / ETH / SOL / ... |
Go to chain detail dashboard |
<SYM> GP |
Price graph (area chart) |
<SYM> HVG |
Historical volatility graph |
<SYM> DEV |
Developer activity chart |
<SYM> SENT |
Sentiment / funding rate chart |
<SYM> VOL |
Scroll to volume section |
<SYM> HOLD |
Scroll to holders section |
Symbols: BTC, ETH, SOL, ARB, OP, POL/MATIC, SUI, AVAX, BNB, ADA, DOT, ATOM, NEAR, TON, TRX, APT, FTM, ALGO, TIA, SEI, HBAR, ICP, STRK, ZK, MNT, INJ, XRP, DOGE, LTC, FIL
| Command | Action |
|---|---|
WATCH <SYM> |
Toggle chain in watchlist |
REFRESH ALL |
Force-refresh all chain data |
REFRESH <SYM> |
Force-refresh one chain |
| Command | Action |
|---|---|
VC |
List all VC intel sources |
VC <slug> |
View VC source detail + classified items |
FLOW |
Chain flow index table (1d/7d/30d) |
| Command | Action |
|---|---|
PUBLISH <SYM> FLOW 7D |
Publish 7-day flow index on-chain |
PUBLISH <SYM> FLOW 1D |
Publish 1-day flow index on-chain |
PUBLISH <SYM> FLOW 30D |
Publish 30-day flow index on-chain |
PUBLISH <SYM> RISK |
Publish reputation/risk score on-chain |
| Key | Action |
|---|---|
/ or Ctrl+K |
Focus command bar |
? |
Open help modal |
Esc |
Clear input / close modals |
Tab |
Autocomplete command |
Up / Down |
Command history |
Enter |
Execute command |
D |
Toggle compact density mode |
AI-powered VC and crypto funding sentiment tracker.
- Sources: Configured in
backend/config/intel_sources.yaml— RSS feeds and HTML scraping from major crypto VCs and news outlets - Fetch: Background scheduler fetches all sources every 30 minutes (configurable via
INTEL_FETCH_INTERVAL_SECONDS) - Classify: Each item is sent to OpenAI (gpt-4o-mini by default) for structured JSON classification:
- Item type:
funding_round,portfolio_update,grant,partnership,blog_post,other - Entity extraction: companies (name, website, confidence) and people (name, role, confidence)
- Funding info: round type, amount in USD, investors list
- Per-chain impact: chain name, direction (positive/negative/neutral), magnitude (0-100), confidence (0-1), rationale
- Item type:
- Flow Index: Computed per chain per window (1d/7d/30d) from classified items using sigmoid normalization
| Source | Type | Tags |
|---|---|---|
| a16z Crypto | RSS (Substack) | vc, crypto, web3 |
| Multicoin Capital | RSS | vc, crypto, web3 |
| Variant Fund | RSS | vc, crypto, web3 |
| Hack VC | RSS | vc, crypto, ai |
| Dragonfly Capital | RSS (Medium) | vc, crypto, defi |
| Pantera Capital | RSS (Medium) | vc, crypto, blockchain |
| Paradigm | HTML scrape | vc, crypto, defi |
| CoinDesk | RSS | news, crypto |
| The Block | RSS | news, crypto |
| Blockworks | RSS | news, crypto |
Edit backend/config/intel_sources.yaml:
sources:
- slug: my-vc
name: My VC Firm
kind: rss # or "html"
url: https://myvc.com/feed/
tags: [crypto]Publish computed metrics (flow index, reputation score) to EVM-compatible blockchains with a two-tier fallback:
- Tier A (Real): Send transactions via JSON-RPC to any EVM chain or Flare network
- Tier B (Simulated): Store publish records in SQLite with deterministic fake tx hashes (
0xSIM...for EVM,0xFLR...for Flare)
No web3.py dependency — uses raw httpx JSON-RPC calls for minimal footprint.
| Target | Behavior |
|---|---|
auto |
Prefers Flare (if enabled + configured), falls back to EVM, then simulated |
evm |
Generic EVM publish via ONCHAIN_RPC_URL + ONCHAIN_PRIVATE_KEY |
flare |
Flare-specific publish via FLARE_RPC_URL + FLARE_PRIVATE_KEY |
Reference Solidity contract at backend/contracts/MetricStore.sol:
publishMetric(string chain, string metricType, uint256 value)— standard metric publish, emitsMetricPublishedeventsetMetricWithAttestation(string chain, string metricType, uint256 value, bytes32 attestationProof)— FDC-verified publish, emitsMetricPublishedWithAttestationeventgetLatest(string chain, string metricType)— view function returning latest value, timestamp, and publisher address- Metric values are scaled by
1e4(4 decimal places). A flow index of 65.5 is stored as655000.
BlockBerg integrates with the Flare blockchain for verifiable metric publishing and external data attestation.
-
Flare Publisher (
backend/src/blockberg/onchain/flare_publisher.py): Dedicated publisher targeting Flare/Coston2 RPC. Supports direct metric publishing (mode=flare_direct) and FDC-attested updates (mode=flare_attested) viasetMetricWithAttestation(). -
FDC Attestation (
backend/src/blockberg/onchain/fdc.py): Flare Data Connector integration for verifying intel items. BuildsAddressValidityattestation payloads, computes deterministic SHA-256 payload hashes, and tracks verification status:requested->verified->on-chain. -
FTSO Price Provider (
backend/src/blockberg/providers/flare_ftso.py): Skeleton provider for reading prices from Flare Time Series Oracle. Maps 16 CoinGecko IDs to FTSO symbols. BehindFLARE_ENABLEDfeature flag — CoinGecko remains the default price source. -
Smart Contract (
backend/contracts/MetricStore.sol): Reference Solidity contract withpublishMetric()for standard updates andsetMetricWithAttestation(bytes32 attestationProof)for FDC-verified updates. -
Frontend: Flare mode badges (
FLARE DIRECT/FLARE ATTESTED/SIMULATED) on publish records, andVERIFYbuttons on intel items for requesting FDC attestation.
FLARE_ENABLED=true
FLARE_RPC_URL=https://coston2-api.flare.network/ext/C/rpc
FLARE_PRIVATE_KEY=0x... # NEVER commit
FLARE_CONTRACT_ADDRESS=0x...
FLARE_NETWORK_NAME=flare-coston2Intel Item -> AI Classification -> Flow Index Computation
|
PUBLISH ETH FLOW 7D (command)
|
target=auto -> FlarePublisher
|
publishMetric() on Flare Coston2
|
MetricPublished event emitted
|
Record stored in SQLite + shown in UI
Intel Item -> VERIFY button -> FDC Attestation Request
|
Build payload -> hash -> store
|
FDC verifier (when available)
|
Merkle proof -> setMetricWithAttestation()
| Route | Page | Description |
|---|---|---|
/ |
Home | Chain overview grid — prices, sparklines, reputation badges for all 30 chains |
/chains/{chainId} |
Chain Detail | Full dashboard: price chart, OHLC candles, volume, sentiment, holders, dev activity, reputation, on-chain publishes |
/screener |
Screener | Multi-chain comparison charts and strategy tools |
/intel/vc |
VC List | All configured VC intel sources with item counts |
/intel/vc/{slug} |
VC Detail | Source metadata, classified items, per-chain impact breakdown |
/intel/flow |
Flow Table | Flow index for all chains across 1d/7d/30d windows |
/intel/news |
News Feed | AI-classified intel items from all sources, with FDC VERIFY buttons |
/intel/news/{hash} |
News Detail | Full item detail with raw classification, entity extraction, funding info |
| Variable | Required | Default | Description |
|---|---|---|---|
BLOCKBERG_ENV |
No | development |
Environment: development or production |
BLOCKBERG_LOG_LEVEL |
No | INFO |
Log level (DEBUG, INFO, WARNING, ERROR) |
BLOCKBERG_HOST |
No | 0.0.0.0 |
Server bind host |
BLOCKBERG_PORT |
No | 8000 |
Server bind port |
BLOCKBERG_ADMIN_TOKEN |
No | — | Admin auth token for /admin/refresh. Empty = open in dev |
BLOCKBERG_CORS_ORIGINS |
No | — | Comma-separated allowed CORS origins for production |
| Variable | Required | Default | Description |
|---|---|---|---|
BLOCKBERG_RATE_LIMIT_RPS |
No | 20 |
Token-bucket refill rate (requests/second) |
BLOCKBERG_RATE_LIMIT_BURST |
No | 40 |
Maximum burst size per IP |
BLOCKBERG_CACHE_TTL_SECONDS |
No | 60 |
Default in-memory cache TTL |
BLOCKBERG_REDIS_URL |
No | — | Redis URL (empty = in-memory only) |
| Variable | Required | Default | Description |
|---|---|---|---|
BLOCKBERG_ETH_RPC_URL |
No | — | Ethereum JSON-RPC (e.g., Alchemy) |
BLOCKBERG_ARBITRUM_RPC_URL |
No | — | Arbitrum One JSON-RPC |
BLOCKBERG_OPTIMISM_RPC_URL |
No | — | Optimism JSON-RPC |
BLOCKBERG_BASE_RPC_URL |
No | — | Base JSON-RPC |
BLOCKBERG_POLYGON_RPC_URL |
No | — | Polygon PoS JSON-RPC |
BLOCKBERG_SUI_RPC_URL |
No | https://fullnode.mainnet.sui.io:443 |
Sui full node RPC |
| Variable | Required | Default | Description |
|---|---|---|---|
BLOCKBERG_GITHUB_TOKEN |
No | — | GitHub PAT for 5000/hr rate limit (vs 60/hr) |
BLOCKBERG_ETHERSCAN_API_KEY |
No | — | Etherscan API key for EVM holder data (PRO for holder list) |
BLOCKBERG_BLOCKVISION_API_KEY |
No | — | BlockVision API key for Sui holder data |
BLOCKBERG_BINANCE_FUTURES_BASE_URL |
No | https://fapi.binance.com |
Binance Futures base URL |
| Variable | Required | Default | Description |
|---|---|---|---|
CHATGPT_KEY |
For intel | — | OpenAI API key for LLM classification |
GITHUB_KEY |
No | — | GitHub PAT for dev activity (intel-specific) |
INTEL_DB_PATH |
No | ./data/intel.sqlite |
SQLite database path for intel data |
INTEL_FETCH_INTERVAL_SECONDS |
No | 1800 |
Background fetch cycle interval (seconds) |
INTEL_USER_AGENT |
No | BlockBergIntel/0.1 |
User-Agent for source fetching |
INTEL_MAX_ITEMS_PER_SOURCE |
No | 20 |
Max items to ingest per source per cycle |
OPENAI_MODEL |
No | gpt-4o-mini |
OpenAI model for classification |
INTEL_ALLOWED_DOMAINS |
No | — | Comma-separated allowlist of fetch domains |
| Variable | Required | Default | Description |
|---|---|---|---|
ONCHAIN_ENABLED |
No | true |
Enable onchain publishing (uses simulated if no RPC) |
ONCHAIN_NETWORK |
No | sepolia |
Target network name (informational) |
ONCHAIN_RPC_URL |
No | — | EVM RPC URL for real publishing (empty = simulated) |
ONCHAIN_PRIVATE_KEY |
No | — | Private key for signing transactions (never commit) |
ONCHAIN_CONTRACT_ADDRESS |
No | — | Deployed MetricStore contract address |
ONCHAIN_DB_PATH |
No | ./data/onchain.sqlite |
SQLite database for publish records |
| Variable | Required | Default | Description |
|---|---|---|---|
FLARE_ENABLED |
No | false |
Enable Flare as a publish target |
FLARE_RPC_URL |
No | — | Flare / Coston2 testnet RPC URL |
FLARE_PRIVATE_KEY |
No | — | Private key for Flare transactions (never commit) |
FLARE_CONTRACT_ADDRESS |
No | — | MetricStore contract address on Flare |
FLARE_NETWORK_NAME |
No | flare-coston2 |
Network name: flare or flare-coston2 |
| Variable | Required | Default | Description |
|---|---|---|---|
NEXT_PUBLIC_API_URL |
No | http://localhost:8000 |
Backend API URL |
BlockBerg/
├── backend/
│ ├── src/
│ │ ├── cli.py # CLI entry point (serve, etc.)
│ │ ├── blockberg/
│ │ │ ├── api/
│ │ │ │ ├── app.py # FastAPI factory + lifespan
│ │ │ │ ├── routes.py # Core chain/query/admin endpoints
│ │ │ │ ├── middleware.py # Rate limiting, CORS, Prometheus instrumentation
│ │ │ │ └── deps.py # FastAPI dependency injection
│ │ │ ├── core/
│ │ │ │ ├── config.py # Pydantic Settings (env vars)
│ │ │ │ ├── cache.py # In-memory TTL cache
│ │ │ │ ├── chains.py # 30 chain definitions (ChainId, ChainInfo)
│ │ │ │ ├── rate_limiter.py # Token-bucket per-IP rate limiter
│ │ │ │ ├── logging.py # structlog JSON logging setup
│ │ │ │ └── metrics.py # Prometheus counters and gauges
│ │ │ ├── models/
│ │ │ │ └── chains.py # Pydantic v2 response schemas
│ │ │ ├── providers/
│ │ │ │ ├── base.py # Abstract provider interfaces
│ │ │ │ ├── coingecko.py # CoinGecko price/history provider
│ │ │ │ ├── github.py # GitHub dev activity provider
│ │ │ │ ├── binance.py # Binance funding rate provider
│ │ │ │ ├── etherscan.py # EVM holder concentration provider
│ │ │ │ ├── blockvision.py # Sui holder concentration provider
│ │ │ │ ├── evm_rpc.py # EVM JSON-RPC (block number)
│ │ │ │ ├── sui_rpc.py # Sui JSON-RPC (block number)
│ │ │ │ └── flare_ftso.py # Flare FTSO price provider (skeleton)
│ │ │ ├── services/
│ │ │ │ ├── metrics_service.py # Orchestrates providers + caching
│ │ │ │ ├── reputation.py # Reputation score computation
│ │ │ │ └── scheduler.py # Background refresh tasks
│ │ │ ├── intel/
│ │ │ │ ├── config.py # Intel env var configuration
│ │ │ │ ├── db.py # SQLite async database (aiosqlite)
│ │ │ │ ├── fetcher.py # RSS/HTML source fetcher
│ │ │ │ ├── flow.py # Flow index computation
│ │ │ │ ├── llm.py # OpenAI classification provider
│ │ │ │ ├── models.py # Pydantic v2 intel schemas
│ │ │ │ ├── routes.py # Intel API endpoints
│ │ │ │ └── service.py # Intel service orchestrator
│ │ │ └── onchain/
│ │ │ ├── config.py # Onchain + Flare env var config
│ │ │ ├── db.py # SQLite for publishes + attestations
│ │ │ ├── models.py # Pydantic v2 onchain schemas
│ │ │ ├── publisher.py # Publisher factory (create_publisher)
│ │ │ ├── evm_publisher.py # EVM JSON-RPC publisher
│ │ │ ├── sim_publisher.py # Simulated publisher (SQLite only)
│ │ │ ├── flare_publisher.py # Flare-specific publisher
│ │ │ ├── fdc.py # FDC attestation builder
│ │ │ ├── service.py # Onchain service orchestrator
│ │ │ └── routes.py # Onchain API endpoints
│ │ └── blockberg_tests/ # pytest tests (87 tests)
│ ├── config/
│ │ └── intel_sources.yaml # VC/news source definitions
│ ├── contracts/
│ │ └── MetricStore.sol # Reference Solidity contract
│ ├── deployments/
│ ├── Dockerfile
│ └── pyproject.toml
├── frontend/
│ ├── src/
│ │ ├── app/ # Next.js 15 App Router
│ │ │ ├── page.tsx # Home — chain overview grid
│ │ │ ├── chains/[chainId]/ # Chain detail dashboard
│ │ │ ├── screener/ # Screener + comparison charts
│ │ │ └── intel/ # VC list, detail, flow, news
│ │ ├── components/ # React components (command bar, help modal, charts)
│ │ └── lib/
│ │ ├── api.ts # Typed API client
│ │ ├── hooks.ts # TanStack Query hooks
│ │ └── commands.ts # Command parser + autocomplete
│ ├── deployments/
│ ├── Dockerfile
│ └── package.json
├── libs/ # Shared libraries (scaffolding)
├── docker-compose.yml
└── .env.example
- FastAPI + uvicorn + uvloop for async request handling
- ORJSONResponse for fast JSON serialization
- In-memory TTL cache with per-key expiration and periodic eviction (every 5 min)
- Batch price fetching: single CoinGecko API call pre-warms prices for all 30 chains
- Singleflight deduplication: concurrent requests for the same price history share one in-flight API call
- Cache tier slicing: larger cached ranges (90d, 365d) are sliced to serve shorter ranges without extra calls
- Per-provider timeout: 15s timeout per provider prevents one slow source from blocking all metrics
- Route-level timeout: 30s timeout on all API endpoints, returns 504 on timeout
Token-bucket algorithm per client IP (in-memory). Default: 20 tokens/sec, burst of 40. Auto-cleanup at >10,000 entries to prevent memory leaks. Extensible to Redis via Lua script for multi-process deployments.
Pure asyncio task scheduler — no Celery dependency:
| Task | Interval | Description |
|---|---|---|
| Metrics refresh | cache_ttl_seconds (min 30s) |
Pre-warms cache for all chains on startup, then periodic refresh |
| Cache eviction | 5 minutes | Evicts expired entries to bound memory |
| Intel fetch | INTEL_FETCH_INTERVAL_SECONDS (default 1800) |
Fetches sources, classifies items, computes flow indices |
- Intel data: SQLite via aiosqlite (
intel_sources,intel_items,intel_classifications,chain_flow_snapshots) - Publish records: SQLite via aiosqlite (
onchain_publishes,attestation_requests) - No Redis required — in-memory cache handles all caching needs for single-process deployment
- structlog JSON logging with configurable log level
- Prometheus metrics:
blockberg_request_count,blockberg_request_latency,blockberg_cache_hits,blockberg_cache_misses,blockberg_app_info - Path normalization prevents unbounded Prometheus label cardinality
- Backend: Pydantic v2 validation on all models, mypy strict mode
- Frontend: TypeScript strict, typed API client, TanStack Query with generic types
Abstract base classes (PriceProvider, DevActivityProvider, SentimentProvider, HolderProvider, RPCProvider) enable swapping data sources without changing business logic. CoinGecko can be replaced by Flare FTSO via feature flag.