Skip to content
Rewards System

Rewards System

This documentation is automatically synced from the source repository. To contribute, submit a PR there directly.

SUPERSATS — Rewards Server

Built by The Surfer Kids in collaboration with Bitcoin Ekasi, Mossel Bay, South Africa.

Handles Bitcoin reward payouts for the SUPERSATS programme — BoltCard NFC payments via LNURL-W, Lightning address refills via LNURL-P, and batch disbursements triggered by the companion supersats-attendance app at the end of each month.


What it does

  • BoltCard payments (LNURL-W) — NFC card taps resolve to LNURL-withdraw; the server checks the card balance and returns a Lightning invoice for the tap amount
  • Lightning address refills (LNURL-P) — participants can receive sats to their card via a Lightning address (user@yourdomain)
  • Batch payout API — the attendance app calls this at report approval to credit each participant’s card balance with their monthly reward
  • Reserve management — tracks a sats reserve; payouts draw from the reserve with invoice-based top-up when the reserve runs low
  • Admin dashboard — manage cards, view balances, filter by group, monitor transactions
  • Blink integration — connects to the Blink Lightning wallet via GraphQL API for real Bitcoin settlement

Tech stack

LayerTechnology
RuntimeNode.js 20 / Express 4
LanguageTypeScript
DatabaseSQLite via better-sqlite3 (synchronous)
FrontendReact + Vite + Tailwind CSS
BitcoinBlink GraphQL API + WebSocket
DeploymentDocker + GitHub Actions CI

Quick start

# 1. Clone and install
git clone https://github.com/BitcoinEkasi/supersats-rewards
cd supersats-rewards
npm install

# 2. Configure environment
cp .env.example .env
# Edit .env with your values

# 3. Configure Blink credentials
cp blinkapicredentials.example blinkapicredentials
# Edit blinkapicredentials with your Blink API key and wallet ID

# 4. Start the dev server
npm run dev

Environment variables

VariablePurpose
BLINK_API_URLBlink GraphQL endpoint (https://api.blink.sv/graphql)
BLINK_WS_URLBlink WebSocket endpoint (wss://ws.blink.sv/graphql)
BLINK_API_KEYYour Blink API key
BLINK_WALLET_IDYour Blink wallet ID
DOMAINPublic domain of this server (used in LNURL construction)
JWT_SECRET64 random hex chars — signs admin session tokens
DB_PATHPath to the SQLite database file
PORTServer port (default 3001)
ADMIN_USERNAMEAdmin dashboard username
ADMIN_PASSWORDAdmin dashboard password (remove from env after first run)

See .env.example for a full template.

Blink credentials file

In addition to the env vars, create a blinkapicredentials file (see blinkapicredentials.example for the format). This file is gitignored and should never be committed.

Deployment

Ships as a multi-stage Docker image. On push to main, GitHub Actions builds and pushes to GHCR. On the server:

docker compose pull
docker compose up -d

API

The batch payout endpoint used by the attendance app:

POST /api/batch-payout
Authorization: Bearer <BOLT_API_KEY>

All other endpoints follow LNURL protocol specs.

Progressive Web Apps (PWAs)

Two pages are installable as PWAs on Android via Chrome — no app store required.

Balances PWA (/balances)

Shows all participant card balances in a scrollable list with per-participant transaction history. Protected by a passcode set via the BALANCES_PASSCODE env var.

Visit yourdomain.com/balances on Android Chrome and tap Add to Home Screen. Requires the passcode on first open; the session is remembered until the browser session ends.

Card Check PWA (/balance_check)

Tap an NFC BoltCard to instantly see its balance and recent transactions. Requires a device with NFC and Chrome on Android. No authentication — physical card access is the gate.

Visit yourdomain.com/balance_check on Android Chrome and tap Add to Home Screen.

NFC requirement: The Web NFC API is only available in Chrome on Android. The page shows an “unsupported” message on other browsers/platforms.

Customising names and icons

Edit the manifests in src/frontend/public/ and replace the icons in src/frontend/public/icons/ with your own 192×192 and 512×512 PNGs:

PWAManifestIcons
Balancesbalances-manifest.jsonbalances-192.png, balances-512.png
Card Checkbalance-check-manifest.jsoncard-check-192.png, card-check-512.png

Companion project

Card balances are loaded by the supersats-attendance app, which generates monthly reports and calls this server’s batch payout API at approval time.

License

MIT © BitcoinEkasi