mirror of
https://github.com/luxfi/explorer.git
synced 2026-09-24 00:25:12 +00:00
luxd serves chain APIs under one segment from constants.ChainAliasPrefix (constants v1.6.4, node v1.36.181): /v1/bc/<alias>/... -> /v1/chain/<alias>/... /ext/bc/<alias>/... -> /v1/chain/<alias>/... Observations keep their original addresses: a dated note or a recorded status code is a fact about when it was written, not an instruction to follow.
178 lines
5.4 KiB
Markdown
178 lines
5.4 KiB
Markdown
<p align="center"><img src=".github/hero.svg" alt="explorer" width="880"></p>
|
|
|
|
# Explorer
|
|
|
|
Single-binary Lux explorer: chain indexer, GraphQL engine, and SPA frontend
|
|
in one Go process. Imports [`luxfi/indexer`](https://github.com/luxfi/indexer)
|
|
and [`luxfi/graph`](https://github.com/luxfi/graph) as libraries; embeds the
|
|
[`luxfi/explore`](https://github.com/luxfi/explore) Next.js build via
|
|
`go:embed`.
|
|
|
|
```
|
|
ghcr.io/luxfi/explorer
|
|
-> indexes one or more EVM chains (luxfi/indexer)
|
|
-> exposes per-chain GraphQL (luxfi/graph)
|
|
-> serves embedded SPA + REST API (luxfi/explore)
|
|
```
|
|
|
|
## Routes
|
|
|
|
| Path | Purpose |
|
|
|---------------------------------------------------|----------------------------------|
|
|
| `/` | SPA (embedded; SPA-routing fallback) |
|
|
| `/envs.js` | Runtime config `window.ENV = {...}` |
|
|
| `/icon.svg`, `/logo.svg` | Per-host brand assets (disk override) |
|
|
| `/health` | Service health |
|
|
| `/v1/indexer/*` | Default chain explorer API |
|
|
| `/v1/indexer/{slug}/*` | Per-chain explorer API |
|
|
| `/v1/explorer/{slug}/*` | Legacy alias for `/v1/indexer/{slug}` |
|
|
| `/v1/graph/{slug}/{subgraph}/graphql` | Per-chain, per-subgraph GraphQL |
|
|
| `/v1/explorer/admin/chains[/{slug}]` | Runtime registry CRUD |
|
|
| `/v1/explorer/realtime` | WebSocket realtime hub |
|
|
| `/v1/explorer/realtime/stats` | Realtime stats |
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
docker run -p 8090:8090 \
|
|
-v $(pwd)/chains.example.yaml:/etc/explorer/chains.yaml:ro \
|
|
-v explorer-data:/data \
|
|
ghcr.io/luxfi/explorer:latest \
|
|
--config /etc/explorer/chains.yaml
|
|
```
|
|
|
|
Or with compose:
|
|
|
|
```bash
|
|
docker compose up
|
|
```
|
|
|
|
## Configuration
|
|
|
|
`chains.yaml` is the single source of truth. Every aspect of the deploy --
|
|
chains, branding, GraphQL subgraphs, network switcher links -- is per-chain
|
|
customizable. See [`chains.example.yaml`](chains.example.yaml) for the full
|
|
schema.
|
|
|
|
```yaml
|
|
data_dir: /data
|
|
http_addr: :8090
|
|
|
|
brand_default:
|
|
name: Lux Explorer
|
|
coin: LUX
|
|
accent_color: "#5cf"
|
|
|
|
networks:
|
|
- { label: Mainnet, domain: explorer.lux.network, chain_id: 96369 }
|
|
|
|
chains:
|
|
- slug: cchain
|
|
name: Lux C-Chain
|
|
chain_id: 96369
|
|
type: evm
|
|
rpc: https://api.lux.network/v1/chain/C/rpc
|
|
coin: LUX
|
|
enabled: true
|
|
default: true
|
|
|
|
indexer:
|
|
poll_interval: 30s
|
|
|
|
graph:
|
|
enabled: true
|
|
subgraphs:
|
|
- { name: amm, schema: amm, enabled: true }
|
|
|
|
brand:
|
|
name: Lux C-Chain
|
|
accent_color: "#5cf"
|
|
```
|
|
|
|
`$ENV_VAR` substitution in `rpc:` / `ws:` lets one file template every
|
|
network -- mount it read-only and inject secrets via env vars.
|
|
|
|
## Per-Network Customization
|
|
|
|
The same image powers every deploy. To rebrand for a different network:
|
|
|
|
1. Mount a different `chains.yaml`.
|
|
2. Optionally mount `icon.svg` / `logo.svg` at the path referenced by
|
|
`chains.yaml` -- they are read from disk per-request, not embedded.
|
|
3. Set environment variables to fill the `${VAR}` placeholders.
|
|
|
|
No image rebuild needed. The SPA reads chain list and brand at runtime from
|
|
`/envs.js`.
|
|
|
|
## Runtime Registry
|
|
|
|
Chains can be added, updated, and removed at runtime without restart:
|
|
|
|
```bash
|
|
# Add
|
|
curl -X POST http://localhost:8090/v1/explorer/admin/chains \
|
|
-H 'Content-Type: application/json' \
|
|
-d '{"slug":"new","name":"New","chain_id":123,"rpc":"http://node:8545","type":"evm"}'
|
|
|
|
# List
|
|
curl http://localhost:8090/v1/explorer/admin/chains
|
|
|
|
# Remove
|
|
curl -X DELETE http://localhost:8090/v1/explorer/admin/chains/new
|
|
```
|
|
|
|
Adding a chain spawns its indexer + (optional) graph workers; removing
|
|
cancels them and frees the routes.
|
|
|
|
## mDNS Discovery
|
|
|
|
Set `EXPLORER_MDNS=true` to auto-register chains advertised by local Lux
|
|
nodes (`_luxd._tcp`, `_zood._tcp`, `_hanzod._tcp`, `_parsd._tcp`). The
|
|
explorer queries `info.getChains` on the discovered node and registers each
|
|
tracked chain. mDNS-sourced chains never override config-sourced entries.
|
|
|
|
## Storage Layout
|
|
|
|
```
|
|
/data/
|
|
cchain/
|
|
query/indexer.db (SQLite WAL, indexer)
|
|
{zapdb}/ (KV store)
|
|
graph/
|
|
amm/graph.db (SQLite WAL, per-subgraph)
|
|
zoo/
|
|
...
|
|
```
|
|
|
|
Each chain (and each subgraph) owns an isolated SQLite + KV store. WAL is
|
|
optionally streamed to S3 with PQ encryption when `REPLICATE_S3_ENDPOINT`
|
|
is set -- see `luxfi/indexer/daemon`.
|
|
|
|
## Local Build
|
|
|
|
```bash
|
|
# Sibling layout: ~/work/lux/{indexer,graph,explorer}
|
|
cd ~/work/lux/explorer
|
|
go build -o explorer .
|
|
```
|
|
|
|
`go.mod` uses local `replace` directives pointing at `../indexer` and
|
|
`../graph`. Production CI clones all three repos into the same layout
|
|
inside the Docker build.
|
|
|
|
## Endpoints (curl examples)
|
|
|
|
```bash
|
|
curl http://localhost:8090/health
|
|
curl http://localhost:8090/v1/indexer/cchain/blocks/latest
|
|
curl -X POST http://localhost:8090/v1/graph/cchain/amm/graphql \
|
|
-H 'Content-Type: application/json' \
|
|
-d '{"query":"{ swaps(first:5) { id amount0 amount1 } }"}'
|
|
```
|
|
|
|
## Related
|
|
|
|
- [`luxfi/indexer`](https://github.com/luxfi/indexer) -- chain indexer library
|
|
- [`luxfi/graph`](https://github.com/luxfi/graph) -- per-chain GraphQL library
|
|
- [`luxfi/explore`](https://github.com/luxfi/explore) -- Next.js SPA
|