Node.js + Fastify backend for Novatip.
Runtime: Node.js 20, Framework: Fastify 4, Language: TypeScript 5 Database: PostgreSQL 16 + Prisma ORM Cache: Redis 7 + IORedis Auth: Sign-In With Stellar (SIWS) + JWT Email: Resend, QR: qrcode, Events: @novatip/sdk
Prerequisites: Node.js >= 18, Docker + Docker Compose
- Install: npm install
- Copy env: cp .env.example .env
- Start infra: docker compose up -d postgres redis
- Migrate: npm run db:generate && npm run db:migrate
- Dev server: npm run dev (http://localhost:3001)
- Full stack: docker compose up -d
DATABASE_URL (required) - PostgreSQL connection string JWT_SECRET (required) - Secret for signing JWTs TIP_SPLITTER_CONTRACT_ID (required) - Deployed contract ID REDIS_URL - Redis URL (default: redis://localhost:6379) PORT - Server port (default: 3001) STELLAR_NETWORK - testnet | mainnet | local (default: testnet) SOROBAN_RPC_URL - Soroban RPC endpoint HORIZON_URL - Horizon REST endpoint NETWORK_PASSPHRASE - Stellar network passphrase USDC_CONTRACT_ID - USDC Stellar Asset Contract ID INDEXER_START_LEDGER - Ledger to begin indexing from (default: 0) RESEND_API_KEY - Resend API key (skip to disable email) APP_BASE_URL - Frontend base URL (default: http://localhost:3000)
GET /health - Simple liveness ping GET /health/live - Liveness (process up, no dependency checks) GET /health/ready - Readiness (PostgreSQL + Redis reachable; 503 if not)
POST /auth/challenge - Issue one-time sign-in nonce POST /auth/verify - Verify signature, return JWT GET /auth/me - Current user (JWT)
GET /creators/:slug - Public creator profile GET /creators/check/:slug - Slug availability POST /creators/claim - Claim a slug (JWT) PATCH /creators/me - Update profile (JWT) PATCH /creators/me/splits - Update splits (JWT)
GET /qr/:slug - QR code SVG GET /qr/:slug/png - QR code PNG download GET /resolve/:slug - Full tip-page data
GET /analytics/totals - Total tips, amount, supporters (JWT) GET /analytics/timeseries - Daily breakdown ?days=30 (JWT) GET /analytics/top-supporters- Ranked supporters ?limit=10 (JWT) GET /analytics/recent - Live tip feed ?limit=20 (JWT)
GET /webhooks - List webhooks (JWT) POST /webhooks - Register webhook (JWT) DELETE /webhooks/:id - Remove webhook (JWT)
Polls Soroban RPC every 6s for TipReceived events, persists to PostgreSQL, dispatches webhooks, sends email notifications. Resumes from IndexerCursor.
Header: X-Novatip-Signature: sha256= Verify: createHmac("sha256", secret).update(body).digest("hex")
npm run dev - hot reload npm run build - compile TypeScript npm run start - run compiled output npm run typecheck - tsc --noEmit npm run lint - eslint npm run db:generate - regenerate Prisma client npm run db:migrate - apply migrations (dev) npm run db:migrate:deploy - apply migrations (production) npm run db:studio - open Prisma Studio
MIT