This guide explains how to run the Lance platform locally, validate background workers, and check system health and sync status.
- Frontend: Next.js app in
apps/web - Backend API: Axum service in
backend - Postgres: backing store for jobs, disputes, and indexer checkpoints
- Workers:
- Judge worker for dispute automation
- Soroban indexer worker for ledger event ingestion
- Node.js 20+
- Rust stable toolchain
- Docker (recommended for local Postgres)
- A funded Stellar Testnet account if testing real on-chain flows
git clone https://github.com/DXmakers/lance.git
cd lance
cd apps/web
npm install
cd ../..
cargo build -p backendCreate backend env file:
cp backend/.env.example backend/.env
cp backend/.env.example backend/.env.developmentCreate web env file:
cp apps/web/.env.example apps/web/.env.localImportant backend variables:
APP_ENV: optional environment selector (defaults todevelopment). Backend loads.envthen.env.<APP_ENV>and keeps shell-provided vars highest priority.DATABASE_URL: Postgres connection stringSOROBAN_RPC_URLorSTELLAR_RPC_URL: Soroban RPC endpointJUDGE_AUTHORITY_SECRET: signing key used by backend judge/contract actionsESCROW_CONTRACT_ID,JOB_REGISTRY_CONTRACT_ID,REPUTATION_CONTRACT_ID: deployed contract IDs
docker run --rm \
--name lance-postgres \
-p 5432:5432 \
-e POSTGRES_USER=lance \
-e POSTGRES_PASSWORD=lance \
-e POSTGRES_DB=lance \
postgres:16In a second terminal:
cd backend
cargo runOn startup, backend will:
- apply SQL migrations
- start API server on
PORT(default3001) - spawn judge worker
- spawn Soroban indexer worker
In a third terminal:
cd apps/web
npm run devOpen http://localhost:3000.
All endpoints below are prefixed with /api because backend mounts router at /api.
- Liveness:
GET /api/health/live - Readiness:
GET /api/health/ready - Aggregate health:
GET /api/health - Indexer sync status:
GET /api/sync-status - Prometheus metrics:
GET /api/metrics
Examples:
curl -s http://localhost:3001/api/health/live | jq
curl -s http://localhost:3001/api/health/ready | jq
curl -s http://localhost:3001/api/health | jq
curl -s http://localhost:3001/api/sync-status | jq
curl -s http://localhost:3001/api/metrics/api/sync-status includes:
- latest processed ledger
- latest network ledger (when RPC is reachable)
- ledger lag
- configured max allowed lag (
INDEXER_MAX_LEDGER_LAG, default5) - RPC reachability details
To test indexer resilience:
- Start backend normally.
- Temporarily break RPC connectivity (for example, set an invalid
SOROBAN_RPC_URL). - Confirm retries and backoff in backend logs.
- Restore RPC URL.
- Confirm worker resumes from checkpoint in
indexer_statetable.
Useful SQL:
SELECT id, last_processed_ledger, updated_at FROM indexer_state;
SELECT COUNT(*) FROM indexed_events;backendservicepostgresservice- optional
prometheusandgrafanaservices scraping/api/metrics
- Use readiness probe against
/api/health/ready - Use liveness probe against
/api/health/live - Scrape
/api/metricsvia Prometheus annotations or ServiceMonitor - Keep only one indexer instance unless leader election is introduced
- Set resource requests/limits and watch:
- event processing rate
- error count
- sync lag
- Sequence mismatch errors: wait briefly and retry transaction flow
- RPC unreachable: verify
SOROBAN_RPC_URLand firewall rules - DB connection errors: verify
DATABASE_URLand that Postgres is running - Frontend cannot call backend: check CORS and port alignment
- Run backend and frontend together.
- Trigger a job flow from UI.
- Watch toast progress and verify explorer links.
- Check
/api/sync-statusand/api/metricswhile processing events. - Run tests before opening PR:
cargo test -p backend
cd apps/web && npm test