Rewards System
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
| Layer | Technology |
|---|---|
| Runtime | Node.js 20 / Express 4 |
| Language | TypeScript |
| Database | SQLite via better-sqlite3 (synchronous) |
| Frontend | React + Vite + Tailwind CSS |
| Bitcoin | Blink GraphQL API + WebSocket |
| Deployment | Docker + 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 devEnvironment variables
| Variable | Purpose |
|---|---|
BLINK_API_URL | Blink GraphQL endpoint (https://api.blink.sv/graphql) |
BLINK_WS_URL | Blink WebSocket endpoint (wss://ws.blink.sv/graphql) |
BLINK_API_KEY | Your Blink API key |
BLINK_WALLET_ID | Your Blink wallet ID |
DOMAIN | Public domain of this server (used in LNURL construction) |
JWT_SECRET | 64 random hex chars — signs admin session tokens |
DB_PATH | Path to the SQLite database file |
PORT | Server port (default 3001) |
ADMIN_USERNAME | Admin dashboard username |
ADMIN_PASSWORD | Admin 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 -dAPI
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:
| PWA | Manifest | Icons |
|---|---|---|
| Balances | balances-manifest.json | balances-192.png, balances-512.png |
| Card Check | balance-check-manifest.json | card-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