Skip to content

luxfi/explorer

Repository files navigation

Explorer

Single-binary Lux explorer: chain indexer, GraphQL engine, and SPA frontend in one Go process. Imports luxfi/indexer and luxfi/graph as libraries; embeds the 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

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:

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 for the full schema.

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/mainnet/ext/bc/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:

# 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

# 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)

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

About

Lux Explorer

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors