ExplorerToken is a production-oriented, multi-chain token explorer inspired by Polygonscan. It ships as a full-stack TypeScript monorepo with a hardened Express API, a React + Vite frontend, and operational blueprints for running behind Nginx, Redis, and PostgreSQL.
- End-to-end TypeScript – shared typings drive the Express API, React frontend, and SWR data hooks.
- Security baked in – Helmet CSP, strict CORS, Redis-backed rate limiting with in-memory fallback, and disabled Cronos chain (id 25) per requirements.
- Ops ready – Nginx/site config,
systemdunit, deployment script, runbook, and acceptance testing guide included underdocs/andops/.
| Path | Purpose |
|---|---|
backend/ |
Express API, Redis limiter, Postgres migrations, vendor stubs |
frontend/ |
React 18 + Vite client, Tailwind UI, SWR data hooks |
ops/ |
Nginx vhost, systemd service, deployment script |
docs/ |
Setup, deployment playbook, runbook, acceptance checklist |
.github/ |
CI workflow (lint, typecheck, build) |
.vscode/ |
Remote-friendly tasks for dev servers and migrations |
- Install Node.js 20 (
nvm use) and dependencies:npm install
- Copy and adjust backend environment variables:
cp backend/.env.example backend/.env
- Apply migrations:
npm run migrate --workspace backend
- Launch dev servers in separate terminals (or via VS Code tasks):
npm run dev --workspace backend npm run dev --workspace frontend
Detailed instructions live in docs/setup.md.
Run from the repository root unless stated otherwise:
| Script | Description |
|---|---|
npm run lint |
ESLint across frontend and backend |
npm run typecheck |
TypeScript --noEmit for both workspaces |
npm run build |
Builds frontend (Vite) and backend (tsc) |
npm run dev --workspace backend |
Nodemon-style backend watcher via ts-node-dev |
npm run dev --workspace frontend |
Vite dev server with proxy to backend |
npm run migrate --workspace backend |
Applies SQL migrations from backend/migrations |
npm test --workspace backend |
Runs backend API tests with Vitest + Supertest |
- Provisioning, Nginx, and
systemdinstructions:docs/deployment.md - Operational runbook (restart, rollback, Redis actions):
docs/runbook.md - Server assets ready to copy:
Pair the host with Cloudflare (WAF+TLS termination) and managed Postgres/Redis as outlined in the deployment guide.
Each chain poller runs under a templated unit defined in
ops/systemd/explorertoken-chain@.service.
Enable the required chains (Polygon, Ethereum mainnet, Arbitrum) with:
sudo systemctl enable --now explorertoken-chain@137
sudo systemctl enable --now explorertoken-chain@1
sudo systemctl enable --now explorertoken-chain@42161Tail logs for a specific chain to confirm block ingestion:
sudo journalctl -u explorertoken-chain@137 -f
sudo journalctl -u explorertoken-chain@1 -f
sudo journalctl -u explorertoken-chain@42161 -fHealth checks surface from the backend service; curl them locally or through your load balancer:
curl -fsS http://localhost:4000/health | jq
curl -fsS https://explorertoken.yourdomain.com/health | jq- Dashboard with chain pill filter (Cronos disabled), health status cards, quick search module, and placeholder “Top tokens” table.
- Token detail page featuring overview stats plus cursor-based holder pagination with reset/back/next controls.
- Admin console protected by token auth middleware and rate-limited endpoints.
/healthexposes build metadata for uptime checks./api/chains,/api/tokens/:chainId/:address,/api/tokens/:chainId/:address/holderssupply the frontend via SWR.- Middleware stack: Helmet CSP, strict CORS, JSON body parsing, rate limiting (Redis store with memory fallback), structured error handling.
- Migration runner seeds schema for admin users, chain settings, and job checkpoints.
erDiagram
blocks ||--o{ transactions : contains
transactions ||--o{ receipts : produces
transactions ||--o{ logs : emits
logs ||--o{ token_transfers : decodes
blocks {
int chain_id PK
bigint number PK
bytea hash UNIQUE
bytea parent_hash
timestamptz timestamp
}
transactions {
int chain_id PK
bytea hash PK
bigint block_number FK
bytea from
bytea to
numeric value
numeric nonce
numeric gas
numeric gas_price
bytea input
}
receipts {
int chain_id PK
bytea tx_hash PK FK
boolean status
numeric gas_used
numeric effective_gas_price
bytea contract_address
}
logs {
int chain_id PK
bytea tx_hash PK FK
int log_index PK
bytea address
bytea topic0
bytea topic1
bytea topic2
bytea topic3
bytea data
}
token_transfers {
int chain_id PK
bytea tx_hash PK FK
int log_index PK FK
bytea token
bytea from
bytea to
numeric value
}
- Local setup:
docs/setup.md - Deployment playbook:
docs/deployment.md - Ops runbook:
docs/runbook.md - Release acceptance checklist:
docs/acceptance.md
See docs/acceptance.md for the sign-off steps covering automated checks, manual walkthroughs, and production smoke tests.
.nvmrcpins Node 20.11.1; GitHub Actions mirrors this version.- ESLint + Prettier share a consistent code style across the repo.
.vscode/tasks.jsonexposes Remote-SSH friendly tasks for dev servers and migrations.
- Run the quality gates (
lint,typecheck,build, backend tests`). - Ensure Cronos chain stays disabled in sample data.
- Submit PRs against
main; CI will validate automatically.