jwinterm 00f8057cb5 Fix credits mode payment processing and payout tracking
- Add payout database records: processPayout now inserts into payouts
  table with tx_hash, fee, status, and updates user statistics
- Fix credits deduction: QueueManager game start methods now properly
  call processGameStart() to deduct credits (was being skipped)
- Fix credits_update emission: moved from GameModeManager (no io access)
  to socketHandlers/queueManager where io is available
- Add payment recovery: users who disconnect during payment confirmation
  now get credits recovered automatically on reconnect
- Remove dead handlePaymentDetected method that referenced undefined this.db
2026-01-02 14:19:11 -05:00
2025-04-27 09:03:16 -04:00
2025-12-24 16:45:35 -05:00

Wownerogue

A browser-based roguelike synchronized with Monero (XMR) and Wownero (WOW) block timing. Built with Node.js/Express and Socket.IO for real-time play, optional crypto payments, and automated payouts.

Features

  • Provably fair gaming with pre-game hash commitments
  • Live spectator mode - watch active games in real-time
  • Persistent chat with 30-day history
  • Transaction history - view payment and payout records
  • Multiple game modes: Free play, per-game payments, or credit bundles
  • Configurable difficulty with house edge tuning
  • Automatic wallet RPC integration for payments and payouts

Quick Start

git clone <repository-url>
cd wownerogue/src
npm install
cp .env.example .env  # Edit with your database/wallet settings
npm run db:create     # Initialize PostgreSQL
npm run dev           # Start development server

Open http://localhost:3000 to play.


Game Modes

Mode Cost Payout Description
FREE None None No payments required
PAID_SINGLE 1 WOW/game 2× escape, 3× with treasure Per-run payment
PAID_CREDITS 10 credits/5 WOW Optional Buy credit bundles

When both modes are enabled (ALLOW_MIXED_MODE=true), players with credits can start games instantly without the payment modal.

Difficulty Presets

Preset Dungeon Size Monster Aggression House Win Rate
easy 30×15 Low ~30%
normal 45×22 Medium ~55%
hard 55×28 High ~65%
casino 60×30 Very High ~70%

Set via DIFFICULTY_PRESET in .env. Defaults to casino for paid modes.


Key Features

Provably Fair Gaming

  1. Server generates a random seed and shows its SHA-256 hash before the game
  2. The seed deterministically generates the dungeon layout and positions
  3. After the game, the seed is revealed for verification
  4. Players can verify hash(seed) = commitment to prove no manipulation

Spectator Mode

Click "👁️ Watch Games" to see active games. Spectators receive real-time updates via Socket.IO rooms. Press ESC to exit.

Transaction History

Click "📜 History" to view your payment and payout records. Shows:

  • Total received from payouts
  • Payment history with status and credits received
  • Payout history with multipliers and transaction hashes

Session Persistence

Sessions use an anonymous token stored in localStorage:

  • ✅ Persists across refreshes, browser closes, server restarts
  • ⚠️ Lost when clearing cookies/localStorage, using incognito mode, or switching browsers/devices

A warning appears if localStorage is unavailable.


API Reference

Public Endpoints

Endpoint Description
GET /health Server health, uptime, memory, wallet status
GET /api/game-modes Current modes and pricing
GET /api/user/:socketId/credits User credit balance
GET /api/user/:socketId/payments Payment history (paginated)
GET /api/user/:socketId/payouts Payout history (paginated)
POST /api/user/:socketId/address Set payout address
GET /verify/:gameId Provably fair verification page

Admin Endpoints

Require X-Admin-Key header matching ADMIN_API_KEY env variable.

Endpoint Description
POST /api/admin/refund/payment Refund a payment, deduct credits if applicable
POST /api/admin/credits/adjust Add or remove credits from a user
GET /api/admin/users/search Search users by socket ID or address

Example: Refund a payment

curl -X POST http://localhost:3000/api/admin/refund/payment \
  -H "Content-Type: application/json" \
  -H "X-Admin-Key: your-admin-key" \
  -d '{"paymentId": 123, "reason": "Customer request", "sendFunds": true}'

Example: Adjust credits

curl -X POST http://localhost:3000/api/admin/credits/adjust \
  -H "Content-Type: application/json" \
  -H "X-Admin-Key: your-admin-key" \
  -d '{"socketId": "abc123", "amount": 5, "reason": "Compensation"}'

Socket.IO Events

Client → Server

Event Description
auto_start Start game (uses credits if available)
player_move Move player (direction: 0-3)
request_payment Request payment address
get_active_games List games for spectating
spectate_game Start spectating a game

Server → Client

Event Description
game_start Game initialized with dungeon state
game_update State after movement
game_over Game ended
payment_created Payment address ready
credits_update Credit balance changed
spectator_update Spectated game state

Configuration

Key environment variables (see .env.example for full list):

# Core
NODE_ENV=production
PORT=3000
DIFFICULTY_PRESET=casino

# Payments
PAYMENTS_ENABLED=true
PAYMENT_MODES=direct,credits
DIRECT_GAME_PRICE=100000000000    # 1 WOW in atomic units
CREDITS_PACKAGES='[{"id":"small","credits":10,"price":"500000000000","bonus":0}]'

# Payouts
DIRECT_PAYOUT_ESCAPE=2.0
DIRECT_PAYOUT_TREASURE=3.0

# Wallet RPC (required for paid modes)
PRIMARY_WALLET_ENDPOINT=http://127.0.0.1:34570
WALLET_RPC_USER=user
WALLET_RPC_PASSWORD=password

# Database
DB_HOST=localhost
DB_NAME=wownerogue
DB_USER=your_user
DB_PASSWORD=your_password

# Admin API (generate with: openssl rand -hex 32)
ADMIN_API_KEY=your-secure-key

# Network (Monero only - Wownero only has mainnet)
MONERO_NETWORK=mainnet

Amounts use atomic units: 1 WOW = 10^11 atomic units.


Production Deployment

Checklist

  • Set NODE_ENV=production
  • Configure TLS via reverse proxy (Nginx/Caddy)
  • Set secure database credentials
  • Configure wallet-rpc with authentication
  • Set ADMIN_API_KEY for admin endpoints
  • Firewall: expose only 80/443
  • Protect /admin.html with basic auth
  • Set up database backups
  • Configure log rotation

Create Dedicated User

Create an isolated system user for security:

# Create system user with no login shell and dedicated home
sudo useradd --system --shell /usr/sbin/nologin --home-dir /var/www/wownerogue --create-home wownerogue

# Create .ssh directory for deploy key
sudo mkdir -p /var/www/wownerogue/.ssh
sudo chmod 700 /var/www/wownerogue/.ssh
sudo chown wownerogue:wownerogue /var/www/wownerogue/.ssh

# Create log directory
sudo mkdir -p /var/log/wownerogue
sudo chown wownerogue:wownerogue /var/log/wownerogue

Setup Deploy Key and Clone Repository

Generate an SSH deploy key for the wownerogue user:

# Generate deploy key (as root, since user has no shell)
sudo ssh-keygen -t ed25519 -C "wownerogue-deploy" -f /var/www/wownerogue/.ssh/id_ed25519 -N ""

# Set correct ownership and permissions
sudo chown wownerogue:wownerogue /var/www/wownerogue/.ssh/id_ed25519*
sudo chmod 600 /var/www/wownerogue/.ssh/id_ed25519
sudo chmod 644 /var/www/wownerogue/.ssh/id_ed25519.pub

# Display the public key
sudo cat /var/www/wownerogue/.ssh/id_ed25519.pub

Add the deploy key to GitHub:

  1. Go to your repository → Settings → Deploy keys
  2. Click Add deploy key
  3. Paste the public key from the command above
  4. Leave "Allow write access" unchecked (read-only is sufficient)
  5. Click Add key

Configure SSH for GitHub:

# Create SSH config for the wownerogue user
sudo tee /var/www/wownerogue/.ssh/config << 'EOF'
Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes
    StrictHostKeyChecking accept-new
EOF

sudo chown wownerogue:wownerogue /var/www/wownerogue/.ssh/config
sudo chmod 600 /var/www/wownerogue/.ssh/config

Clone the repository:

# Clone as the wownerogue user (replace YOUR_USERNAME with your GitHub username)
sudo -u wownerogue git clone git@github.com:YOUR_USERNAME/wownerogue.git /var/www/wownerogue/app

Install Node.js

Install Node.js LTS using NodeSource (run as root):

# Install Node.js 22.x LTS (or check https://nodejs.org for current LTS)
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt-get install -y nodejs

# Verify installation
node --version
npm --version

Install dependencies and audit for vulnerabilities:

cd /var/www/wownerogue/app/src
sudo -u wownerogue npm install

# Check for known vulnerabilities
sudo -u wownerogue npm audit

# Auto-fix vulnerabilities where possible
sudo -u wownerogue npm audit fix

To update the deployment later:

cd /var/www/wownerogue/app
sudo -u wownerogue git pull
cd src && sudo -u wownerogue npm install
sudo -u wownerogue npm audit fix
sudo systemctl restart wownerogue

Set File Permissions

# Set ownership of application files
sudo chown -R wownerogue:wownerogue /var/www/wownerogue

# Restrict permissions (owner only, no world access)
sudo chmod 750 /var/www/wownerogue
sudo chmod 640 /var/www/wownerogue/app/src/.env

Database permissions - create a restricted PostgreSQL role:

-- Create role with minimal privileges
CREATE USER wownerogue WITH PASSWORD 'secure-password-here';
CREATE DATABASE wownerogue OWNER wownerogue;

-- Revoke dangerous permissions
REVOKE CREATE ON SCHEMA public FROM wownerogue;

-- Grant only what's needed
GRANT CONNECT ON DATABASE wownerogue TO wownerogue;
GRANT USAGE ON SCHEMA public TO wownerogue;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO wownerogue;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO wownerogue;

Filesystem isolation (optional, for extra hardening):

# Prevent the user from accessing other users' home directories
sudo chmod 700 /home/*

# Mount application directory with noexec for uploads (if applicable)
# Add to /etc/fstab if using separate partition

systemd Service

Save to /etc/systemd/system/wownerogue.service:

[Unit]
Description=Wownerogue Game Server
After=network.target postgresql.service

[Service]
Type=simple
User=wownerogue
Group=wownerogue
# Adjust paths if you cloned to a different location
WorkingDirectory=/var/www/wownerogue/app/src
EnvironmentFile=/var/www/wownerogue/app/src/.env
ExecStart=/usr/bin/node index.js
Restart=on-failure
RestartSec=10

# Security hardening
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ReadWritePaths=/var/www/wownerogue /var/log/wownerogue

[Install]
WantedBy=multi-user.target

Then enable and start:

# Create .env from example first!
sudo -u wownerogue cp /var/www/wownerogue/app/src/.env.example /var/www/wownerogue/app/src/.env
sudo vim /var/www/wownerogue/app/src/.env  # Edit with your settings

# Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable wownerogue
sudo systemctl start wownerogue
sudo systemctl status wownerogue

The systemd hardening options:

  • NoNewPrivileges - prevents privilege escalation
  • ProtectSystem=strict - mounts filesystem read-only except allowed paths
  • ProtectHome=yes - hides /home, /root, /run/user
  • PrivateTmp=yes - isolates /tmp
  • ReadWritePaths - whitelists writable directories

Reverse Proxy (Nginx Proxy Manager)

If using Nginx Proxy Manager:

  1. Add Proxy Host

    • Domain Names: yourdomain.com
    • Scheme: http
    • Forward Hostname/IP: Your server's LAN IP (e.g., 192.168.1.100)
    • Forward Port: 3000
    • Enable "Websockets Support" toggle
  2. SSL Tab

    • Request a new SSL certificate
    • Enable "Force SSL"
  3. Advanced Tab - Paste this config for WebSocket support:

location /socket.io/ {
    proxy_pass http://192.168.1.100:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_read_timeout 86400s;
    proxy_send_timeout 86400s;
}

Testing

cd src
npm test

Tests cover payment handlers, wallet RPC, security rules, movement logic, and integration flows.


Project Structure

src/
├── index.js                 # Entry point
├── config/                  # Payment config, validation
├── db/                      # PostgreSQL layer
├── game/                    # Dungeon, player, monster logic
├── network/                 # Socket handlers, chat, queue, spectator
├── payments/                # Wallet RPC, QR codes
└── utils/                   # Errors, memory management
html/
├── index.html               # Game client
├── admin.html               # Admin dashboard
└── js/                      # Frontend modules
test/
└── *.test.js                # Jest tests

License

See LICENSE file for details.

S
Description
Mirror of github.com/Such-Software/wownerogue
Readme MIT
8.4 MiB
Languages
JavaScript 92.2%
HTML 4.2%
PLpgSQL 2.3%
CSS 0.8%
Shell 0.4%
Other 0.1%