Production-ready payment orchestration engine for Dorisio, built with Fastify, Stellar integration, and enterprise-grade infrastructure for managing tips, payouts, and creator analytics.
- Payment Engine: Handles tip creation, Stellar transaction submission, and payout orchestration
- Background Job Queues: BullMQ + Redis for async processing (Stellar confirmation polling, webhook dispatch)
- Webhook System: Event-driven architecture with HMAC-SHA256 signing and exponential backoff retries
- Analytics Layer: Real-time creator earnings, supporter tracking, and tip frequency analysis
- Admin/Moderation: Wallet flagging, account freezing, and compliance controls
- Metrics & Monitoring: Prometheus endpoints for production observability
- Node.js 20+
- PostgreSQL 14+
- Redis 6+
# Install dependencies (use pnpm as specified in package.json)
pnpm install
# Set up environment variables
cp .env.example .env
# Run database migrations
pnpm run prisma:migrate
# Start development server
pnpm run devServer runs on http://localhost:3000
For the full Docker, environment, migration, seeding, IDE, debugging, and testing workflow, see SETUP.md, IDE.md, DEBUGGING.md, and TESTING.md.
The quickest reproducible setup is:
make setuppnpm run build # Compile TypeScript
pnpm run test # Run test suite
pnpm run test:watch # Run tests in watch mode
pnpm run lint # Check code style
pnpm run format # Format code with Prettierpnpm run prisma:migrate # Run pending migrations
pnpm run prisma:generate # Generate Prisma client
pnpm run prisma:studio # Open Prisma Studio UIAsynchronous job processing for long-running operations:
- Stellar Confirmation Polling: Polls blockchain for transaction confirmation with exponential backoff (5 retries, 2-32s delays)
- Webhook Dispatch: Delivers webhook events with retry logic and delivery tracking
Files: src/lib/queue.ts, src/lib/workers/*
Event-driven integration for creators' external systems:
Features:
- Event filtering (tip.created, tip.confirmed, tip.failed, payout.completed)
- HMAC-SHA256 signature verification
- Exponential backoff retries (max 5 attempts)
- Delivery history tracking
Endpoints:
POST /api/v1/webhooks- Register webhookGET /api/v1/webhooks- List webhooksDELETE /api/v1/webhooks/:id- Delete webhookGET /api/v1/webhooks/:id/history- Delivery history
Files: src/domains/webhooks/*
Real-time insights into creator earnings and supporter engagement:
Endpoints:
GET /api/v1/analytics/summary- Total earnings, tip count, unique supporters, average tipGET /api/v1/analytics/earnings?days=30- Daily earnings breakdown (customizable period)GET /api/v1/analytics/supporters?limit=10- Top supporters by amount (max 100)GET /api/v1/analytics/frequency?days=30- Tip frequency statistics (avg/min/max/daily)
Features:
- Queries use Prisma aggregations (no raw SQL)
- Per-creator data isolation
- Configurable time windows (1-365 days)
Files: src/domains/analytics/*
Compliance and fraud prevention controls:
Endpoints:
POST /api/v1/admin/wallets/:address/flag- Flag wallet as suspicious (severity: low/medium/high/critical)POST /api/v1/admin/wallets/flags/:flagId/resolve- Resolve wallet flagPOST /api/v1/admin/creators/:creatorId/freeze- Freeze account pending review (optional duration in hours)POST /api/v1/admin/creators/freezes/:freezeId/resolve- Unfreeze accountGET /api/v1/admin/moderation- View moderation queue (active flags and freezes)
Features:
- Admin-only access (role='ADMIN')
- Flagged wallets prevent payment processing
- Frozen accounts block tip intake
- Severity levels and reason tracking
Files: src/domains/admin/*
Prometheus-compatible metrics for production monitoring:
Endpoints:
GET /metrics- Prometheus text format (scrape this for monitoring)GET /metrics/json- JSON format for alternative tooling
Tracked Metrics:
- Counters: Total tips, payments, webhooks, auth attempts
- Gauges: Active tips, confirmed tips, total users, total creators, queue length, total earnings
- Histograms: Request latency, database query latency, webhook delivery latency
Files: src/lib/metrics.ts, src/routes/metrics.routes.ts
Every route is rate limited by class (public 100/min, authenticated 300/min
per user, sensitive 10/min). Health probes are exempt. Classes, limits and
exemptions are configured centrally in src/config/rate-limit.ts, and 429
responses carry X-RateLimit-* and Retry-After headers. Set TRUST_PROXY
when running behind a reverse proxy.
Files: src/config/rate-limit.ts, src/plugins/rateLimit.ts
POST /api/v1/auth/register- Create accountPOST /api/v1/auth/login- Get JWT tokenPOST /api/v1/auth/refresh- Refresh tokenPOST /api/v1/auth/wallet- Wallet authentication
POST /api/v1/tips- Create tip (async → Stellar submission → confirmation polling)GET /api/v1/tips/:id- Get tip statusPOST /api/v1/payments/confirm- Confirm payment via hash
POST /api/v1/creators- Register creatorGET /api/v1/creators/:id- Get creator profilePOST /api/v1/creators/payout- Request payoutGET /api/v1/creators/payout/history- View past payouts
- See Webhook System section above
- See Analytics Endpoints section above
- See Admin & Moderation Layer section above
GET /health- Enhanced health check (DB status, uptime, memory usage, Node.js version)GET /metrics- Prometheus metricsGET /metrics/json- JSON metrics
Comprehensive test suite included. See INFRASTRUCTURE_TEST_PLAN.md for detailed test scenarios covering:
- BullMQ queue initialization and job processing
- Stellar confirmation polling with retry logic
- Webhook dispatch and delivery retries
- Analytics query accuracy and data isolation
- Admin operations and access control
- Metrics endpoint format validation
Run tests with:
npm run testAll configuration is centralized and validated at startup (issue #60).
Every variable is declared in a single Zod schema (src/config/schema.ts),
validated when the process boots, and fails fast with a readable list of all
problems — missing keys, wrong types, out-of-range values — before the server
listens.
- Full reference: docs/CONFIGURATION.md — every variable with type, default, range, secret flag and hot-reload behavior.
- Template:
.env.example— copy to.env(git-ignored) and fill in real values. - Per-environment defaults:
.env.development,.env.staging,.env.production— selected byNODE_ENV; real environment variables always win.
Key variables:
# Server
NODE_ENV=development|staging|production|test
LOG_LEVEL=debug|info|warn|error
PORT=3000
# Database
DATABASE_URL=postgresql://user:pass@host:5432/dorisio
# Stellar
STELLAR_NETWORK=testnet|mainnet
STELLAR_HORIZON_URL=https://horizon-testnet.stellar.org
STELLAR_SERVER_SECRET_KEY=...
# Redis (pools, rate limiting, queues)
REDIS_URL=redis://localhost:6379
# JWT
JWT_SECRET=<32+ chars in production>
JWT_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d
# Reverse proxy / rate limiting (see docs/RATE_LIMITING.md)
TRUST_PROXY=false|<hop count>|<proxy IPs/CIDRs>
RATE_LIMIT_ENABLED=true
RATE_LIMIT_STORE=memory|redis
Secrets may reference the environment or a secrets provider with
{{ SECRET_NAME }} syntax (an unresolved reference aborts startup):
DATABASE_URL={{ DATABASE_URL }}
JWT_SECRET={{ JWT_SECRET }}
Feature flags toggle features per environment with FEATURE_* variables
and are read in code via isFeatureEnabled('<name>') from src/config:
FEATURE_EMAIL_VERIFICATION=true
FEATURE_ANALYTICS=true
FEATURE_WEBHOOKS=true
FEATURE_EXPORTS=true
FEATURE_MAINTENANCE_MODE=false
Configuration loads, overrides and hot reloads are recorded in a redacted
audit log (src/config/audit.ts). Non-critical settings can be reloaded
without a restart via reloadConfig(); critical secrets are pinned at boot
by design. See docs/CONFIGURATION.md.
docker build -t dorisio-backend .
docker run -p 3000:3000 --env-file .env dorisio-backenddocker-compose up -dIncludes PostgreSQL and Redis services.
scrape_configs:
- job_name: 'dorisio-backend'
static_configs:
- targets: ['localhost:3000']
metrics_path: '/metrics'
scrape_interval: 30sdorisio_queue_length > 1000- Job queue backlogdorisio_active_tips > 10000- High pending confirmation loaddorisio_request_duration_seconds (p99) > 5- Slow requestsdorisio_webhooks_total{status="failed"} increasing- Webhook failures
- Check Redis connection and BullMQ worker logs
- Verify Stellar network connectivity and RPC endpoint
- Inspect
stellar-confirmationqueue in BullMQ UI
- Check webhook URL is reachable and returning 2xx status
- Verify HMAC-SHA256 signature validation on receiver end
- Review delivery history:
GET /api/v1/webhooks/:id/history - Check
webhook-dispatchqueue status
- Monitor
/metrics/jsonmemory_usage_mb gauge - Check for long-running queries in analytics endpoints
- Review number of active database connections
See CONTRIBUTING.md for guidelines on:
- Branch naming conventions
- Commit message format
- Pull request process
- Code review checklist
See SECURITY.md for:
- Vulnerability reporting process
- Security best practices
- Wallet key management
- Payment processing security
MIT. See LICENSE for details.
- Jobs / workers — see
docs/JOBS.md - CORS & security headers — see
docs/CORS.md - Database indexes — see
docs/INDEXING.md - Query performance — see
docs/QUERY_PERFORMANCE.md(GET /diagnostics/queries/performance,POST /diagnostics/queries/explain) - GraphQL — see
docs/GRAPHQL.md(POST /graphql)