Backend services for the ProofStell decentralized competitive gaming platform β a whack-a-mole game on StarkNet with on-chain leaderboards and wallet-based identity.
The backend is a NestJS REST + WebSocket API that:
- Manages game sessions, scores, badges, and challenges
- Integrates with StarkNet smart contracts for minting and on-chain actions
- Handles JWT-based authentication, role-based access control, and token revocation
- Provides real-time leaderboard and game-state updates over Socket.IO
- Emits analytics events to external providers (PostHog, Mixpanel, Plausible, GA)
| Document | Contents |
|---|---|
| ARCHITECTURE.md | Module map, request lifecycle, cross-module contracts, data flows |
| RUNBOOK.md | Env vars, migrations, observability, scheduled jobs, cache, incident checks |
| README-config.md | Centralized config system, TypedConfigService usage |
| SECURITY_CHECKLIST.md | Auth, API, data-storage, and dependency security checklist |
| SECURITY_AUDIT_REPORT.md | Findings from the last security audit |
| CONTRIBUTING.md | Branching strategy, commit conventions, contributor checklist |
See ARCHITECTURE.md for the full module map and data flows.
HTTP / WebSocket Clients
β
NestJS (ThrottlerGuard β AuthGuard β ValidationPipe β Controller β Service)
β β β
PostgreSQL Redis StarkNet
(TypeORM) (Cache + (BlockchainService,
Dist. Lock) MintService,
WalletProviders)
Observability: Winston β Loki Β· Prometheus β Grafana Β· alert.rules.yml β Alertmanager
- NestJS Β· TypeScript
- PostgreSQL + TypeORM
- Redis (cache + distributed locks)
- Socket.IO (real-time gateway)
- StarkNet SDK Β· Soroban SDK
- Passport JWT + bcrypt
- Winston + Prometheus + Loki
- Swagger (
/api/docsin non-production)
npm install
# Copy and fill in required env vars
cp .env.example .env
npm run start:devSee RUNBOOK.md for the full environment variable reference and production startup guide.
See SECURITY_CHECKLIST.md and SECURITY_AUDIT_REPORT.md.
Key controls:
- JWT access tokens (15 min) with refresh tokens (7 days) and server-side revocation
- bcrypt password hashing (12 rounds by default)
- Global
ThrottlerGuard(10 req / 60 s per IP); stricter limits on auth endpoints SecurityHeadersMiddlewareapplies CSP, HSTS, X-Frame-Options, etc. globally- CORS origins are env-driven (
ALLOWED_ORIGINS) β no hardcoded values ValidationPipewithwhitelist: trueon all endpoints- Sensitive fields stripped by
ClassSerializerInterceptor(@Exclude) - Logging redacts passwords, tokens, and other PII fields automatically
The translation module provides first-class locale support with consistent fallback behaviour.
- Default locale: Configured by marking exactly one language record with
isDefault = truein thelanguagestable. - Validation: Endpoints that opt in via
LanguageValidationPipeorLanguageGuardreject unknown or inactive locale codes with HTTP 400. - Lenient endpoints:
TranslationInterceptorandLanguageMiddlewaresilently fall back to the configured default. - Coverage check:
GET /api/v1/translations/:languageCode/missing-translations - Adding a new locale: Insert a
languagesrow, then add translations viaPOST /api/v1/translations/bulk.
ProofStell Backend β Powering decentralized gaming.
- Login/session β
POST /auth/loginβaccess_token(15m) +refresh_token(7d) βPOST /auth/refreshbefore expiry βPOST /auth/logoutor/auth/logout-allto revoke. See ARCHITECTURE.md for the full contract and error payload shape. - Wallet β
connectβsign-message/send-transaction(idempotent viarequestId, chain-validated) βdisconnect. See ARCHITECTURE.md. - Audit logs β every
@AuditLog()-decorated mutation is recorded immutably and queryable atadmin/audit-logs/*(admin-only). See ARCHITECTURE.md.
```bash npm install cp .env.example .env # fill in JWT_SECRET, JWT_REFRESH_SECRET, DATABASE_URL, REDIS_HOST npm run start:dev
curl -X POST localhost:3000/api/v1/auth/register -d '{"email":"a@b.com","password":"..."}' -H 'Content-Type: application/json'
curl -X POST localhost:3000/api/v1/auth/login -d '{"email":"a@b.com","password":"..."}' -H 'Content-Type: application/json'
curl -X POST localhost:3000/api/v1/wallet/connect -H 'Authorization: Bearer <access_token>' -d '{"providerName":"argentx"}' -H 'Content-Type: application/json'
curl -X POST localhost:3000/api/v1/auth/refresh -d '{"refresh_token":"<refresh_token>"}' -H 'Content-Type: application/json' ```
Full interactive Swagger docs (non-production only): GET /api/docs.